我正在用 Java 编写一个程序来输入一个文件,供其他用 C++ 编写的程序使用。因此,这个文件必须是浮点数的小端二进制文件。
我使用了许多不同类型的方法来进行这种字节序转换,包括 Apache Commons I/O、Geosoft 实用程序(与 apache.. 完全相同)和 ByteBuffer。
总之,我必须采用一堆浮点数并以二进制小端显示它们。这个过程大部分时间都有效。但是,在某些情况下,在浮点数被识别为 NaN 的字节序转换中似乎存在一些精度错误。结果,当我读取我刚刚编写的大约 1% 的时间的二进制文件时,显示的不是特定的浮点数,而是 6.055E-41 之类的数字。我在网上搜索过类似的问题。
另一个人诊断出错误包含在 float 到 Int Bits 和 Int Bits 到 float 之间的转换(在 Apache 和 Geosoft Utilities 中找到)。
推荐的解决方案是将文件直接制作成 int 位,而不是进行这一轮处理。但是,在我的情况下,直接转换为整数会使我在需要编写的原始浮点数上失去精度。推荐的解决方案是,供您参考:
“通过使用 DataInputStream 的 readFloat() 例程读取浮点数,使用 Float.floatToIntBits() 将其转换为位,交换整数,然后使用 Float.intBitsToFloat() 将其转换回浮点数,在某些情况下会导致精度错误,从而导致垃圾被退回。
解决方案是编写一组新的例程,将字节流中的位直接读取为整数,然后执行字节交换并将其转换回浮点数。”
这是一个问题的例子......
将这一系列浮点数写入二进制文件并读回它们时,预期的结果是:
1.50411975 -1.974895 1.0301249 -0.43540177 0.8161005 0.38000694 0.43332508
但是,我看到了这个:
6.9055E-41 -1.974895 1.0301249 -0.43540177 0.8161005 0.38000694 0.43332508
我正在粘贴我的代码。此版本专门使用字节缓冲区实现。你能告诉我什么是错的,我该如何解决它?
public int writeBinaryFile( ArrayList<P> p) throws FileNotFoundException, IOException
{
int c = 0;
for (int i = 0; i < p(); i++)
{
ArrayList<Float> cube = new ArrayList<Float>();
ArrayList<Float> dir = p.get(i).getDirection();
ArrayList<Float> pos = p.get(i).getPosition();
Float angle = (float) p.get(i).getAngle();
Float id = (float) p.get(i).getPEvents().get(0).getid();
ArrayList<Float> things = new ArrayList<Float>();
boolean truism = true;
if (dir.get(1) > 0 ) {
/*byte [] byte2 = this.float2ByteArray(id);
float f = ByteBuffer.wrap(byte2).order(ByteOrder.LITTLE_ENDIAN ).getFloat();
dos.writeFloat(f);*/
for (int j = 0; j < pos.size(); j++) {
byte [] bytes = this.float2ByteArray(pos.get(j));
float d = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN ).getFloat();
cube.add(d);
}
for (int j = 0; j < dir.size(); j++) {
byte [] bytes = this.float2ByteArray(dir.get(j));
float d = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN ).getFloat();
cube.add(d);
}
byte [] bytes = this.float2ByteArray(angle);
float d = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN ).getFloat();
cube.add(d);
if (this.checkCube(cube)) {this.writeCube(cube); c++; }
}
}
return c;
}
public byte [] float2ByteArray(float value)
{
return ByteBuffer.allocate(4).putFloat(value).array();
}
这是我拥有的备用交换机制:
public static float swap (float value)
{
int intValue = Float.floatToRawIntBits (value);
intValue = swap (intValue);
return Float.intBitsToFloat (intValue);
}
public static int swap (int value)
{
int b1 = (value >> 0) & 0xff;
int b2 = (value >> 8) & 0xff;
int b3 = (value >> 16) & 0xff;
int b4 = (value >> 24) & 0xff;
return b1 << 24 | b2 << 16 | b3 << 8 | b4 << 0;
}
我尝试使用直接使用整数的东西。这是我的特殊交换器:
public static float specialswap (float value)
{
int intValue = Float.floatToRawIntBits (value);
return Integer.reverseBytes(Integer.parseInt(Integer.toBinaryString(intValue)));
}
已解决:感谢 Louis Wasserman,找到了我的问题的答案:
dataOutputStream.writeInt(Integer.reverseBytes(Float.floatToRawIntBits(float))).