Sì, Pattern.match()
avrà un CharSequence
.
Se l'input è già in un set di caratteri che utilizza esattamente 2 byte per rappresentare un carattere senza alcuna 'prologue', è necessario solo:
ByteBuffer bb = ...; // acquire memory mapped byte buffer
CharBuffer cb = bb.asCharBuffer(); // get a char[] 'view' of the bytes
... e dato CharBuffer
implementa CharSequence
, sei fatto.
D'altra parte, se è necessario per decodificare i byte in qualche altro charset, avrete il vostro bel da fare, dal momento che è CharBuffer
charset-agnostico, e CharsetDecorder.decode(ByteBuffer)
assegna internamente un nuovo CharBuffer
o meno le stesse dimensioni della input byte.
O se non sarete in grado di farla franca con un buffer più piccolo dipende un bel po 'sul vostro regex e che cosa si vuole fare con i risultati delle partite. Ma l'approccio di base sarebbe quella di implementare CharSequence
e avvolgere il memory-mapped ByteBuffer
, una più piccola per CharBuffer
'spazio di lavoro', e un CharsetDecoder
. Utilizzerai Charset.decode(ByteBuffer,CharBuffer,boolean)
per decodificare i byte "su richiesta" e sperare che la direzione generale del regex matcher sia "forward" e che l'input a cui sei interessato sia contenuto in blocchi piuttosto piccoli.
Come un inizio difficile:
class MyCharSequence implements CharSequence {
public MyCharSequence(File file, Charset cs, int bufferSize) throws IOException {
FileInputStream input = new FileInputStream(file);
FileChannel channel = input.getChannel();
this.fileLength = (int) channel.size();
this.bytes = channel.map(FileChannel.MapMode.READ_ONLY, 0, fileLength);
this.charBuffer = CharBuffer.allocate(bufferSize);
this.decoder = cs.newDecoder();
}
public int length() {
// ouch! have to decode the lot, even if you don't choose to keep it all handy
}
public char charAt(final int index) {
while (/* not yet decoded target char[] */) {
this.decoder.decode(this.bytes, this.charBuffer, true);
}
// don't assume 2-bytes == a char unless that's true for your charset!
}
public CharSequence subSequence(final int start, final int end) {
// this'll be fun, too
}
private long fileLength;
private MappedByteBuffer bytes;
private CharBuffer charBuffer;
private CharsetDecoder decoder;
}
Potrebbe essere istruttivo per avvolgere una completamente decodificati CharBuffer
in una molto più semplice CharSequence
involucro della propria, e log come i metodi sono effettivamente chiamati per la vostra data di ingresso, quando lo esegui con un grande heap nella tua casella di sviluppo. Questo ti darà un'idea se questo approccio funzionerà per il tuo particolare scenario.
Ho appena scritto una risposta simile e ho visto che l'avevate già pubblicato! – AlexR
Devi essere veloce :-) Inoltre, [http://java.sun.com/developer/technicalArticles/releases/nio/] è utile, specialmente la sezione su "File mappati". –
Ok, quindi posso ottenere un MappedByteBuffer per il file, e quindi fare qualcosa come Charset.defaultCharset(). NewDecoder(). Decode (buffer) - ma questo non creerà una copia del buffer? – Jake