2009-03-08 4 views
1

java.nio.ByteBufferを介してUTF8ストリングを読み取ろうとしています。サイズはunsinged intで、もちろんJavaにはありません。私は価値を持っているように、値を長く読みました。長さが符号なしのintであるByteBufferからUTF-8ストリングを読み取る

次の問題は、長整数型のバイト配列を作成できないことと、長整数型にキャストすることで署名されることです。

私はまた、バッファ上でlimit()を使ってみましたが、もう一度intで長く動作しません。

私がやっている具体的なことは、UTF8文字列をクラスファイルから読み込むことです。そのため、バッファにはUTF8文字列だけが含まれています。

符号なし整数の潜在的な長さを持つUTF8文字列を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. 

したがって、技術的な観点から、長さ(4バイト、符号なし)完全U4されたクラスファイルの文字列を有することが可能です。

UTF8文字列のサイズに制限がある場合は問題ありません(私はUTF8エキスパートではないため、このような制限があるかもしれません)。

私はちょうどそれにパントし、その長い文字列があるように行っていないという現実で行くことができる...

答えて

6

バイトのあなたの配列が2GB(Javaの正の最大値以上でなければint)、longを符号付きintにキャストする際に問題は発生しません。

バイトのあなたの配列の長さが2GB以上にする必要がある場合は、あなたが間違ったことをやっている、いない、少なくともそれは、JVMのデフォルトの最大ヒープサイズよりも方法の詳細だから...

+1

確かに、エンコーディングが> 1バイト/文字の場合は、バイト配列を長くすることができます。 Stringはbyte []配列ではなく、char []配列をカプセル化します。 –

+0

確かに、もっと長くすることができます。しかし、それは決して2 GBを打つつもりはありません。 – Alnitak

+0

私の編集を参照してください...サイズは私のコントロール下に全くありません... – TofuBeer

1

int型ウォンを締結しましたあなたの主な問題ではない。あなたは40億の長さの弦を持っていたとします。少なくとも4GBのByteBuffer、少なくとも4GBのbyte []が必要です。これを文字列に変換するときは、少なくとも8 GB(文字あたり2バイト)とそれを構築するStringBuilderが必要です。 (少なくとも8 GBの) あなたが必要とするすべて、1つの文字列を処理する24 GB。あなたがたくさんの記憶を持っていても、あなたはこのサイズのストリングをたくさん得られません。

もう1つの方法は、長さを符号付きとして扱い、無署名の場合は、いずれの場合でも文字列を処理するのに十分なメモリがないため、エラーとして扱います。 20億(2^31-1)の長さのStringを扱う場合でも、このようにStringに変換するには12 GBが必要です。

1

Javaの配列は、それが長くInteger.MAX_INT

より(char配列によってバックアップされた)文字列を持つことは不可能ですしかし、たとえそれだけの方法ですので、アクセスas per the languge specのためのint型(Javaの、すなわち署名)を使用します1つのチャンクで処理するにはあまりにも多くの処理能力を必要とします。十分な大きさのStringに遭遇した場合、ほとんどのマシンでOutOfMemoryErrorでプログラムを失敗させます。

あなたがすべきことは、一度に数メガバイトのような実用的なサイズのチャンクで任意の文字列を処理することです。それであなたが対処できるサイズには実際的な制限はありません。

0

私はByteBufferの上にCharSequenceを実装できると思います。そうすれば、文字を扱うほとんどのユーティリティが文字列を実際に期待しているにもかかわらず、 "文字列"がヒープ上にならないようにすることができます。そして、それでも実際にはCharSequenceにも限界があります。これは、サイズがintとして返されることを期待しています。

(論理的には、長さとしてサイズを返す新しいバージョンのCharSequenceを作成できますが、そのCharSequenceの処理に役立つJavaには何もありません。返すにはsubSequence(...)を実装すると便利でしょう。

関連する問題