如何在 Java 中将文件指针重置为文件的开头?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2226699/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How Can I Reset The File Pointer to the Beginning of the File in Java?
提问by Shaz
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?
我正在用 Java 编写一个程序,需要我比较 2 个文件中的数据。我必须根据文件 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();
}
}
}
回答by danben
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 your HashMap
rather than reading through the entire file once for each line of file 1.
我认为最好的办法是将文件 1 中的每一行放入一个HashMap
; 那么您可以检查文件 2 的每一行是否属于您的成员,HashMap
而不是为文件 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
.
但是要回答关于如何返回到文件开头的问题,最简单的方法是打开另一个InputStream
/ Reader
。
回答by Gennady Shumakher
I believe RandomAccessFile
is what you need. It contains: RandomAccessFile#seek
and RandomAccessFile#getFilePointer
.
我相信RandomAccessFile
这就是你所需要的。它包含:RandomAccessFile#seek
和RandomAccessFile#getFilePointer
。
rewind()
is seek(0)
rewind()
是 seek(0)
回答by Ryan Fernandes
well, Gennady S. answer is what I would use to solve your problem.
好吧,Gennady S. 答案是我用来解决您的问题的答案。
I am writing a program in Java that requires me to compare the data in 2 files
我正在用 Java 编写一个程序,它要求我比较 2 个文件中的数据
however, I would rather not code this up again.. I would rather use something like http://code.google.com/p/java-diff-utils/
但是,我宁愿不再对此进行编码。我宁愿使用类似http://code.google.com/p/java-diff-utils/ 的东西
回答by Chad Okere
Obviously you could just close and reopen the file like this:
显然,您可以像这样关闭并重新打开文件:
while((s1=file1.data.readLine())!=null){
System.out.println("s1: "+s1);
FileReader file2=new FileReader("d:\testfiles\FILE2.txt");
while((s2=file2.data.readLine())!=null){
System.out.println("s2: "+s2);
//compare s1 and s2;
}
file2.closeFile()
}
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.
但是你真的不想那样做,因为这个算法的运行时间是 O(n 2)。如果文件 A 中有 1000 行,文件 B 中有 10000 行,则您的内部循环将运行 1,000,000 次。
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).
您应该做的是读取每一行并将其存储在一个集合中,该集合允许快速检查是否已经包含一个项目(可能是一个 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.
如果您只需要检查文件 2 中的每一行是否都在文件 1 中,那么您只需将文件 1 中的每一行添加到一个 HashSet,然后检查文件 2 中的每一行是否都在该集合中。
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 n2method would never have worked anyway.
如果文件太大以至于您没有足够的内存,那么您原来的 n 2方法无论如何都不会奏效。
回答by trashgod
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
inherits mark()
and reset()
methods that address this goal.
正如其他人所建议的那样,您应该考虑其他解决问题的方法。对于返回到文件中的前一个点的具体问题,java.io.FileReader
继承mark()
和reset()
解决此目标的方法。
回答by MJB
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
FileReader 没有实现标记和重置,所以trashgod 的评论是不准确的。您要么必须实现此版本(使用 RandomAccessFile 或不使用),要么包装在 BufferedReader 中。但是,如果您标记它,后者会将整个内容加载到内存中
回答by Dark Star1
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)
只是一个快速的问题。你不能让一个对象指向文件的开头并用另一个对象遍历文件吗?然后当你到达最后时,只需将它指向文件(流)开头的对象。我相信 C++ 有这样的文件 I/O 机制(或者它是流 I/O)
回答by GuitarGuruGaming
I believe that you could just re-initialize the file 2 file reader and that should reset it.
我相信您可以重新初始化文件 2 文件阅读器,然后将其重置。
回答by Niles
If you can clearly indentify the dimensionof 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().
如果您可以清楚地识别文件的尺寸,则可以使用BufferedReader类中的mark(int readAheadLimit)和reset()。方法mark(int readAhedLimit)将标记添加到 BufferedReader 的当前位置,您可以使用reset()返回标记。
Using them you have to be carefulto the number of characters to read until the reset(), you have to specify them as the argument of the function mark(int readAhedLimit).
使用它们时,您必须注意在reset()之前要读取的字符数,您必须将它们指定为函数mark(int readAhedLimit) 的参数。
Assuming a limit of 100 characters your code should look like:
假设限制为 100 个字符,您的代码应如下所示:
class MyFileReader {
BufferedReader data;
int maxNumberOfCharacters = 100;
public MyFileReader(String fileName)
{
try{
FileInputStream fstream = new FileInputStream(fileName);
data = new BufferedReader(new InputStreamReader(fstream));
//mark the current position, in this case the beginning of the file
data.mark(maxNumberOfCharacters);
}
catch (IOException e) {
e.printStackTrace();
}
}
public void resetFile(){
data.reset();
}
public void closeFile()
{
try{
in.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
回答by Parth Shah
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.
如果您只想将文件指针重置为文件顶部,请重新初始化您的缓冲区读取器。我假设您也在使用 try 和 catch 块来检查文件的结尾。
`//To read from a file.
BufferedReader read_data_file = new BufferedReader(new FileReader("Datafile.dat"));'
Let's say this is how you have your buffer reader defined. Now, this is how you can check for end of file=null.
假设这就是您定义缓冲区读取器的方式。现在,这就是您可以检查文件结尾是否为空的方法。
boolean has_data= true;
while(has_data)
{
try
{
record = read_data_file.readLine();
delimit = new StringTokenizer(record, ",");
//Reading the input in STRING format.
cus_ID = delimit.nextToken();
cus_name = delimit.nextToken();'
//And keep grabbing the data and save it in appropriate fields.
}
catch (NullPointerException e)
{
System.out.println("\nEnd of Data File... Total "+ num_of_records
+ " records were printed. \n \n");
has_data = false; //To exit the loop.
/*
------> This point is the trouble maker. Your file pointer is pointing at the end of the line.
-->If you want to again read all the data FROM THE TOP WITHOUT RECOMPILING:
Do this--> Reset the buffer reader to the top of the file.
*/
read_data_file = new BufferedReader(new FileReader(new File("datafile.dat")));
}
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.
通过重新初始化缓冲区读取器,您会将文件读取器标记/指针重置为文件顶部,并且您不必重新编译文件以将文件读取器标记/指针设置为文件的开头/顶部。仅当您不想在同一次运行中重新编译和执行相同的特技时,才需要重新初始化缓冲区读取器。但是,如果您只想运行循环一次,那么您不必执行所有这些操作,只需重新编译文件,文件阅读器标记将设置为文件的顶部/开头。