Domanda

Ho un grosso file su cui sto aprendo un FileInputStream. Questo file contiene alcuni file ogni avendo un offset dall'inizio e una dimensione. Inoltre, ho un parser che dovrebbe valutare un file contenuto.

File file = ...; // the big file
long offset = 1734; // a contained file's offset
long size = 256; // a contained file's size
FileInputStream fis = new FileInputStream(file );
fis.skip(offset);
parse(fis, size);

public void parse(InputStream is, long size) {
   // parse stream data and insure we don't read more than size bytes
   is.close();
}

Mi sento come se questa non è una buona pratica. C'è un modo migliore per fare questo, magari usando il buffering?

Inoltre, mi sento come il salto () metodo rallenta il processo di lettura molto.

È stato utile?

Soluzione

Sembra che ciò che si vuole veramente è una sorta di flusso di input "parziale" -. Uno un po 'come lo ZipInputStream, dove hai un flusso all'interno di un flusso

Si potrebbe scrivere da soli, il proxy tutti i metodi di InputStream al flusso di input originale effettuare le regolazioni adatte per offset e il controllo per la lettura oltre la fine del file secondario.

E 'questo il genere di cosa stai parlando?

Altri suggerimenti

In primo luogo, FileInputStream.skip () ha un bug che può rendere il file sotto saltare oltre l'indicatore EOF del file in modo diffidare di quello.

Ho personalmente trovato a lavorare con input / OutputStreams essere un dolore rispetto all'utilizzo FileReader e FileWriter e si sta mostrando il problema principale che ho con loro: la necessità di chiudere i flussi dopo l'utilizzo. Uno dei problemi è che non si può mai essere sicuri se hai chiuso tutte le risorse correttamente a meno che si effettua il codice un po 'troppo prudente in questo modo:

public void parse(File in, long size) {
    try {
        FileInputStream fis = new FileInputStream(in);
        // do file content handling here
    } finally {
        fis.close();
    }
    // do parsing here
}

Questo è ovviamente male, nel senso che ciò porterebbe alla creazione di nuovi oggetti per tutto il tempo che può finire per mangiare un sacco di risorse. Il lato buono di questo è, naturalmente, che il flusso otterrà chiusa anche se il codice di gestione di file genera un'eccezione.

Questo suona come un file nidificato tipica aka problema di file "zip".

Un modo comune per gestire questo è di avere effettivamente un'istanza InputStream separata per ciascun flusso logico annidato. Questi sarebbero eseguire le operazioni necessarie sul flusso phsycial sottostante, e buffer possono essere sia sul flusso sottostante e il flusso logico, a seconda che si adatta meglio. Questo significa che il flusso di logica incapsula tutte le informazioni sul posizionamento nel flusso sottostante.

Si potrebbe Forinstance avere una sorta di metodo factory che avrebbe una firma in questo modo:

List<InputStream> getStreams(File inputFile)

Si potrebbe fare lo stesso con OutputStreams.

Ci sono alcuni dettagli a questo, ma questo può essere abbastanza per voi?

In generale, il codice che apre il file dovrebbe chiudere il file - il parse () la funzione non dovrebbe chiudere il flusso di input, dal momento che è della massima arroganza per poter supporre che il resto del programma non lo farà Volete continuare a leggere altri file contenuti in quello grande.

Si dovrebbe decidere se l'interfaccia a parse () dovrebbe essere solo lo streaming e la lunghezza (con la funzione in grado di assumere che il file sia posizionato correttamente) oppure se l'interfaccia dovrebbe includere l'offset (quindi le prime posizioni di funzione e quindi legge ). Entrambi i modelli sono fattibili. Sarei propenso a lasciare che il parse () fare il posizionamento, ma non è una decisione chiara.

Si potrebbe utilizzare una classe wrapper su un RandomAccessFile - provare questo

Si potrebbe anche provare avvolgendo che in un BufferedInputStream e vedere se le prestazioni migliorano.

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