Frage

Nach einigen verarbeiteten Inhalt an einen Ausgangsstrom auszuschreiben, muss ich den Anfang des Streams zu überdenken und einige Inhalte Metadaten schreiben. Die Daten ich schreibe ist sehr groß, so viel wie 4 GB und können entweder direkt in eine Datei oder auf einen in-Speicherpuffer, in Abhängigkeit von verschiedenen Umweltfaktoren geschrieben werden.

Wie kann ich einen Output implementieren, die mir Header schreiben, können nach dem Schreiben des Inhalts abgeschlossen?

War es hilfreich?

Lösung

Hier ist ein Random Access-Datei-Ausgabestream.

Beachten Sie, dass, wenn es für eine große Menge von gestreamten Ausgabe unter Verwendung sie vorübergehend in einem BufferedOutputStream wickeln kann zu vermeiden viele kleine Schreibvorgänge (nur sehr sicher, dass es zu spülen, bevor die Verpackung oder mit dem zugrunde liegenden Stream direkt verworfen).

import java.io.*;

/**
 * A positionable file output stream.
 * <p>
 * Threading Design : [x] Single Threaded  [ ] Threadsafe  [ ] Immutable  [ ] Isolated
 */

public class RandomFileOutputStream
extends OutputStream
{

// *****************************************************************************
// INSTANCE PROPERTIES
// *****************************************************************************

protected RandomAccessFile              randomFile;                             // the random file to write to
protected boolean                       sync;                                   // whether to synchronize every write

// *****************************************************************************
// INSTANCE CONSTRUCTION/INITIALIZATON/FINALIZATION, OPEN/CLOSE
// *****************************************************************************

public RandomFileOutputStream(String fnm) throws IOException {
    this(fnm,false);
    }

public RandomFileOutputStream(String fnm, boolean syn) throws IOException {
    this(new File(fnm),syn);
    }

public RandomFileOutputStream(File fil) throws IOException {
    this(fil,false);
    }

public RandomFileOutputStream(File fil, boolean syn) throws IOException {
    super();

    File                                par;                                    // parent file

    fil=fil.getAbsoluteFile();
    if((par=fil.getParentFile())!=null) { IoUtil.createDir(par); }
    randomFile=new RandomAccessFile(fil,"rw");
    sync=syn;
    }

// *****************************************************************************
// INSTANCE METHODS - OUTPUT STREAM IMPLEMENTATION
// *****************************************************************************

public void write(int val) throws IOException {
    randomFile.write(val);
    if(sync) { randomFile.getFD().sync(); }
    }

public void write(byte[] val) throws IOException {
    randomFile.write(val);
    if(sync) { randomFile.getFD().sync(); }
    }

public void write(byte[] val, int off, int len) throws IOException {
    randomFile.write(val,off,len);
    if(sync) { randomFile.getFD().sync(); }
    }

public void flush() throws IOException {
    if(sync) { randomFile.getFD().sync(); }
    }

public void close() throws IOException {
    randomFile.close();
    }

// *****************************************************************************
// INSTANCE METHODS - RANDOM ACCESS EXTENSIONS
// *****************************************************************************

public long getFilePointer() throws IOException {
    return randomFile.getFilePointer();
    }

public void setFilePointer(long pos) throws IOException {
    randomFile.seek(pos);
    }

public long getFileSize() throws IOException {
    return randomFile.length();
    }

public void setFileSize(long len) throws IOException {
    randomFile.setLength(len);
    }

public FileDescriptor getFD() throws IOException {
    return randomFile.getFD();
    }

} // END PUBLIC CLASS

Andere Tipps

Wenn Sie die Größe des Headers wissen, Sie zunächst einen leeren Header schreiben kannst, dann ist es in Ordnung zu bringen geht mit RandomAccessFile am Ende. Wenn Sie nicht über die Größe des Kopf wissen, dann haben Sie eine grundlegende, dass Dateisysteme im Allgemeinen ist es nicht möglich Daten einzufügen. Sie müssen also eine temporäre Datei schreiben und dann die reale Datei schreiben.

Lucene scheint eine Implementierung zu haben; und die api aussehen ok.

getFilePointer()
void seek(long pos)  

http: //lucene.apache .org / java / 1_4_3 / api / org / apache / Lucene / store / OutputStream.html

Ich denke, sie Random

Eine Möglichkeit wäre Anfangsinhalt zunächst in einen Speicherpuffer zu schreiben, dann Header in ‚echten‘ Ausgabestrom durch flush gepufferter Inhalte gefolgt, und von da an nur an den nicht gepufferten Strom schreiben. Es klingt wie Anfangssegment nicht so lange dauern würde, um vernünftig zu puffern. Wie es die Umsetzung können Sie ByteArrayOutputStream zur Pufferung verwenden, und dann Output Klasse nehmen „echten“ Ausgabe-Stream als Argument; und wechseln Sie einfach zwischen den beiden wie nötig. Sie müssen möglicherweise Output API erweitern, damit für die Festlegung, welche Metadaten zu schreiben ist, wie die Umstellung von gepufferten Modus auslöst.

Wie die anderen Antwort erwähnt, Random würde auch funktionieren, obwohl würde Output nicht umsetzen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top