2010-02-09 237 views
10

我正在寫一個Java程序,要求我比較兩個文件中的數據。我必須檢查文件1的每一行對文件2的每一行,如果我找到一個匹配將它們寫入第三個文件。讀完文件2後,如何將指針重置爲文件開頭?如何將文件指針重置爲Java中文件的起始位置?

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(); 
     } 
    } 
} 
+0

好的 - 我做了拼寫和語法,我沒有做格式。 – danben 2010-02-09 04:19:40

+0

我懷疑原始的海報可能會錯誤地解釋這個任務,實際要求的是一個退化的「差異」。這個猜測是基於OP的先前問題和解決方案的比較難度。 – msw 2010-03-19 20:17:21

回答

4

我認爲做的最好的事情將是把每一行從文件1到HashMap;那麼你可以檢查文件2的每一行作爲你的HashMap的成員資格,而不是通過文件1的每行讀取整個文件一次。

但是要回答你如何返回到文件開頭的問題,最簡單的做法是打開另一個InputStream/Reader

+1

+1 - 首先加載文件1效率更高。除非文件可能非常大。 – 2010-02-09 07:18:26

11

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

rewind()seek(0)

1

好,根納季·S.答案是什麼,我會用它來解決你的問題。

我用Java編寫的程序,需要我的數據在2個文件

然而相比,我寧可不要再編寫這件事。我寧願使用類似http://code.google.com/p/java-diff-utils/

+1

很高興知道有一個開源解決這類問題,但GPL許可證類型可能成爲使用它的嚴重問題。 – 2010-02-09 05:23:23

+0

@Gennady - 只有在恐龍之地:-)。但是,嚴重的是,如果您對GPL不滿意,您可以自由開發自己的非GPL庫。 – 2010-02-09 06:02:27

+0

@Stephen C,它不是我,它是公司的法律部門:-)但無論如何,GPL要求你的代碼變成GPL,這在很多情況下是不合適的。 – 2010-02-09 06:09:34

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

但你真的不想這樣做的,因爲這ALG算術運行時間爲O(n )。如果文件A中有1000行,文件B中有10000行,則內部循環將運行1,000,000次。

你應該做的是閱讀每行並將其存儲在一個集合中,該集合允許快速檢查一個項目是否已被包含(可能是一個HashSet)。

如果您只需要檢查文件2中的每一行是否在文件1中,那麼您只需將文件1中的每一行添加到HashSet中,然後檢查文件2中的每一行是否在組。

如果您需要進行交叉比較,您可以找到每個字符串都在一個字符串中,但不在另一個字符串中,那麼您需要兩個哈希集合,每個文件一個哈希集合。 (雖然有一個技巧,你可以做只用一個)

如果文件太大,你沒有足夠的內存,那麼你原來的方法永遠不會工作。

0

如前所述,有更好的算法 - 調查這些

旁白:

的FileReader沒有實現標記和重置,所以trashgod的評論是不準確的。 你必須實現這個版本(使用RandomAccessFile或不是)或包裝在BufferedReader中。但是,如果你標記它,後者將把所有東西加載到內存中。

0

只是一個簡單的問題。你不能讓一個對象指向文件的開頭,並用另一個對象遍歷文件嗎?然後,當你到達最後時,只需將它指向文件開始處的對象(流)即可。我相信C++有這樣的機制與文件I/O(或者它是流I/O)

0

我相信你可以重新初始化文件2文件閱讀器,應該重置它。

0

如果你可以清楚地indentify文件的尺寸可以使用馬克(INT readAheadLimit)復位()從類BufferedReader中。 方法mark(int readAhedLimit)將標記添加到您的BufferedReader的當前位置,並且您可以使用reset()回到標記。

使用他們,你必須小心到的字符數讀,直到復位(),你必須指定它們作爲功能馬克的參數(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(); 
     } 
    } 
} 
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"))); 
} 

通過重新初始化緩衝讀者,您將文件讀取器標記/指針復位到文件的頂部,你將不必重新編譯的文件來設置文件讀取的標記/指針的開始/頂文件。 只有當您不想重新編譯並在同一運行中拉出相同的特技時,您才需要重新初始化緩衝區讀取器。但是如果你只想運行一次循環,那麼你就不必這麼做,只需重新編譯文件,文件讀取器標記就會被設置爲文件的頂部/開始。

相關問題