Чтение строки UTF-8 из ByteBuffer, где длина - беззнаковое целое - PullRequest
1 голос
/ 08 марта 2009

Я пытаюсь прочитать строку UTF8 через java.nio.ByteBuffer. Размер - это неизменный тип int, которого, конечно, в Java нет. Я прочитал значение в long, так что у меня есть значение.

Следующая проблема, с которой я столкнулся, заключается в том, что я не могу создать массив байтов с long, и приведение его long к int приведет к его подписанию.

Я также пытался использовать limit () в буфере, но опять-таки он работает с int не долго.

Конкретная вещь, которую я делаю, - это чтение строк UTF8 из файла класса, поэтому в буфере содержится больше, чем просто строка UTF8.

Любые идеи о том, как прочитать строку UTF8, которая имеет потенциальную длину беззнакового целого числа из ByteBuffer.

РЕДАКТИРОВАТЬ:

Вот пример вопроса .

SourceDebugExtension_attribute {
       u2 attribute_name_index;
       u4 attribute_length;
       u1 debug_extension[attribute_length];
    }

attribute_name_index
    The value of the attribute_name_index item must be a valid index into the constant_pool table. The constant_pool entry at that index must be a CONSTANT_Utf8_info structure representing the string "SourceDebugExtension".

attribute_length
    The value of the attribute_length item indicates the length of the attribute, excluding the initial six bytes. The value of the attribute_length item is thus the number of bytes in the debug_extension[] item.

debug_extension[]
    The debug_extension array holds a string, which must be in UTF-8 format. There is no terminating zero byte.

    The string in the debug_extension item will be interpreted as extended debugging information. The content of this string has no semantic effect on the Java Virtual Machine.

Таким образом, с технической точки зрения, в файле классов может быть строка, полная длина которой равна u4 (без знака, 4 байта).

Это не будет проблемой, если есть ограничение на размер строки UTF8 (я не эксперт по UTF8, так что, возможно, такое ограничение существует).

Я мог бы просто надуть это и пойти с реальностью, что не будет такой длинной строки ...

Ответы [ 4 ]

6 голосов
/ 08 марта 2009

Если ваш массив байтов не превышает 2 ГБ (наибольшее положительное значение Java int), у вас не возникнет проблем с приведением long обратно в int.

со знаком.

Если ваш массив байтов должен иметь длину более 2 ГБ, вы делаете это неправильно, не в последнюю очередь потому, что это намного больше, чем максимальный размер кучи JVM по умолчанию ...

1 голос
/ 09 марта 2009

Java-массивы используют (Java, то есть подписанный) int для доступа согласно спецификации языка , поэтому невозможно иметь String (которая поддерживается массивом char) длиннее, чем Integer.MAX_INT

Но даже это слишком много для обработки в одном блоке - это полностью снизит производительность и приведет к сбою вашей программы с ошибкой OutOfMemoryError на большинстве машин, если когда-либо встретится достаточно большая строка.

Что вам нужно сделать, так это обработать любую строку в виде кусков разумного размера, скажем, по несколько мегабайт за раз. Тогда нет никаких практических ограничений на размер, с которым вы можете иметь дело.

1 голос
/ 08 марта 2009

Подпись int не будет вашей главной проблемой. Скажем, у вас была строка длиной 4 миллиарда. Вам потребуется ByteBuffer размером не менее 4 ГБ, а байт [] - не менее 4 ГБ. Когда вы конвертируете это в String, вам нужно как минимум 8 ГБ (2 байта на символ) и StringBuilder для его построения. (Не менее 8 ГБ) Все, что вам нужно, 24 ГБ для обработки 1 строки. Даже если у вас много памяти, вы не получите много строк такого размера.

Другой подход состоит в том, чтобы рассматривать длину как подписанную, а если без знака - как ошибку, у вас не будет достаточно памяти для обработки строки в любом случае. Даже для обработки строки длиной 2 миллиарда (2 ^ 31-1) вам потребуется 12 ГБ, чтобы преобразовать ее в строку таким образом.

0 голосов
/ 10 октября 2009

Полагаю, вы могли бы реализовать CharSequence поверх байтового буфера. Это позволит вам не допустить появления вашей «строки» в куче, хотя большинство утилит, которые работают с персонажами, на самом деле ожидают строку. И даже тогда, на самом деле, есть ограничение на CharSequence. Ожидается, что размер будет возвращен как int.

(Теоретически можно создать новую версию CharSequence, которая возвращает размер как long, но в Java нет ничего, что помогло бы вам справиться с этой CharSequence. Возможно, было бы полезно, если бы вы реализовали subSequence (...) чтобы вернуть обычный CharSequence.)

...