4

Javaでバイナリファイルを読み込もうとしています。符号なし8ビット値、符号なし16ビット値、および符号なし32ビット値を読み取るメソッドが必要です。これを行うのに最適な(最も速く、見栄えの良いコード)ものは何ですか?私はこれをC++で実行し、次のようなことを実行しました。

uint8_t *buffer;
uint32_t value = buffer[0] | buffer[1] << 8 | buffer[2] << 16 | buffer[3] << 24;

しかし、Javaでは、たとえばbuffer [1]に、左シフトの結果として符号ビットが設定された値が含まれている場合、これは問題を引き起こします。特定の場所で0xA5のみにOR:ingする代わりに、0xFFFFA500などでOR:sを実行すると、上位2バイトが「損傷」します。

私は今このようなコードを持っています:

public long getUInt32() throws EOFException, IOException {
    byte[] bytes = getBytes(4);
    long value = bytes[0] | (bytes[1] << 8) | (bytes[2] << 16) | (bytes[3] << 24);
    return value & 0x00000000FFFFFFFFL;
}

4バイトを変換したい場合0x670xA50x72 0x50結果は、0x5072A567ではなく0xFFFFA567になります。

編集:これはうまくいきます:

public long getUInt32() throws EOFException, IOException {
    byte[] bytes = getBytes(4);
    long value = bytes[0] & 0xFF;
    value |= (bytes[1] << 8) & 0xFFFF;
    value |= (bytes[2] << 16) & 0xFFFFFF;
    value |= (bytes[3] << 24) & 0xFFFFFFFF;
    return value;
}

しかし、これを行うためのより良い方法はありませんか?10ビット演算は、このような単純なものでは「ビット」のように見えます。(私がそこで何をしたかを参照してください)=)

4

2 に答える 2

5

より通常のバージョンでは、最初にバイトが整数として符号なしの値に変換されます。

public long getUInt32() throws EOFException, IOException {
    byte[] bytes = getBytes(4);
    long value = 
        ((bytes[0] & 0xFF) <<  0) |
        ((bytes[1] & 0xFF) <<  8) |
        ((bytes[2] & 0xFF) << 16) |
        ((long) (bytes[3] & 0xFF) << 24);
    return value;
}

ビット演算の数にとらわれないでください。ほとんどの場合、コンパイラはそれらをバイト演算に最適化します。

longまた、符号を避けるためだけに32ビット値を使用するべきではありませんint。ほとんどの場合、符号付きであるという事実を使用して無視することができます。この回答を参照してください。

更新:最上位バイトをlongにキャストする必要があります。そうしないと、最上位ビットが32ビット整数の符号ビットにシフトされ、負になる可能性があるためです。

于 2013-03-03T09:25:06.097 に答える
2

あなたは正しい考えを持っています、私は明白な改善があるとは思いません。java.io.DataInput.readIntスペックを見ると、同じもののコードがあります。それらは<<との順序を切り替え&ますが、それ以外は標準です。

メモリマップト領域を使用しない限りint、配列から一度に読み取る方法はありませんこれは、これにはかなりやり過ぎです。byte

もちろん、最初DataInputStreamに読み取る代わりに直接使用することもできます。byte[]

DataInputStream d = new DataInputStream(new FileInputStream("myfile"));
d.readInt();

DataInputStreamInteger.reverseBytes使用しているエンディアンとは反対のエンディアンで動作するため、いくつかの呼び出しも必要になります。これ以上速くなることはありませんが、よりクリーンです。

于 2012-11-02T22:01:33.300 に答える