如何在 Java 中将文件指针重置到文件开头?
我正在用 Java 编写一个程序,需要比较两个文件中的数据。我必须对照文件 2 的每一行检查文件 1 中的每一行,如果找到匹配项,请将它们写入第三个文件。读到文件 2 的末尾后,如何将指针重置到文件的开头?
public class FiFo {
public static void main(String[] args)
{
FileReader file1=new FileReader("d:\\testfiles\\FILE1.txt");
FileReader file2=new FileReader("d:\\testfiles\\FILE2.txt");
try{
String s1,s2;
while((s1=file1.data.readLine())!=null){
System.out.println("s1: "+s1);
while((s2=file2.data.readLine())!=null){
System.out.println("s2: "+s2);
}
}
file1.closeFile();
file2.closeFile();
}catch (IOException e) {
e.printStackTrace();
}
}
}
class FileReader {
BufferedReader data;
DataInputStream in;
public FileReader(String fileName)
{
try{
FileInputStream fstream = new FileInputStream(fileName);
data = new BufferedReader(new InputStreamReader(fstream));
}
catch (IOException e) {
e.printStackTrace();
}
}
public void closeFile()
{
try{
in.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
I am writing a program in Java that requires me to compare the data in 2 files. I have to check each line from file 1 against each line of file 2 and if I find a match write them to a third file. After I read to the end of file 2, how do I reset the pointer to the beginning of the file?
public class FiFo {
public static void main(String[] args)
{
FileReader file1=new FileReader("d:\\testfiles\\FILE1.txt");
FileReader file2=new FileReader("d:\\testfiles\\FILE2.txt");
try{
String s1,s2;
while((s1=file1.data.readLine())!=null){
System.out.println("s1: "+s1);
while((s2=file2.data.readLine())!=null){
System.out.println("s2: "+s2);
}
}
file1.closeFile();
file2.closeFile();
}catch (IOException e) {
e.printStackTrace();
}
}
}
class FileReader {
BufferedReader data;
DataInputStream in;
public FileReader(String fileName)
{
try{
FileInputStream fstream = new FileInputStream(fileName);
data = new BufferedReader(new InputStreamReader(fstream));
}
catch (IOException e) {
e.printStackTrace();
}
}
public void closeFile()
{
try{
in.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
我相信
RandomAccessFile
是你所需要的。它包含:RandomAccessFile#seek 和RandomAccessFile#getFilePointer。rewind()
是seek(0)
I believe
RandomAccessFile
is what you need. It contains:RandomAccessFile#seek
andRandomAccessFile#getFilePointer
.rewind()
isseek(0)
我认为最好的办法是将文件 1 中的每一行放入
HashMap
中;那么您可以检查文件 2 的每一行是否存在HashMap
中的成员身份,而不是为文件 1 的每一行读取整个文件一次。但是要回答您的问题:如何返回到开头文件,最简单的方法是打开另一个
InputStream
/Reader
。I think the best thing to do would be to put each line from file 1 into a
HashMap
; then you could check each line of file 2 for membership in yourHashMap
rather than reading through the entire file once for each line of file 1.But to answer your question of how to go back to the beginning of the file, the easiest thing to do is to open another
InputStream
/Reader
.显然你可以像这样关闭并重新打开文件:
但你真的不想这样做,因为这个算法的运行时间是 O(n2)。如果文件 A 中有 1000 行,文件 B 中有 10000 行,则内部循环将运行 1,000,000 次。
您应该做的是读取每一行并将其存储在一个集合中,该集合允许快速检查是否已包含某个项目(可能是哈希集)。
如果您只需要检查文件 2 中的每一行是否都在文件 1 中,则只需将文件 1 中的每一行添加到 HashSet 中,然后检查文件 2 中的每一行是否都在该集合中。
如果您需要进行交叉比较,找到一个字符串中的每个字符串,但在另一个字符串中找不到,那么您将需要两个哈希集,每个文件一个。 (尽管您可以使用一个技巧来只使用一个)
如果文件太大以至于您没有足够的内存,那么您原来的 n2 方法无论如何都不会起作用。
Obviously you could just close and reopen the file like this:
But you really don't want to do it that way, since this algorithm's running time is O(n2). if there were 1000 lines in file A, and 10000 lines in file B, your inner loop would run 1,000,000 times.
What you should do is read each line and store it in a collection that allows quick checks to see if an item is already contained(probably a HashSet).
If you only need to check to see that every line in file 2 is in file 1, then you just add each line in file one to a HashSet, and then check to see that every line in file 2 is in that set.
If you need to do a cross comparison where you find every string that's in one but not the other, then you'll need two hash sets, one for each file. (Although there's a trick you could do to use just one)
If the files are so large that you don't have enough memory, then your original n2 method would never have worked anyway.
好吧,Gennady S. 的答案就是我用来解决你的问题的答案。
,但是,我不想再次编码。我宁愿使用类似 http://code.google.com/p/java-diff-utils/
well, Gennady S. answer is what I would use to solve your problem.
however, I would rather not code this up again.. I would rather use something like http://code.google.com/p/java-diff-utils/
正如其他人所建议的,您应该考虑解决该问题的其他方法。对于返回文件中前一点的具体问题,
java.io.FileReader
似乎继承mark()
和reset()
方法可实现此目标。不幸的是,markSupported()
返回false
。或者,
BufferedReader
确实支持mark()
。下面的程序打印true
,说明了效果。As others have suggested, you should consider other approaches to the problem. For the specific question of returning to a previous point in a file,
java.io.FileReader
would appear to inheritmark()
andreset()
methods that address this goal. Unfortunately,markSupported()
returnsfalse
.Alternatively,
BufferedReader
does supportmark()
. The program below printstrue
, illustrating the effect.如前所述,还有更好的算法 -
除了这些之外,请调查一下:
FileReader 不实现标记和重置,因此 Trashgod 的评论不准确。
您要么必须实现此版本(使用 RandomAccessFile 或其他),要么包装在 BufferedReader 中。但是,如果您标记它,后者会将整个内容加载到内存中
As noted, there are better algorithms - investigate these
aside:
FileReader doesn't implement mark and reset, so trashgod's comments are inaccurate.
You'd either have to implement a version of this (using RandomAccessFile or what not) or wrap in a BufferedReader. However, the latter will load the whole thing in memory if you mark it
只是一个简单的问题。难道不能将一个对象指向文件的开头并使用另一个对象遍历文件吗?然后,当您到达末尾时,只需将其指向文件(流)开头的对象即可。我相信C++有这样的文件I/O机制(或者是流I/O)
Just a quick Question. can't you keep one object pointed at the start of the file and traverse through the file with another object? Then when you get to the end just point it to the object at the beginning of the file(stream). I believe C++ has such mechanisms with file I/O ( or is it stream I/O)
我相信您只需重新初始化文件 2 文件读取器即可将其重置。
I believe that you could just re-initialize the file 2 file reader and that should reset it.
如果您可以清楚地识别文件的维度,则可以使用BufferedReader类中的mark(int readAheadLimit)和reset() 。
mark(int readAhedLimit) 方法将标记添加到 BufferedReader 的当前位置,您可以使用 reset() 返回到该标记。
使用它们时,您必须小心要读取的字符数,直到reset(),您必须将它们指定为函数mark( int readAhedLimit)。
假设限制为 100 个字符,您的代码应如下所示:
If you can clearly indentify the dimension of your file you can use mark(int readAheadLimit) and reset() from the class BufferedReader.
The method mark(int readAhedLimit) add a marker to the current position of your BufferedReader and you can go back to the marker using reset().
Using them you have to be careful to the number of characters to read until the reset(), you have to specify them as the argument of the function mark(int readAhedLimit).
Assuming a limit of 100 characters your code should look like:
如果您只想将文件指针重置到文件顶部,请重新初始化缓冲区读取器。我假设您还使用 try 和 catch 块来检查文件末尾。
假设这就是您定义缓冲区读取器的方式。现在,您可以通过以下方式检查文件结尾=null。
通过重新初始化缓冲区读取器,您将把文件读取器标记/指针重置到文件顶部,并且不必重新编译文件来将文件读取器标记/指针设置到文件的开头/顶部。
仅当您不想在同一运行中重新编译并完成相同的特技时,才需要重新初始化缓冲区读取器。但是,如果您只想运行一次循环,则不必执行所有这些操作,只需重新编译文件,文件读取器标记将设置为文件的顶部/开头。
If you just want to reset the file pointer to the top of the file, reinitialize your buffer reader. I assume that you are also using the try and catch block to check for end of the file.
Let's say this is how you have your buffer reader defined. Now, this is how you can check for end of file=null.
By reinitializing the buffer reader you will reset the file reader mark/pointer to the top of the file and you won't have to recompile the file to set the file reader marker/pointer to beginning/top of the file.
You need to reinitialize the buffer reader only if you don't want to recompile and pull off the same stunt in the same run. But if you wish to just run loop one time then you don't have to all this, by simply recompiling the file, the file reader marker will be set to the top/beginning of the file.