2009-03-08 1 views
1

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

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

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

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

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

EDIT:

Here is an example of the issue.

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, поэтому, возможно, существует такой предел).

я мог бы просто выбивать на него и с реальностью, что не собирается быть строка, которая долго ...

ответ

6

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

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

+1

Несомненно, массив байтов может быть длиннее в случае, когда кодировка составляет> 1 байт/символ. String инкапсулирует массив char [], а не массив byte []. –

+0

уверен, он может быть длиннее. Это никогда не ударит по 2 ГБ. – Alnitak

+0

см. Мое редактирование ... размер не находится под моим контролем вообще ... – TofuBeer

1

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

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

1

Java массивы использовать (Java, то есть подпись) Int для доступа as per the languge spec, так что невозможно иметь String (которая опирается на массив символов) больше, чем Integer.MAX_INT

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

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

0

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

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

Смежные вопросы