2010-02-09 4 views
10

Java에서 2 파일의 데이터를 비교해야하는 프로그램을 작성 중입니다. 파일 2의 각 줄에 대해 파일 1의 각 줄을 확인하고 일치하는 파일을 찾으면 세 번째 파일에 기록해야합니다. 파일 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

Ok - 맞춤법 및 문법을 수행 했으므로 서식을 지정하지 않았습니다. – danben

+0

원래 포스터가 과제를 잘못 해석하고 실제로 요청한 내용이 타락한 'diff'라고 생각합니다. 이 추측은 영업 이익에 의한 이전 질문과 솔루션의 비교 어려움에 근거합니다. – msw

답변

4

가장 좋은 방법은 파일 1의 각 줄을 HashMap에 넣는 것입니다. 파일 1의 각 줄마다 한 번씩 전체 파일을 읽는 대신 파일 2의 각 줄에 HashMap의 멤버십이 있는지 확인할 수 있습니다.

그러나 파일 시작 부분으로 돌아가는 방법에 대한 질문에 대답하려면, 가장 쉬운 방법은 InputStream/Reader을 여는 것입니다.

+1

+1 - 먼저 파일 1을로드하는 것이 훨씬 효율적입니다. 파일이 매우 클 수없는 한. –

11

나는 RandomAccessFile이 무엇을 필요로한다고 생각합니다. 여기에는 RandomAccessFile#seekRandomAccessFile#getFilePointer이 포함됩니다.

rewind()은 나디 S.의 대답은 내가 당신의 문제를 해결하기 위해 사용하는 것이 무엇인가 잘 seek(0)

1

입니다.

내가

그러나이 개 파일

의 데이터를 비교하는 저를 필요로 자바 프로그램을 작성하고, 차라리 차라리 http://code.google.com/p/java-diff-utils/

같은 것을 사용합니다 .. 다시를 코딩 않을 것
+1

GPL 라이센스 유형이 오픈 소스를 사용하는 데 심각한 문제가 될 수 있지만 이러한 종류의 문제를 해결하는 오픈 소스가 있다는 것을 알면 좋습니다. –

+0

@Gennady - 오직 공룡의 땅에서만 :-). 그러나 진지하게, 당신이 GPL에 만족하지 않는다면, 당신은 자신의 비 GPL 라이브러리를 자유롭게 개발할 수 있습니다. –

+0

@Stephen C, 그것은 나인 것이 아니라 회사의 법무 부서입니다 :-)하지만 어쨌든 GPL은 코드가 GPL이되어 많은 경우에 적합하지 않도록 요구합니다. –

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 때문에, 그런 식으로하고 싶지 않아 orithm의 실행 시간은 O (n)입니다. 파일 A에 1000 줄이 있고 파일 B에 10000 줄이 있으면 내부 루프가 1,000,000 번 실행됩니다.

각 행을 읽고 항목이 이미 포함되어 있는지 (즉, HashSet인지) 빠르게 확인할 수있는 모음에 저장해야합니다.

파일 2의 모든 줄이 파일 1에 있는지 확인하기 만하면 파일 1의 각 줄을 HashSet에 추가 한 다음 파일 2의 모든 줄이 그 안에 있는지 확인하십시오 세트.

하나의 문자열에 있지만 다른 하나의 문자열을 찾을 수없는 교차 비교가 필요한 경우 각 파일에 하나씩 두 개의 해시 세트가 필요합니다. (단지 하나만 사용하면 되겠지만)

파일이 너무 커서 메모리가 충분하지 않으면 원본 n 메쏘드는 절대로 작동하지 않을 것입니다.

0

다른 사람들이 제안했듯이 문제에 대한 다른 접근 방법을 고려해야합니다. 파일의 이전 지점으로 돌아가는 특정 질문의 경우 java.io.FileReader은이 목표를 처리하는 mark()reset() 메서드를 상속합니다.언급 한 바와 같이

0

더 나은 알고리즘이 있습니다 -이

따로 조사 :

을 FileReader 마크를 구현하고 재설정하지 않기 때문에 trashgod의 의견은 정확하지 않습니다. RandomAccessFile을 사용하거나 사용하지 않는 버전을 구현하거나 BufferedReader를 랩핑해야합니다. 그러나 후자는 표시를하면 메모리에 모든 것을로드합니다.

0

빠른 질문. 하나의 객체를 파일의 시작 부분으로 향하게하고 다른 객체로 파일을 가로 지르지는 못합니까? 그런 다음 파일의 시작 부분 (스트림)에서 개체를 가리 키도록합니다. 나는 C++이 파일 I/O (또는 스트림 I/O)와 같은 메커니즘을 가지고 있다고 믿는다.

0

나는 파일 2 파일 판독기를 다시 초기화 할 수 있고 재설정해야한다고 생각한다.

0

당신이 명확하게 파일의 차원을 indentify 수 있다면 당신은 클래스 의 BufferedReader에서 마르크 (INT의 readAheadLimit)리셋()를 사용할 수 있습니다. 메서드 mark (int readAhedLimit) BufferedReader의 현재 위치에 마커를 추가하고 reset()을 사용하여 마커로 돌아갈 수 있습니다.

리셋()까지 읽을 수있는 문자의 수에주의는 에있는 그들을 사용하면 기능 마르크의 인수로 지정해야 (readAhedLimit를 INT).

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

방금 ​​파일의 상단에 파일 포인터를 재설정하여 버퍼 리더를 다시 초기화하려면 :

같은 코드가 보일 것입니다 100 자로 제한 가정. try & catch 블록을 사용하여 파일의 끝을 확인한다고 가정합니다.

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

버퍼 판독기를 정의하는 방법을 가정 해 봅시다. 이제는 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"))); 
} 

파일. 동일한 실행에서 동일한 스턴트를 다시 컴파일하고 제거하지 않으려는 경우에만 버퍼 판독기를 다시 초기화해야합니다. 그러나 루프를 한 번 실행하기를 원한다면이 모든 것을 할 필요는 없습니다. 단순히 파일을 다시 컴파일하면 파일 판독기 마커가 파일의 맨 위/맨 처음으로 설정됩니다.

관련 문제