Да, Pattern.match()
займет CharSequence
.
Если ваш ввод уже находится в кодировке, которая использует ровно 2 байта для представления символа без какого-либо «пролога», вам нужно только:
ByteBuffer bb = ...; // acquire memory mapped byte buffer
CharBuffer cb = bb.asCharBuffer(); // get a char[] 'view' of the bytes
... и поскольку CharBuffer
реализует CharSequence
, все готово.
С другой стороны, если вам нужно декодировать байты в какой-то другой набор символов, ваша работа будет исключена, поскольку CharBuffer
не зависит от набора символов, а CharsetDecorder.decode(ByteBuffer)
внутренне выделяет новый CharBuffer
примерно тот же размер, что и входные байты.
То, удастся ли вам избежать использования меньшего буфера, зависит от вашего регулярного выражения и того, что вы хотите сделать с результатами матча. Но основным подходом было бы реализовать CharSequence
и обернуть карту памяти ByteBuffer
, меньший CharBuffer
для «рабочего пространства» и CharsetDecoder
. Вы будете использовать Charset.decode(ByteBuffer,CharBuffer,boolean)
для декодирования байтов «по требованию» и надеетесь, что общее направление сопоставителя регулярных выражений - «вперед», и что интересующий вас ввод состоит из довольно маленьких кусочков.
Как грубое начало:
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;
}
Может быть поучительно завернуть полностью декодированный CharBuffer
в гораздо более простую собственную оболочку CharSequence
и записать, как на самом деле вызываются методы для заданного вами ввода, когда вы запускаете его с большой кучей на ваша коробка разработки. Это даст вам представление, будет ли этот подход работать для вашего конкретного сценария.