Domanda

Lavoro in un piccolo ufficio, ho un'applicazione che genera un grande file di testo con 14000 righe;

dopo ogni generazione devo filtrarlo ed è davvero noioso;

Voglio scrivere un'applicazione con Java finché non sarò in grado di gestirla il prima possibile.

Mi aiuti per favore;Ho scritto un'applicazione con lo scanner (ovviamente con aiuto :)) ma non va bene perché è stato molto lento;

Ad esempio è il mio file:

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)

e voglio questo output (filtro :)

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

quale soluzione è la migliore e la più veloce dell'altra?

è il mio codice sorgente:

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

}

Molte grazie ...

È stato utile?

Soluzione

Poiché il tuo codice presenta problemi di prestazioni, devi prima trovare il collo di bottiglia.Puoi profilarlo con il profiler disponibile con l'IDE che usi.

Tuttavia, poiché il tuo codice non ha un elevato calcolo ma un intenso I/O, sia nella lettura del file che nell'output utilizzando System.out.print, è qui che ti suggerirei di migliorare per migliorare l'IO del file.

.

Sostituisci questa riga di codice

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

.

Con queste righe di codice

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

Facci sapere se questo aiuta.

.

Poiché la soluzione precedente non è stata di grande aiuto, ho apportato alcune ulteriori modifiche per migliorare il tuo codice.Potrebbe essere necessario correggere eventuali errori di analisi.Sono stato in grado di visualizzare l'output dell'analisi di 392832 linee in circa 5 secondi.La soluzione originale richiede più di 50 secondi.

Le modifiche sono le seguenti:

  1. Utilizzo di StringTokenizer anziché scanner
  2. Utilizzo di BufferedReader per leggere file
  3. Utilizzo di StringBuilder per bufferizzare l'output

.

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

}

.

Aggiornamento su ENSUP e MSLH:

A me sembra che tu abbia scambiato ENSUP e MSLH nell'istruzione if come di seguito.Quindi vedi il valore "MSLH" per "ENSUP" e viceversa.

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

Altri suggerimenti

filtraggio di testo semplice è probabilmente più facile da scrivere in Perl (la mia scelta, perché ho usato per anni) o Python (quello che io consiglierei a persone nuove, perché è un linguaggio più moderno).

Diverse soluzioni ad un problema simile utilizzando Java Scanner o StreamTokenizer sono stati recentemente discusso qui .

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top