简体   繁体   English

Java读取二进制文件(无符号long long)

[英]Java read binary file (unsigned long long)

I want to convert a C code to Java. 我想将C代码转换为Java。 It reads a binary file: 它读取一个二进制文件:

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;
}

The output with this code looks like: 此代码的输出如下所示:

INDEX 0
INDEX 9800000000000000
INDEX 1801000000000000
INDEX 5001000000000000
INDEX b801000000000000

Here is my Java code. 这是我的Java代码。 I've tried to do that with BigInteger : 我试图用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);
    }
}

However, read() doesn't seem to read the file correctly. 但是, read()似乎无法正确读取文件。 Because the output is: 因为输出是:

INDEX 0
INDEX 98
INDEX 118
INDEX 150
INDEX 1b8

Could it be an endianess problem? 可能是流行病吗? How to solve it? 怎么解决呢?

Thanks 谢谢

The BigInteger constructor assumes a big-endian representation, while the data in the file seems to be stored in little-endian. BigInteger构造函数假定使用大端表示,而文件中的数据似乎存储在小端。 To fix this problem you can reverse the bytes in the array that you obtain, or use order method in ByteBuffer to set the endianness and use the long data type: 要解决此问题,您可以反转获取的数组中的字节,或者使用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's long data type is signed though. 但是,Java的long数据类型已签名。 This may or may not be a problem depending on what you want to do with the numbers afterwards. 取决于您以后对数字的处理方式,这可能是问题,也可能不是问题。

Update: If you must use BigInteger you can just reverse the array of bytes like I said earlier, or read the numbers using long and then correct the sign: 更新:如果必须使用BigInteger ,则可以像我之前所说的那样反转字节数组,或者使用long读取数字,然后更正符号:

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

Java defines all primitive data types as using big endian. Java将所有原始数据类型定义为使用big endian。 If you are working on an x86 (windows or linux or OSX) platform, your computer is likely using little endian. 如果您使用的是x86(Windows,Linux或OSX)平台,则您的计算机可能会使用Little Endian。 Endianess is likely the cause of your affliction. 疲劳可能是您痛苦的原因。 You can probably solve the problem using mask and shift operations to reverse the byte order. 您可以使用掩码和移位操作反转字节顺序来解决问题。 The answer to this is actually given in this answer 这个答案实际上是在这个答案中给出的

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM