2009-03-06 19 views
11

Apprendimento di Java, quindi sii gentile, per favore. Idealmente ho bisogno di creare un array di byte che punterà ad una porzione di una matrice più grande:In Java: è dove un modo per creare un sottoarray che punterà a una porzione di un array più grande?

byte[] big = new byte[1000]; 

// C-style code starts 
load(file,big); 

byte[100] sub = big + 200; 

// C-style code ends 

So che questo non è possibile in Java e ci sono due modi di aggirare che vengono in mente e dovrebbe includere:

  1. Ciascuna porzione di copiatura grande in sub scorrendo grande.

  2. O scrittura propria classe che avrà un riferimento grande + compensato + dimensione e attuazione del "sottomatrice" attraverso metodi di accesso utilizzando grande come struttura dati reali sottostante.

Il compito che sto cercando di risolvere è quello di caricare un file in memoria uno poi ottenere l'accesso in sola lettura ai record memorizzati withing il file tramite una classe. La velocità è fondamentale, quindi idealmente mi piacerebbe evitare i metodi di copia o di accesso. E poiché sto imparando Java, mi piacerebbe seguirlo.

Altre alternative che ho? Si prega di fare domande se non ho spiegato abbastanza bene il compito.

+0

Incoerenza: byte [] sub = nuovo byte [100]; riserva spazio per 100 byte ma l'assegnazione sub = big + 200; memorizza solo un puntatore. –

+0

sganslandt, vero. Spostato anche nel codice in stile C. –

risposta

21

La creazione di un array come "vista" di un altro array non è possibile in Java. Ma potresti usare java.nio.ByteBuffer, che è fondamentalmente la classe che suggerisci nel work-around # 2. Ad esempio:

ByteBuffer subBuf = ByteBuffer.wrap(big, 200, 100).slice().asReadOnlyBuffer(); 

Nessuna copia coinvolta (qualche creazione di oggetto, però). Come classe di una biblioteca standard, suppongo anche che ByteBuffer abbia più probabilità di ricevere un trattamento speciale.Ottimizzazioni "JIT" della JVM rispetto a una personalizzata.

1

Dai un'occhiata all'origine di java.lang.String (sarà presente in src.zip o src.jar). Vedrai che hanno una serie di cahr e poi un inizio e una fine. Quindi, sì, la soluzione è usare una classe per farlo.

Here is a link to the source online.

Le variabili di interesse sono:

  • valore
  • compensato
  • conteggio

sottostringa è probabilmente un buon metodo per guardare come punto di partenza.

Se si desidera leggere direttamente dal file, utilizzare la classe java.nio.channels.FileChannel, in particolare il metodo map(), che consente di utilizzare l'I/O mappato in memoria che sarà molto veloce e utilizzerà meno memoria rispetto alla copia in array.

+0

Ricordare l'implementazione String durante la lettura di un file enorme: i metodi substring e split mantengono il riferimento alla stringa originale. Quindi se leggi un file da 1 GB e memorizzi solo la prima parola di ogni riga, lo spazio necessario è ancora 1 GB !!! – pihentagy

3

Se si desidera leggere un file in modo rapido e con accesso a basso livello, controllare la documentazione di java nio. Ecco un esempio da java almanac.

È possibile utilizzare un buffer di byte mappato per navigare all'interno del contenuto del file.

+0

Grazie Miguel, ma sembra che sotto il cofano questa soluzione non ha né 1 né 2 combinati. –

0

Leggere il file nella memoria è un bel culo presto il file è relativamente piccolo. Ma quando devi gestire enormi file, tenerli fuori dalla memoria è un obiettivo molto più desiderato.

MappedByteBuffer è la cosa che stai cercando.

MappedByteBuffer è un buffer di byte diretto il cui contenuto è una regione mappata in memoria di un file. Il contenuto di un buffer di byte mappato può cambiare in qualsiasi momento, ad esempio se il contenuto della regione corrispondente del file mappato viene modificato da questo programma o da un altro. Se tali cambiamenti si verificano e quando si verificano, dipende dal sistema operativo e quindi non specificato.

Problemi correlati