2017-05-04 2 views
-6

Diese Frage ist sehr kurz. Ich habe eine Datei3GB Datei ohne Ausnahme lesen

Datei.trec-3,99 GB und ich las es mit diesem Code:

public class Main { 
    public static void main(String[] args) { 
     byte[] content = null; 
     try { 
      content = Files.readAllBytes(Paths.get("D:", "Videos","Captures","Datei.trec")); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
     System.out.println(content); 
    } 
} 

und dies ist die Ausgabe:

Exception in thread "main" java.lang.OutOfMemoryError: Required array size too large 
    at java.nio.file.Files.readAllBytes(Unknown Source) 
    at Main.main(Main.java:13) 

so ist es eine Option zum Schreiben des Arrays ohne die Ausnahme (FileInputStream ect.)?

+0

Inhalt ist ein Array mit einer begrenzten Größe, die Sie überlaufen .... –

+0

Ich weiß, aber wie sollte ich den Inhalt lesen? – Niton

+3

Sie würden es streamen. Lies ein bisschen Daten, mach was du brauchst, lies das nächste Bit usw. – pandaadb

Antwort

3

Das Problem, dass das Array benötigt, um alle diese Daten zu halten größer als MAX_BUFFER_SIZE, die in java.nio.Files als Integer.MAX_VALUE - 8 definiert ist: Sie können zum Beispiel LineIterator, von Apache Commons verwenden

public static byte[] readAllBytes(Path path) throws IOException { 
     try (SeekableByteChannel sbc = Files.newByteChannel(path); 
      InputStream in = Channels.newInputStream(sbc)) { 
      long size = sbc.size(); 
      if (size > (long)MAX_BUFFER_SIZE) 
       throw new OutOfMemoryError("Required array size too large"); 

      return read(in, (int)size); 
     } 
    } 

Dies ist notwendig, da Arrays durch Ganzzahlen indiziert werden - dies ist das größte Array, das Sie erhalten können.

Sie haben drei Möglichkeiten:

Strom durch die Datei

Das heißt, die Datei öffnen, lesen ein Stück, zu verarbeiten, lesen Sie einen weiteren Brocken, zu verarbeiten, immer wieder, bis Sie‘ Ich bin durch die ganze Sache gegangen.

Java bietet viele Klassen, um dies zu tun: InputStream, Reader, Scanner usw. - sie sind in den meisten einleitenden Java-Kurse und Bücher bereits früh diskutiert. Studiere eins davon.

Beispiel https://stackoverflow.com/a/21706141/7512

Der Nutzen hängt davon ab, Sie etwas zu können, lohnt sich mit einem frühen Teil der Datei zu tun, ohne zu wissen, was kommt. Oft ist das der Fall. In anderen Fällen müssen Sie mehr als einen Durchlauf durch die Datei machen.

Dateiformate sind oft so konzipiert, dass die Verarbeitung in einem einzigen Durchgang erfolgen kann - es ist daher eine gute Idee, Ihre eigenen Dateiformate zu entwerfen.

Ich beachte, dass Ihre Datei eine .trec Datei ist, die ein Bildschirmvideo ist. Video- und Audioformate sind besonders für das Streaming geeignet. Aus diesem Grund können Sie den Start eines YouTube-Videos vor dem Ende des Downloads verfolgen.

Speicherzuordnung

Wenn Sie wirklich um den Inhalt der Datei, um sie zu verarbeiten, müssen springen, können Sie es öffnen, wie ein Speicher Datei abgebildet.

Schauen Sie in der Dokumentation für RandomAccessFile - das gibt Ihnen ein Objekt mit einer seek() Methode, so dass Sie beliebige Punkte in den Daten der Datei lesen können.

Mehreren Arrays Lesen

Ich schließe dies nur der Vollständigkeit; es ist hässlich, die ganze Datei in den Heapspeicher zu schlürfen. Aber wenn Sie wirklich wollen, könnten Sie die Bytes in einer Reihe von Arrays speichern - vielleicht eine List<byte[]>. Java-ish Pseudo-Code:

List<byte[]> filecontents = new ArrayList<byte[]>(); 
    InputStream is = new FileInputStream(...); 
    byte[] buffer = new byte[MAX_BUFFER_SIZE]; 
    int bytesGot = readUpToMaxBufferSizeFrom(file); 
    while(bytesGot != -1) { 
     byte[] chunk = new byte[bytesGot]; 
     System.arrayCopy(buffer, 0, chunk, 0, bytesGot); 
     filecontents.add(chunk); 
    } 

Auf diese Weise können Sie bis zu MAX_BUFFER_SIZE * Integer.MAX_INTEGER Bytes. Der Zugriff auf die Inhalte ist ein wenig komplizierter als die Verwendung eines einfachen Arrays - aber dieses Implementierungsdetail kann in einer Klasse verborgen werden.

Sie würden natürlich müssen Java konfigurieren, dass eine große Heap-Größe zu haben - siehe How to set the maximum memory usage for JVM?

Sie es nicht tun.

+1

Entschuldigung, zunehmende Heap-Größe wird nicht helfen - haben entfernt diesen Teil und erklärte über 'MAX_BUFFER_SIZE' – slim

+0

Danke für die Antwort – Niton

0

Ich würde Ihnen empfehlen, durch die Datei zu streamen; ist

LineIterator it = FileUtils.lineIterator(theFile, "UTF-8"); 
try { 
    while (it.hasNext()) { 
     String line = it.next(); 
    } 
} finally { 
    LineIterator.closeQuietly(it); 
} 
+0

Ich muss den gesamten Inhalt in einer Variabe (Array oder DataType) sammeln – Niton