我想将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
这可能是一个结束问题吗?怎么解决?
由于
答案 0 :(得分:1)
BigInteger
构造函数假定为big-endian表示,而文件中的数据似乎以little-endian存储。要解决此问题,您可以反转所获得的数组中的字节,或使用order
中的ByteBuffer
方法设置字节顺序并使用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);
答案 1 :(得分:0)
Java将所有原始数据类型定义为使用big endian。如果您正在使用x86(Windows或Linux或OSX)平台,则您的计算机可能使用小端。 Endianess可能是你痛苦的原因。您可以使用掩码和移位操作来解决问题,以反转字节顺序。答案实际上是在this answer
中给出的