如何在 Java 中将文件指针重置到文件开头?

发布于 2024-08-20 22:01:40 字数 1294 浏览 4 评论 0原文

我正在用 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

把昨日还给我 2024-08-27 22:01:40

我相信 RandomAccessFile 是你所需要的。它包含:RandomAccessFile#seek 和RandomAccessFile#getFilePointer。

rewind()seek(0)

I believe RandomAccessFile is what you need. It contains: RandomAccessFile#seek and RandomAccessFile#getFilePointer.

rewind() is seek(0)

筱武穆 2024-08-27 22:01:40

我认为最好的办法是将文件 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 your HashMap 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.

倒带 2024-08-27 22:01:40

显然你可以像这样关闭并重新打开文件:

     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()
     }

但你真的不想这样做,因为这个算法的运行时间是 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:

     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.

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.

二手情话 2024-08-27 22:01:40

好吧,Gennady S. 的答案就是我用来解决你的问题的答案。

我正在用 Java 编写一个程序,需要比较 2 个文件中的数据

,但是,我不想再次编码。我宁愿使用类似 http://code.google.com/p/java-diff-utils/

well, Gennady S. answer is what I would use to solve your problem.

I am writing a program in Java that requires me to compare the data in 2 files

however, I would rather not code this up again.. I would rather use something like http://code.google.com/p/java-diff-utils/

驱逐舰岛风号 2024-08-27 22:01:40

正如其他人所建议的,您应该考虑解决该问题的其他方法。对于返回文件中前一点的具体问题, java.io.FileReader 似乎继承 mark()reset() 方法可实现此目标。不幸的是,markSupported() 返回false

或者,BufferedReader 确实支持mark()。下面的程序打印 true,说明了效果。

package cli;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

public class FileReaderTest {

    public static void main(String[] args) {
        try {
            BufferedReader in = new BufferedReader(new InputStreamReader(
                new FileInputStream("src/cli/FileReaderTest.java")));
            in.mark(1);
            int i1 = in.read(); in.read(); in.read();
            in.reset();
            int i2 = in.read();
            System.out.println(i1 == i2);
        } catch (IOException e) {
            e.printStackTrace(System.err);
        }
    }
}

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 inherit mark() and reset() methods that address this goal. Unfortunately, markSupported() returns false.

Alternatively, BufferedReader does support mark(). The program below prints true, illustrating the effect.

package cli;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

public class FileReaderTest {

    public static void main(String[] args) {
        try {
            BufferedReader in = new BufferedReader(new InputStreamReader(
                new FileInputStream("src/cli/FileReaderTest.java")));
            in.mark(1);
            int i1 = in.read(); in.read(); in.read();
            in.reset();
            int i2 = in.read();
            System.out.println(i1 == i2);
        } catch (IOException e) {
            e.printStackTrace(System.err);
        }
    }
}
赏烟花じ飞满天 2024-08-27 22:01:40

如前所述,还有更好的算法 -

除了这些之外,请调查一下:

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

毁我热情 2024-08-27 22:01:40

只是一个简单的问题。难道不能将一个对象指向文件的开头并使用另一个对象遍历文件吗?然后,当您到达末尾时,只需将其指向文件(流)开头的对象即可。我相信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)

放飞的风筝 2024-08-27 22:01:40

我相信您只需重新初始化文件 2 文件读取器即可将其重置。

I believe that you could just re-initialize the file 2 file reader and that should reset it.

荒岛晴空 2024-08-27 22:01:40

如果您可以清楚地识别文件的维度,则可以使用BufferedReader类中的mark(int readAheadLimit)reset()
mark(int readAhedLimit) 方法将标记添加到 BufferedReader 的当前位置,您可以使用 reset() 返回到该标记。

使用它们时,您必须小心要读取的字符数,直到reset(),您必须将它们指定为函数mark( int readAhedLimit)

假设限制为 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();
        }
    }
}

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:

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();
        }
    }
}
梦断已成空 2024-08-27 22:01:40

如果您只想将文件指针重置到文件顶部,请重新初始化缓冲区读取器。我假设您还使用 try 和 catch 块来检查文件末尾。

`//To read from a file. 
      BufferedReader read_data_file = new BufferedReader(new FileReader("Datafile.dat"));'

假设这就是您定义缓冲区读取器的方式。现在,您可以通过以下方式检查文件结尾=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")));
}

通过重新初始化缓冲区读取器,您将把文件读取器标记/指针重置到文件顶部,并且不必重新编译文件来将文件读取器标记/指针设置到文件的开头/顶部。
仅当您不想在同一运行中重新编译并完成相同的特技时,才需要重新初始化缓冲区读取器。但是,如果您只想运行一次循环,则不必执行所有这些操作,只需重新编译文件,文件读取器标记将设置为文件的顶部/开头。

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.

`//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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文