Java读取二进制文件(unsigned long long)

标签 java c++ binaryfiles endianness

我想将 C 代码转换为 Java。它读取一个二进制文件:

int main(int argc, char**argv)
{
    FILE *fd;
    unsigned long trameNumber = 0;
    unsigned long long INDEX;

    fd = fopen(argv[1],"rb");
    if (fd == NULL)
    {
        printf("Usage %s [File]\n", argv[0]);
        exit(1);
    }

    fread(&INDEX, sizeof(INDEX),1, fd);
    printf("INDEX %llx\n",INDEX);
    trameNumber++;

    while (fread(&INDEX, sizeof(INDEX),1, fd) != 0)
    {
        printf("INDEX %llx\n",INDEX);
        trameNumber++;
    }

    fclose(fd);
    printf("%lu", trameNumber);

    return 0;
}

此代码的输出如下所示:

INDEX 0
INDEX 9800000000000000
INDEX 1801000000000000
INDEX 5001000000000000
INDEX b801000000000000

这是我的 Java 代码。我尝试使用 BigInteger 来做到这一点:

public static final int DATA_BYTE_LENGHT = 8;

public void readBinary(final String readFilePath)
{
    // A 8 byte buffer = 64 bits
    ByteBuffer byteBuffer = ByteBuffer.allocate(DATA_BYTE_LENGHT);

    // Those channels will be used to read/write files
    FileChannel channelFileInput = null;

    BigInteger bigIndex = null;

    try {

        // File to read
        final File fileRead = new File(readFilePath);

        // Channel used to read the file.
        channelFileInput = new FileInputStream(fileRead).getChannel();

        byteBuffer.put(new byte[DATA_BYTE_LENGHT]);
        byteBuffer.rewind();

        // While the file has content
        while( channelFileInput.read(byteBuffer) != -1 ) {

            byteBuffer.rewind();

            // Big integer positive
            bigIndex = new BigInteger(1, byteBuffer.array());

            byteBuffer.rewind();

            System.out.println("INDEX "+bigIndex.toString(16));

            // Clear the buffer
            byteBuffer.put(new byte[DATA_BYTE_LENGHT]);
            byteBuffer.rewind();

        }

    } catch(FileNotFoundException e) {
        System.err.println("The file cannot be read: "+e.getMessage());
    } catch(Exception e) {
        System.err.println(e.getMessage());
    } finally {
        // Close file connections
        IOUtils.closeQuietly(channelFileInput);
    }
}

但是,read() 似乎没有正确读取文件。因为输出是:

INDEX 0
INDEX 98
INDEX 118
INDEX 150
INDEX 1b8

会不会是字节序问题?如何解决?

谢谢

最佳答案

BigInteger 构造函数采用大端表示法,而文件中的数据似乎以小端法存储。要解决此问题,您可以反转获取的数组中的字节,或使用 ByteBuffer 中的 order 方法设置字节序并使用 long 数据类型:

// before loop
byteBuffer.order(ByteOrder.LITTLE_ENDIAN);

// in loop
long bigIndex = byteBuffer.getLong();
byteBuffer.rewind();
System.out.println("INDEX "+Long.toHexString(bigIndex));

Java 的long 数据类型是有符号的。这可能是问题,也可能不是问题,具体取决于您之后要对这些数字执行的操作。

更新:如果您必须使用 BigInteger,您可以像我之前所说的那样反转字节数组,或者使用 long 读取数字然后更正符号:

BigInteger bi = BigInteger.valueOf(bigIndex & ~Long.MIN_VALUE);
if (bigIndex < 0) bi = bi.setBit(63);

关于Java读取二进制文件(unsigned long long),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20121623/

相关文章:

java - 从数组中播放android中的mp3文件

全局变量的java单独文件

c++ - 在 C++ 中返回结构

c++ - 两个类的前向声明会导致构造函数中的循环依赖吗?

python-3.x - Falcon 和 falcon-multipart + POST 请求上传文件的实现

java - easymock - 模拟使用 anyObject 作为 void setter 方法的参数

使用 REST 的 Java PayPal 客户端快速结帐(redirect_urls 不工作)

C++ 继承 : Can't access private element of base class

c - 如何从图像/二进制文件中检查结构的值?

image - 是否有纯 ASCII 图像文件?