76

私は次のようなバイナリファイルを読んでいます:

InputStream in = new FileInputStream( file );
byte[] buffer = new byte[1024];
while( ( in.read(buffer ) > -1 ) {

   int a = // ??? 
}

最大4バイトを読み取り、それらからint値を作成するためにやりたいことですが、その方法がわかりません。

一度に4バイトを取得し、1つの「バイト」操作( >> << >> & FF など)を実行して新しいintを作成する必要があるような気がします

これのイディオムは何ですか?

編集

おっと、これはもう少し複雑であることが判明しました(説明するため)

私がやろうとしているのは、ファイル(ASCII、バイナリ、それは問題ではない)を読み取り、それが持つ可能性のある整数を抽出することです。

たとえば、バイナリ コンテンツ (基数 2) があるとします。

00000000 00000000 00000000 00000001
00000000 00000000 00000000 00000010

整数表現はです12ね?:- / 最初の 32 ビットは 1、残りの 32 ビットは 2。

11111111 11111111 11111111 11111111

-1だろう

01111111 11111111 11111111 11111111

だろう Integer.MAX_VALUE ( 2147483647 )

4

12 に答える 12

75

ByteBuffer にはこの機能があり、リトル エンディアンとビッグ エンディアンの両方の整数を処理できます。

次の例を検討してください。


//  read the file into a byte array
File file = new File("file.bin");
FileInputStream fis = new FileInputStream(file);
byte [] arr = new byte[(int)file.length()];
fis.read(arr);

//  create a byte buffer and wrap the array
ByteBuffer bb = ByteBuffer.wrap(arr);

//  if the file uses little endian as apposed to network
//  (big endian, Java's native) format,
//  then set the byte order of the ByteBuffer
if(use_little_endian)
    bb.order(ByteOrder.LITTLE_ENDIAN);

//  read your integers using ByteBuffer's getInt().
//  four bytes converted into an integer!
System.out.println(bb.getInt());

お役に立てれば。

于 2010-03-05T00:25:33.303 に答える
37

それらがすでにbyte[]配列にある場合は、次を使用できます。

int result = ByteBuffer.wrap(bytes).getInt();

ソース:ここ

于 2010-05-15T14:08:46.007 に答える
30

次のような関数に入れる必要があります。

public static int toInt(byte[] bytes, int offset) {
  int ret = 0;
  for (int i=0; i<4 && i+offset<bytes.length; i++) {
    ret <<= 8;
    ret |= (int)bytes[i] & 0xFF;
  }
  return ret;
}

例:

byte[] bytes = new byte[]{-2, -4, -8, -16};
System.out.println(Integer.toBinaryString(toInt(bytes, 0)));

出力:

11111110111111001111100011110000

これにより、バイトが不足し、負のバイト値が正しく処理されます。

これを行うための標準関数を知りません。

考慮すべき問題:

  1. エンディアン:異なる CPU アーキテクチャでは、int を構成するバイトが異なる順序で配置されます。最初にバイト配列をどのように考え出すかによっては、これについて心配する必要がある場合があります。と

  2. バッファリング:一度に 1024 バイトを取得し、要素 1022 でシーケンスを開始すると、4 バイトを取得する前にバッファの最後に到達します。おそらく、バッファリングを自動的に行う何らかの形式のバッファリングされた入力ストリームを使用することをお勧めします。これによりreadByte()、繰り返し使用でき、それ以外の場合は心配する必要がなくなります。

  3. トレーリング バッファ:ソースによっては、入力の末尾が奇数のバイト数になる場合があります (具体的には 4 の倍数ではありません)。ただし、最初から入力を作成し、4 の倍数であることが「保証」されている (または少なくとも前提条件である) 場合は、気にする必要はないかもしれません。

バッファリングのポイントをさらに詳しく説明するには、次のことを考慮してBufferedInputStreamください。

InputStream in = new BufferedInputStream(new FileInputStream(file), 1024);

これで、一度に 1024 バイトInputStream自動的にバッファリングする ができました。この方法では、一度に 4 バイトを問題なく読み取ることができ、I/O が多すぎることを心配する必要はありません。

次に、次のものも使用できますDataInputStream

InputStream in = new DataInputStream(new BufferedInputStream(
                     new FileInputStream(file), 1024));
byte b = in.readByte();

あるいは:

int i = in.readInt();

s の構築についてまったく心配する必要はありませんint

于 2010-03-04T22:45:06.817 に答える
18

DataInputStream.readInt() がどのように実装されているかを確認してください。

    int ch1 = in.read();
    int ch2 = in.read();
    int ch3 = in.read();
    int ch4 = in.read();
    if ((ch1 | ch2 | ch3 | ch4) < 0)
        throw new EOFException();
    return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
于 2010-03-05T10:52:54.847 に答える
5

最も簡単な方法は次のとおりです。

RandomAccessFile in = new RandomAccessFile("filename", "r"); 
int i = in.readInt();

- また -

DataInputStream in = new DataInputStream(new BufferedInputStream(
    new FileInputStream("filename"))); 
int i = in.readInt();
于 2010-03-04T22:48:25.873 に答える
4

このようなことを試してください:

a = buffer[3];
a = a*256 + buffer[2];
a = a*256 + buffer[1];
a = a*256 + buffer[0];

これは、最下位バイトが最初に来ると仮定しています。最上位バイトが最初に来る場合は、インデックスを交換する必要がある場合があります (0 から 3 に移動します)。

基本的に、追加したいバイトごとに、最初にaに 256 を掛けて (これは左への 8 ビットのシフトに相当します)、次に新しいバイトを追加します。

于 2010-03-04T22:46:37.610 に答える
1
for (int i = 0; i < buffer.length; i++)
{
   a = (a << 8) | buffer[i];
   if (i % 3 == 0)
   {
      //a is ready
      a = 0;
   }       
}
于 2010-03-04T22:49:53.080 に答える
1

可変長バイトに BigInteger を使用することもできます。必要に応じて、Long、Integer、または Short に変換できます。

new BigInteger(bytes).intValue();

または極性を示すには:

new BigInteger(1, bytes).intValue();
于 2013-07-31T20:36:40.383 に答える
0

array次のコードは、 (a byte[]) の位置から 4 バイトを読み取り、 indexa を返しますint。Java 10 に関する他の回答のほとんどのコードと、私が思いついた他のいくつかのバリアントを試しました。

このコードは CPU 時間の使用量が最小でしたが、ByteBufferJava 10 の JIT が割り当てを取り除くまで割り当てます。

int result;

result = ByteBuffer.
   wrap(array).
   getInt(index);

このコードは、何も割り当てない最高のパフォーマンスのコードです。残念ながら、上記のコードと比較して 56% 多くの CPU 時間を消費します。

int result;
short data0, data1, data2, data3;

data0  = (short) (array[index++] & 0x00FF);
data1  = (short) (array[index++] & 0x00FF);
data2  = (short) (array[index++] & 0x00FF);
data3  = (short) (array[index++] & 0x00FF);
result = (data0 << 24) | (data1 << 16) | (data2 << 8) | data3;
于 2018-11-23T18:39:18.917 に答える