2010-01-18 6 views
1

저는 작은 사무실에서 일하고 있습니다. 저는 응용 프로그램을 가지고 있으며, 14000 라인의 큰 텍스트 파일을 생성합니다.최상의 성능으로 어떻게 필터링 할 수 있습니까? (JAVA)

각 생성 후에 필자는 그것을 필터링해야하며 정말 지루합니다.

가능한 한 빨리 처리 할 수있을 때까지 Java로 응용 프로그램을 작성하고 싶습니다.

도와주세요. 스캐너로 응용 프로그램을 작성했습니다 (물론 도움이 필요합니다 :)). 그러나 좋지는 않습니다. becase 매우 느립니다. 예를 들어

는 내 파일입니다 :

SET CELL:NAME=CELL:0,CELLID=3; 
SET LSCID:NAME=LSC:0,NETITYPE=MDCS,T32=5,EACT=FILTER-NOFILTER-MINR-FILTER-NOFILTER,ENSUP=GV2&NCR,MINCELL=6,MSV=PFR,OVLHR=9500,OTHR=80,BVLH=TRUE,CELLID=3,BTLH=TRUE,MSLH=TRUE,EIHO=DISABLED,ENCHO=ENABLED,NARD=NAP_STLP,AMH=ENABLED(3)-ENABLED(6)-ENABLED(9) 

