我遇到了一个问题,使用FileOutputStream将负字节值写入二进制文件,其中负字节值,例如。 -1被写入文件,但它占用了两个字节,在我看来,它们完全是胡说八道。
在我的应用程序中,某些对象具有toByteArray()返回byte [],因此可以将其写入文件。即使它在许多对象上都“有效”,我还是将对象序列化为存在一些负字节的字节数组(新的byte [] {0,0,0,1,-1,-1,-1,-1, 1,3,-48,-5,10}),当我将该对象写入文件时,负数将被写为“ c0 a2”字节。
测试用例:
public void testWRITE() {
String fileName = "TEST_FILE.lldb";
String secondFileName = "SECOND_FILE.lldb";
FileOutputStream fos;
FileOutputStream fos2;
try {
fos = new FileOutputStream(fileName, false);
fos2 = new FileOutputStream(secondFileName, false);
// Writing this to file writes bytes "c2 a0" in place of -1 byte
FileChannel ch = fos.getChannel();
ch.position(0);
ch.write(ByteBuffer.wrap(new byte[] {0, 0, 0, 1, -1, -1, -1, -1, 1, 3, -48, -5, 10}));
// Writing this to file writes "ff" in of -1 byte
Pojo pojo = new Pojo();
FileChannel ch2 = fos2.getChannel();
ch2.position(0);
ch2.write(ByteBuffer.wrap(pojo.getBytes()));
fos.close();
fos2.close();
} catch (IOException e) {
fail();
}
}
其中Pojo类是简单的POJO,
public class Pojo {
private Integer negativeNumber;
public Pojo() {
this.negativeNumber = -1;
}
public byte[] getBytes() {
return Pojo.bytesFromInt(this.negativeNumber);
}
public static byte[] bytesFromInt(int value) {
return new byte[] {
(byte)(value >>> 24),
(byte)(value >>> 16),
(byte)(value >>> 8),
(byte)value};
}}
我指望着这样一个事实,当我向文件中写入一个字节将只是一个字节时,由于它是我图书馆的基石,因此我无法继续进行工作。
这是否甚至被视为FileOutputStream的预期行为? 我想念什么?
答案 0 :(得分:0)
一切都写正确。
写负数时,它们以二进制补码形式书写。
因此,写-5
= 1111 1011
(十六进制为FB
)。这就是您所看到的。
并且FF
= 1111 1111
= -1
。
这是我用来检查结果的修改后的代码。请注意,我在文件名中添加了逻辑文件字母。也许我做错了。
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.Arrays;
public class Writing {
public static void main(String[] args) {
testWRITE();
}
public static void testWRITE() {
String fileName = "F:/TEST_FILE.lldb";
String secondFileName = "F:/SECOND_FILE.lldb";
FileOutputStream fos;
FileOutputStream fos2;
try {
fos = new FileOutputStream(fileName, false);
fos2 = new FileOutputStream(secondFileName, false);
// Writing this to file writes bytes "0c2 a0" in place of -1 byte
FileChannel ch = fos.getChannel();
ch.position(0);
System.out.println("Writing to " + fileName);
ByteBuffer b = ByteBuffer.wrap(
new byte[] { 0, 0, 0, 1, -1, -1, -1, -1, 1, 3, -48, -5, 10
});
System.out.println(Arrays.toString(b.array()));
ch.write(b);
// Writing this to file writes "ff" in of -1 byte
Pojo pojo = new Pojo();
FileChannel ch2 = fos2.getChannel();
ch2.position(0);
System.out.println("Writing to " + secondFileName);
ch2.write(ByteBuffer.wrap(pojo.getBytes()));
System.out.println(Arrays.toString(pojo.getBytes()));
fos.close();
fos2.close();
System.out.println();
FileInputStream fs = new FileInputStream(fileName);
FileInputStream fs2 = new FileInputStream(secondFileName);
System.out.println("Reading all bytes from " + fileName);
byte[] bs = fs.readAllBytes();
System.out.println(Arrays.toString(bs));
System.out.println("Reading all bytes from " + secondFileName);
bs = fs2.readAllBytes();
System.out.println(Arrays.toString(bs));
}
catch (IOException e) {
System.out.println(e.getMessage());
}
}
}
class Pojo {
private Integer negativeNumber;
public Pojo() {
this.negativeNumber = -1;
}
public byte[] getBytes() {
return Pojo.bytesFromInt(this.negativeNumber);
}
public static byte[] bytesFromInt(int value) {
return new byte[] {
(byte) (value >>> 24), (byte) (value >>> 16), (byte) (value >>> 8),
(byte) value
};
}
}
这是我的输出。
Writing to F:/TEST_FILE.lldb
[0, 0, 0, 1, -1, -1, -1, -1, 1, 3, -48, -5, 10]
Writing to F:/SECOND_FILE.lldb
[-1, -1, -1, -1]
Reading all bytes from F:/TEST_FILE.lldb
[0, 0, 0, 1, -1, -1, -1, -1, 1, 3, -48, -5, 10]
Reading all bytes from F:/SECOND_FILE.lldb
[-1, -1, -1, -1]
答案 1 :(得分:0)
这有点尴尬,因为我不仅是初学者,而且是的,我错了。当我将该文件读回内存时,实际上只是我以前写入文件中的那些字节。但是为了支持我的职位和态度,我并没有真正运行仅发布的任何其他代码。但是,使用带有HEXEditor扩展名的Notepad ++来查看该文件确实显示了“ FF”和“ C2 A0”,即使我将文件读回内存时字节也只是“字节”,但是我却看到“ C2”,我不知道为什么文件中的“ A0”,我什至没有想到将其读回内存以进行检查。 CaptainObvious提到“在某处”执行UTF-8转换,但是如果是这样,那不在我的代码中。