2010-01-18 5 views
1

Je travaille dans un petit bureau, j'ai une application, elle génère un gros fichier texte avec 14000 lignes;Comment puis-je filtré avec les meilleures performances? (JAVA)

après chaque génération je dois le filtrer et c'est vraiment ennuyeux;

Je veux écrire une application avec java jusqu'à ce que je puisse la gérer le plus rapidement possible.

Aidez-moi s'il vous plaît; J'ai écrit une application avec scanner (bien sûr avec de l'aide :)) mais ce n'est pas bon car c'était très lent;

Par exemple, il est mon fichier:

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) 

et je veux cette sortie (filtre :)

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

quelle solution est la meilleure et la plus rapide que l'autre?

c'est mon code source:

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

} 

Merci beaucoup en effet ...

+0

vous devez poster le code que vous utilisez actuellement, afin que les gens puissent voir pourquoi il est si lent – mportiz08

+0

Quelle est la « logique métier » ici? Qu'est-ce que vous essayez de faire? ce n'est pas clair à partir de l'entrée et de la sortie. –

+0

Pourquoi Java spécifiquement? Je veux dire que c'est correct mais peut ne pas convenir à votre objectif, comme Paul Tomblin l'a déjà signalé. –

Répondre

3

Comme votre code a des problèmes de performances, vous devez d'abord trouver le goulot d'étranglement. Vous pouvez le profiler avec profiler disponible avec IDE que vous utilisez.

Cependant, puisque votre code n'est pas élevé dans le calcul mais IO intensif, à la fois dans le fichier de lecture et de sortie en utilisant System.out.print, c'est là que je vous suggère d'améliorer pour améliorer le fichier IO.

.

Remplacer cette ligne de code

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

.

Avec cette lignes de code

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

Faites nous savoir si cela aide.

.

Comme la solution précédente n'a pas beaucoup aidé, j'ai apporté quelques changements supplémentaires pour améliorer votre code. Vous devrez peut-être corriger les erreurs d'analyse, le cas échéant. J'étais capable d'afficher la sortie de l'analyse de 392832 lignes en 5 secondes environ. La solution d'origine prend plus de 50 secondes.

Chages sont comme ci-dessous:

  1. Utilisation d'StringTokenizer au lieu de Scanner
  2. Utilisation d'BufferedReader pour la lecture du fichier
  3. Utilisation de StringBuilder au tampon de sortie

.

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

} 

.

Mise à jour sur ENSup et MSLH:

Pour moi, il semble que vous avez changé ENSup et MSLH si la déclaration ci-dessous. Vous voyez donc la valeur "MSLH" pour "ENSUP" et vice versa.

} 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

Cher Gladwin Burboz Merci pour votre réponse mais c'est encore très lent. – Freeman

+0

Mike, laissez-moi savoir si la solution ci-dessus est plus rapide. –

+0

Problème avec celui-ci est que si outputBuffer devient trop grand, il peut provoquer OutOfMemoryError. La solution serait de vider la sortie de temps en temps. Les performances pourraient en outre être améliorées par une sortie de rinçage dans un filetage séparé. Je mettrai à jour la solution ci-dessus plus loin si j'ai un peu de temps. –

3

filtrage texte simple est probablement plus facile d'écrire en Perl (mon choix parce que je l'ai utilisé pendant des années) ou Python (ce que je recommande aux nouvelles personnes parce que c'est une langue plus moderne).

+0

+1 Wow, un pirate Perl recommandant Python ... Sérieusement, Python peut vous permettre de vous lancer dans la course. –

+0

Merci mais malheureusement je suis très faible en Perl et je ne connais pas Python: P – Freeman

-1

Plusieurs solutions à un problème similaire en utilisant Java Scanner ou StreamTokenizer ont été récemment discutées here.

+0

Merci pour votre réponse; avec votre code source, il est retourné toutes les données, mais je veux renvoyer juste des informations spécifiques telles que le haut de la page ... – Freeman

+0

Oui, vous devrez filtrer à l'intérieur de la boucle d'analyse. J'ai mis à jour cet exemple pour comparer Scanner et StreamTokenizer. Ce dernier semble être plus rapide dans ce contexte. – trashgod

Questions connexes