2012-04-22 2 views
0
read_data = new BufferedReader(new FileReader(args[0])); 
    data_buffer = new StringBuffer(); 

    int i; 

    while(read_data.ready()) 
    {   
     while((i = read_data.read()) != -1) 
     { 
      data_buffer.append((char)i); 
     }   
    } 

    data_buffer.append(System.getProperty("line.separator")); 

내가하려는 것은 전체 .txt 파일을 문자열로 읽고 문자열에 줄 바꿈을 추가하는 것입니다. 그리고 나서 나중에 data_buffer.toString()을 전달하여 새 Scanner를 작성하여이 문자열을 처리 할 수 ​​있습니다. 분명히 정말로 큰 파일에서이 프로세스는 많은 시간이 걸리고, 내가하고 싶은 것은 메모리에 읽어 들인 .txt 파일에 개행을 추가하는 것뿐입니다.메모리에로드 된 파일에 char을 추가하는 가장 빠르고 효율적인 방법은 무엇입니까?

나는 전체적인 생각이 조금 해킹되거나 이상하게 보일 수도 있지만, 더 빠른 방법이 있습니까?

건배 :)

+0

글쎄, 최소한, 재 배열 작업을 최소화하기 위해 파일의 길이 (알 수있는 경우) 또는 최소한 합리적으로 많은 수로 StringBuffer를 초기화하십시오. –

+0

감사합니다. 나는이 링크가 트릭을 정말 잘했음을 발견했다. 그래서 나는 똑같은 것을 궁금해하는 다른 사람들을 위해 다음과 같이한다. http://weblogs.java.net/blog/pat/archive/2004/10/stupid_scanner.html – Chrispy

답변

3

가장 빠른 방법은 무엇인가하지 않는 것입니다.

끝에있는 개행이 필요하지 않은 방식으로 구문 분석 코드를 수정하지 않는 이유는 무엇입니까? 매번 추가 할 경우 코드가 실제로있는 것처럼 작동하도록 코드를 변경할 수 있습니다.

다음으로 시도 할 것은 char로 거대한 String char을 만드는 것을 피하는 것입니다. 실제로는 비용이 많이 들기 때문입니다. InputStream을 기반으로 Scanner을 만들 수 있으며 데이터를 String으로 읽고 구문 분석하는 것보다 훨씬 빠를 것입니다. FileInputStream을 무시하면 파일 끝에 가상 줄 바꿈 문자가 반환되므로 붙여 넣은 문자열이 표시되지 않습니다.

그리고 데이터를 버퍼로 읽어 들일 필요가 있다면 스트림의 배열 기반 read() 메서드를 사용하여 바이트 배열로 읽는 것이 더 나을 것입니다. 바이트 단위보다 훨씬 빠릅니다. 미리 파일의 크기를 알 수 있으므로 여분의 줄 끝 표시를위한 공간을 버퍼에 할당하고 배열에 삽입 할 수 있습니다. StringBuffer을 생성하고 String을 만드는 것과는 대조적으로 버퍼의 전체 복사본이 필요하지 않습니다.

1

결과 파일을 검사기로 전달하는 경우 파일에 대한 읽기 가능 파일을 만들어 스캐너로 보내야합니다. 여기

은 (안된) 예입니다 :

public class NLReader implements Readable { 

    Reader r; 
    boolean atEndOfReader = false; 
    boolean atEnd = false; 

    public NLReader(Reader r) { 
     this.r = r; 
    } 

    public int read(CharBuffer cb) throws IOException { 
     if (!atEndOfReader) { 
      int result = r.read(cb); 
      if (result == -1) { 
       atEndOfReader = true; 
      } else { 
       return result; 
      } 
     } 
     if (!atEnd) { 
      String nl = System.getProperty("line.separator"); 
      cb.append(nl); 
      atEnd = true; 
      return nl.length(); 
     } 

     return -1; 
    } 
} 

이 한 번만 파일을 읽고, 결코 사본은 (당신의 StringBuffer와는 달리 - 그리고 당신의 StringBuilder를 사용해야하는 것은 정말 StringBuffer와의 동기화를 필요로 대신하지 않는 한).

또한 실제 파일을 메모리에로드하지 않으므로 메모리 사용량을 줄일 수 있습니다.

2

내가 무엇을 말할 수 있듯이 실제로는을 시도하면 마지막 줄 끝에 줄 구분 기호가 항상있는 것처럼 보이는 방식으로 파일을 읽는 것입니다.

이 경우 FilterReader의 하위 유형을 구현하여이 작업을 수행 할 수 있으며 문자 스트림 끝에 도달 할 때 여분의 문자를 두 개 또는 "필요하다면"삽입 할 수 있습니다.

이렇게하는 코드는 간단하지 않지만 전체 파일을 메모리에 버퍼링하는 데 드는 시간과 공간을 피할 수 있습니다.

관련 문제