2016-06-15 16 views
1

Ich habe Mainframe-Datei, die größer als 4 GB ist. Ich muss die Daten für jeweils 500 Bytes lesen und verarbeiten. Ich habe versucht, mit Filechannel, aber ich bin immer Fehler mit Meldung Integer.MAX_VALUEDatei lesen> 4GB Datei in Java

überschritten
public void getFileContent(String fileName) { 
    RandomAccessFile aFile = null; 
    FileChannel inChannel = null; 
    try { 
     aFile = new RandomAccessFile(Paths.get(fileName).toFile(), "r"); 
     inChannel = aFile.getChannel(); 
     ByteBuffer buffer = ByteBuffer.allocate(500 * 100000); 
     while (inChannel.read(buffer) > 0) { 
      buffer.flip(); 
      for (int i = 0; i < buffer.limit(); i++) { 
       byte[] data = new byte[500]; 
       buffer.get(data); 
       processData(new String(data)); 
       buffer.clear(); 
      } 
     } 
    } catch (Exception ex) { 
     // TODO 
    } finally { 
     try { 
      inChannel.close(); 
      aFile.close(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

Können Sie mir helfen mit einer Lösung aus?

+4

zeigen die Ausnahme & Stack-Trace – assylias

+0

Sie könnten versuchen, eine 'FileInputStream' mit einem' BufferedInputStream' Verpackung. – venture

+2

Check out this -> http://stackoverflow.com/questions/8076472/why-does-filechannel-map-take-up-to-integer-max-value-of-data Werden Sie Ihnen eine Vorstellung über den Fehler geben erhalten – Techidiot

Antwort

2

Das größte Problem von Ihnen Code ist der

catch (Exception ex) { 
    // TODO 
} 

Teil, der, dass Sie von Ihrem Code geworfen alle Ausnahmen bemerken nicht impliziert. Da in der JRE-Datei keine Fehlermeldung "Integer.Max_VALUE überschritten" angezeigt wird, muss dieses Problem mit der Methode processData verbunden sein.

Es könnte erwähnenswert sein, dass diese Methode Art und Weise mit wiederholten Daten zu oft aufgerufen wird.

Ihre Schleife

for (int i = 0; i < buffer.limit(); i++) { 

bedeutet, dass Sie so oft wiederholen, wie es Bytes im Puffer ist, bis zu 500 * 100000 mal. Sie extrahieren 500 Bytes aus dem Puffer in jeder Iteration, Verarbeitung insgesamt bis zu 500 * 500 * 100000 Bytes nach jeder read, aber da Sie eine falsche buffer.clear(); am Ende der Schleife Körper haben, werden Sie nie eine BufferUnderflowException erleben. Stattdessen werden Sie processData jeden der bis zu 500 * 100000 mal mit dem ersten 500 Bytes des Puffers aufzuzurufen.

Aber die gesamte Konvertierung von Bytes zu String ist unnötig ausführlich und enthält unnötige Kopiervorgänge. Anstatt dies selbst zu implementieren, können und sollten Sie einfach eine Reader verwenden.

Abgesehen davon, macht der Code einen seltsamen Umweg. Es beginnt mit einem Java 7 API, Paths.get, um es zu einem Legacy-File Objekt zu konvertieren, erstellen Sie ein Vermächtnis RandomAccessFile, um schließlich ein FileChannel zu erwerben. Wenn Sie eine Path haben und eine FileChannel möchten, sollten Sie sie direkt über FileChannel.open öffnen. Und natürlich, verwenden Sie eine try(…) { … } Anweisung, um ordnungsgemäße Schließung zu gewährleisten.

Aber, wie gesagt, wenn Sie die Inhalte als String s verarbeiten möchten, können Sie sicher nutzen wollen eine Reader statt:

public void getFileContent(String fileName) { 
    try(Reader reader=Files.newBufferedReader(Paths.get(fileName))) { 
     CharBuffer buffer = CharBuffer.allocate(500 * 100000); 
     while(reader.read(buffer) > 0) { 
      buffer.flip(); 
      while(buffer.remaining()>500) { 
       processData(buffer.slice().limit(500).toString()); 
       buffer.position(buffer.position()+500); 
      } 
      buffer.compact(); 
     } 
     // there might be a remaining chunk of less than 500 characters 
     if(buffer.position()>0) { 
      processData(buffer.flip().toString()); 
     } 
    } catch(Exception ex) { 
     // the *minimum* to do: 
     ex.printStackTrace(); 
     // TODO real exception handling 
    } 
} 

Es gibt kein Problem mit der Verarbeitung von Dateien ist> 4GB, ich es getestet mit einer 8GB Datei. Beachten Sie, dass der obige Code die Codierung UTF-8 verwendet. Wenn Sie das Verhalten Ihrer ursprünglichen Code der Verwendung beibehalten möchten, was Ihr System Standard-Kodierung werden passiert, können Sie die Reader mit

Files.newBufferedReader(Paths.get(fileName), Charset.defaultCharset()) 

stattdessen erstellen.