나는이 출력 (필터 : 원하는

CELLID : 3 
ENSUP : GV2&NCR 
ENCHO : ENABLED 
MSLH : TRUE 
------------------------ 
Count of CELLID : 2 

하는 솔루션이 최고의 다른 것보다 가장 빠른?

public static void main(String[] args) throws FileNotFoundException { 
     Scanner scanner = new Scanner(new File("i:\\1\\2.txt")); 
     scanner.useDelimiter(";|,"); 
     Pattern words = Pattern.compile("(CELLID=|ENSUP=|ENCHO=)"); 

     while (scanner.hasNextLine()) { 
      String key = scanner.findInLine(words); 

      while (key != null) { 
      String value = scanner.next(); 
      if (key.equals("CELLID=")) 
       System.out.print("CELLID:" + value+"\n"); 
      //continue with else ifs for other keys 
       else if (key.equals("ENSUP=")) 
      System.out.print("ENSUP:" + value+"\n"); 

      else if (key.equals("ENCHO=")) 
      System.out.print("ENCHO:" + value+"\n"); 
      key = scanner.findInLine(words); 
      } 
      scanner.nextLine(); 
     } 

} 

매우 참으로 감사드립니다 ...

+0

명 그것이 – mportiz08

+0

여기에 "비즈니스 로직"이란 무엇입니까 느린 실행 왜 볼 수 있도록 당신이, 당신이 현재 사용하고있는 코드를 게시해야합니까? 당신이하려고하는 것은 무엇입니까? 그것은 입력과 출력으로부터 명확하지 않다. –

+0

Java가 특별히 필요한 이유는 무엇입니까? 폴 톰 블린 (Paul Tomblin)이 이미 지적했듯이, 그 의미는 괜찮지 만 당신의 목적에 부합하지 않을 수도 있습니다. –

답변

3

코드에 성능 문제가 있으므로 먼저 병목 목을 찾아야합니다. 사용하는 IDE로 사용 가능한 프로파일 러로 프로파일 링 할 수 있습니다.

그러나 코드가 System.out.print를 사용하여 파일과 출력을 읽는 데있어 계산량이 많지 않지만 IO가 많이 필요하지 않기 때문에 파일 IO를 개선하기 위해 개선 할 것을 제안합니다.

.

코드

Scanner scanner = new Scanner(new File("i:\\1\\2.txt")); 

이 라인을 교체합니다. 이 코드 라인

File file = new File("i:\\1\\2.txt"); 
BufferedReader br = new BufferedReader(new FileReader(file) ); 
Scanner scanner = new Scanner(br); 

이 도움이되었는지 알려주십시오.

.

이전 솔루션으로 많은 도움을 얻지 못했기 때문에 몇 가지 변경 사항을 적용하여 코드를 개선했습니다. 오류가있는 경우 오류를 해결해야 할 수도 있습니다. 약 5 초 동안 392832 라인의 파싱 결과를 표시 할 수있었습니다. 기존 솔루션은 50 초 이상 걸립니다.

Chages은 다음과 같습니다 : 파일을 모두 StringBuilder의

  • 사용을 읽는 대신 스캐너의 BufferedReader의
  • 이용 있고 StringTokenizer의

    1. 를 사용하여 출력

    버퍼.

    public class FileParse { 
    
        private static final int FLUSH_LIMIT = 1024 * 1024; 
        private static StringBuilder outputBuffer = new StringBuilder(
          FLUSH_LIMIT + 1024); 
        private static final long countCellId; 
    
        public static void main(String[] args) throws IOException { 
         long start = System.currentTimeMillis(); 
         String fileName = "i:\\1\\2.txt"; 
         File file = new File(fileName); 
         BufferedReader br = new BufferedReader(new FileReader(file)); 
         String line; 
         while ((line = br.readLine()) != null) { 
          StringTokenizer st = new StringTokenizer(line, ";|, "); 
          while (st.hasMoreTokens()) { 
           String token = st.nextToken(); 
           processToken(token); 
          } 
         } 
         flushOutputBuffer(); 
         System.out.println("----------------------------"); 
         System.out.println("CELLID Count: " + countCellId); 
         long end = System.currentTimeMillis(); 
         System.out.println("Time: " + (end - start)); 
        } 
    
        private static void processToken(String token) { 
         if (token.startsWith("CELLID=")) { 
          String value = getTokenValue(token); 
          outputBuffer.append("CELLID:").append(value).append("\n"); 
          countCellId++; 
         } else if (token.startsWith("ENSUP=")) { 
          String value = getTokenValue(token); 
          outputBuffer.append("ENSUP:").append(value).append("\n"); 
         } else if (token.startsWith("ENCHO=")) { 
          String value = getTokenValue(token); 
          outputBuffer.append("ENCHO:").append(value).append("\n"); 
         } 
         if (outputBuffer.length() > FLUSH_LIMIT) { 
          flushOutputBuffer(); 
         } 
        } 
    
        private static String getTokenValue(String token) { 
         int start = token.indexOf('=') + 1; 
         int end = token.length(); 
         String value = token.substring(start, end); 
         return value; 
        } 
    
        private static void flushOutputBuffer() { 
         System.out.print(outputBuffer); 
         outputBuffer = new StringBuilder(FLUSH_LIMIT + 1024); 
        } 
    
    } 
    

    . ENSUP 및 MSLH에

    업데이트 : 당신이 다음과 같이 if 문에 ENSUP 및 MSLH을 전환 한 것처럼 나에게

    것 같습니다. 따라서 "ENSUP"값과 "ENSUP"값의 "MSLH"값을 볼 수 있습니다.

    } else if (token.startsWith("MSLH=")) { 
        String value = getTokenValue(token); 
        outputBuffer.append("ENSUP:").append(value).append("\n"); 
    } else if (token.startsWith("ENSUP=")) { 
        String value = getTokenValue(token); 
        outputBuffer.append("MSLH:").append(value).append("\n"); 
    } 
    
  • +0

    친애하는 Gladwin Burboz 답장을 보내 주셔서 감사합니다. 하지만 여전히 매우 느립니다. – Freeman

    +0

    마이크, 위의 해결책이 더 빠르면 알려주세요. –

    +0

    outputBuffer가 너무 커지면 OutOfMemoryError가 발생할 수 있습니다. 해결책은 수시로 출력을 플러시하는 것입니다. 별도의 스레드에서 출력을 플러시하여 성능을 향상시킬 수 있습니다. 내가 약간의 시간이 더 있으면 위의 솔루션을 추가로 업데이트 할 것입니다. –

    3

    간단한 텍스트 필터링 내가 년 동안 그것을 사용하고 있기 때문에 (펄에서 내 선택을 작성하는 것이 더 쉬울 수 있습니다 :

    은 내 소스 코드의) 또는 Python (현대적인 언어이기 때문에 새로운 사람들에게 추천합니다).

    +0

    +1 Perl 해커가 파이썬을 권유하는 와우 ... 심각하게도 Python을 사용하면 게임을 시작할 수 있습니다. –

    +0

    감사합니다.하지만 불행히도 저는 Perl을 매우 약하고 Python을 모른다 : P – Freeman

    -1

    Java Scanner 또는 StreamTokenizer을 사용하여 유사한 문제에 대한 여러 솔루션이 최근에 논의되었습니다. here.

    +0

    답장을 보내 주셔서 감사합니다; 귀하의 소스 코드와 함께, 그것은 모든 데이터를 반환하지만, 페이지의 상단과 같은 특정 정보를 반환하고 싶습니다 ... – Freeman

    +0

    예, 당신은 구문 분석 루프 안에 필터링해야합니다. 이 예제를 Scanner와 StreamTokenizer를 비교하기 위해 업데이트했습니다. 후자는 그 맥락에서 더 빠르다. – trashgod

    관련 문제