繁体   English   中英

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

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

我想将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将所有原始数据类型定义为使用big endian。 如果您使用的是x86(Windows,Linux或OSX)平台,则您的计算机可能会使用Little Endian。 疲劳可能是您痛苦的原因。 您可以使用掩码和移位操作反转字节顺序来解决问题。 这个答案实际上是在这个答案中给出的

暂无
暂无

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

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