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

时间:2010-02-09 04:14:20

标签: java filereader

我正在用Java编写一个程序,要求我比较2个文件中的数据。我必须检查文件1中的每一行与文件2的每一行,如果我找到匹配,则将它们写入第三个文件。在我读到文件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();
        }
    }
}

10 个答案:

答案 0 :(得分:13)

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

rewind()seek(0)

答案 1 :(得分:5)

我认为最好的办法是将文件1中的每一行放入HashMap;那么你可以检查文件2的每一行是否为HashMap的成员资格而不是为每行文件1读取整个文件一次。

但要回答关于如何返回文件开头的问题,最简单的方法是打开另一个InputStream / Reader

答案 2 :(得分:2)

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

     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(n 2 )。如果文件A中有1000行,文件B中有10000行,则内部循环将运行1,000,000次。

您应该做的是读取每一行并将其存储在一个集合中,该集合允许快速检查项目是否已经包含(可能是HashSet)。

如果您只需要检查文件2中的每一行是否在文件1中,那么您只需将文件1中的每一行添加到HashSet中,然后检查文件2中的每一行是否都在该集合中。

如果你需要进行交叉比较,你发现每个字符串都在一个而不是另一个,那么你需要两个哈希集,每个文件一个。 (虽然你可以做一个技巧只使用一个)

如果文件太大而你没有足够的内存,那么原来的n 2 方法无论如何都不会有效。

答案 3 :(得分:1)

好吧,Gennady S.回答是我用来解决你的问题的方法。

  

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

然而,我宁愿不再对此进行编码..我宁愿使用像http://code.google.com/p/java-diff-utils/

这样的东西

答案 4 :(得分:0)

正如其他人所建议的那样,您应该考虑解决问题的其他方法。对于返回文件中上一个点的具体问题,java.io.FileReader会继承mark()reset()方法来解决此问题。

答案 5 :(得分:0)

如上所述,有更好的算法 - 调查这些

除了:

FileReader没有实现标记和重置,因此trashgod的注释不准确。 您要么必须实现此版本(使用RandomAccessFile或不使用)或包装在BufferedReader中。但是,如果你标记它,后者会将整个内容加载到内存中

答案 6 :(得分:0)

只是一个简短的问题。你不能让一个对象指向文件的开头并用另一个对象遍历文件吗?然后,当你到达结束时,只需将其指向文件开头的对象(流)。我相信C ++有这样的文件I / O机制(或者它是流I / O)

答案 7 :(得分:0)

我相信您可以重新初始化文件2文件阅读器,并且应该重置它。

答案 8 :(得分:0)

如果您可以清楚地识别文件的维度,则可以使用 mark(int readAheadLimit) reset()从类< EM>的BufferedReader 。 方法 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();
        }
    }
}

答案 9 :(得分:0)

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

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

让我们说这就是你如何定义缓冲读卡器。现在,这是你可以检查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")));
}

通过重新初始化缓冲区读取器,您将文件读取器标记/指针重置为文件顶部,您不必重新编译文件以将文件读取器标记/指针设置为文件的开头/顶部。 只有在您不想在同一次运行中重新编译和拉出相同的特技时,才需要重新初始化缓冲读取器。但是如果您希望只运行一次循环,那么您不必完成所有这些操作,只需重新编译文件,文件阅读器标记就会设置为文件的顶部/开头。