我编写了以下代码,它将4000字节的0写入文件test.txt。然后,我一次以1000个字节的块读取同一个文件。
FileOutputStream output = new FileOutputStream("test.txt");
ObjectOutputStream stream = new ObjectOutputStream(output);
byte[] bytes = new byte[4000];
stream.write(bytes);
stream.close();
FileInputStream input = new FileInputStream("test.txt");
ObjectInputStream s = new ObjectInputStream(input);
byte[] buffer = new byte[1000];
int read = s.read(buffer);
while (read > 0) {
System.out.println("Read " + read);
read = s.read(buffer);
}
s.close();我期望的是读取1000字节四次。
Read 1000
Read 1000
Read 1000
Read 1000然而,实际发生的情况是,我似乎每1024字节就有“暂停”(因为缺少一个更好的词)。
Read 1000
Read 24
Read 1000
Read 24
Read 1000
Read 24
Read 928如果我试图读取超过1024字节,那么我的上限是1024字节。如果我试图读取小于1024字节,则仍然需要在1024字节标记处暂停。
在检查十六进制的输出文件test.txt时,我注意到有5个非零字节7A 00 00 04 00 1029字节的序列,尽管我只向该文件写入了0。Here is the output from my hex editor. (可能太长了,不适合这个问题)。
所以我的问题是:为什么这五个字节出现在我的文件中,而我已经写了整整0?这5个字节是否与每1024字节发生一次的暂停有关?为什么有这个必要?
发布于 2015-11-29 06:40:41
对象流使用内部1024字节的缓冲区,并在由块数据标记领导的流块中以该大小的块写入原始数据,这些块由32位长字(或0x77后接8位长字)组成。因此,您只能最多读取1024字节。
这里真正的问题是为什么您只使用对象流来读取和写入字节。使用缓冲流。然后缓冲就在您的控制之下,顺便说一句,没有任何空间开销,与具有流头和类型代码的对象流不同。
NB序列化的数据不是文本,不应该存储在名为.txt的文件中。
发布于 2015-11-29 06:58:35
ObjectOutputStream和ObjectInputStream是用于对象序列化的特殊流。
但是,当您执行stream.write(bytes);时,您尝试将ObjectOutputStream用作常规流,用于写入4000字节,而不是用于写入字节数组对象。当像这样将数据写入ObjectOutputStream时,它们将被专门处理。
来自ObjectOutputStream
(强调我的)
原语数据,不包括可序列化字段和外部数据,是在块数据记录中写入ObjectOutputStream的.块数据记录由报头和数据组成。块数据头由标记和标头后面的字节数组成。连续的原始数据写入被合并到一个块数据记录中。块数据记录使用的阻塞因子为1024字节.每个块数据记录将被填充到1024字节,或者在块数据模式终止时被写入。
我希望从这一点可以看出,你为什么要接受这种行为。
我建议您要么使用BufferedOutputStream而不是ObjectOutputStream,要么,如果您真的想使用ObjectOutputStream,那么使用writeObject()而不是write()。相应的应用于输入。
发布于 2015-11-29 06:34:19
我建议您使用 Statement处理关闭资源,使用BufferedInputStream和BufferedOutputStream添加缓冲,然后使用writeObject和readObject序列化byte[]。就像,
try (OutputStream output = new BufferedOutputStream(//
new FileOutputStream("test.txt"), 8192); //
ObjectOutputStream stream = new ObjectOutputStream(output)) {
byte[] bytes = new byte[4000];
stream.writeObject(bytes);
} catch (IOException ioe) {
ioe.printStackTrace();
}然后读到
try (InputStream input = new BufferedInputStream(//
new FileInputStream("test.txt"), 8192); //
ObjectInputStream s = new ObjectInputStream(input)) {
byte[] bytes = (byte[]) s.readObject();
} catch (IOException | ClassNotFoundException ioe) {
ioe.printStackTrace();
}如果涉及到部分数组,则需要添加长度。您可以在另一边使用stream.writeInt(len);和int len = stream.readInt();。
https://stackoverflow.com/questions/33980038
复制相似问题