首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么我一次只能读取1024字节的ObjectInputStream?

为什么我一次只能读取1024字节的ObjectInputStream?
EN

Stack Overflow用户
提问于 2015-11-29 06:24:21
回答 3查看 4.1K关注 0票数 24

我编写了以下代码,它将4000字节的0写入文件test.txt。然后,我一次以1000个字节的块读取同一个文件。

代码语言:javascript
复制
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字节四次。

代码语言:javascript
复制
Read 1000
Read 1000
Read 1000
Read 1000

然而,实际发生的情况是,我似乎每1024字节就有“暂停”(因为缺少一个更好的词)。

代码语言:javascript
复制
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字节发生一次的暂停有关?为什么有这个必要?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-11-29 06:40:41

对象流使用内部1024字节的缓冲区,并在由块数据标记领导的流块中以该大小的块写入原始数据,这些块由32位长字(或0x77后接8位长字)组成。因此,您只能最多读取1024字节。

这里真正的问题是为什么您只使用对象流来读取和写入字节。使用缓冲流。然后缓冲就在您的控制之下,顺便说一句,没有任何空间开销,与具有流头和类型代码的对象流不同。

NB序列化的数据不是文本,不应该存储在名为.txt的文件中。

票数 18
EN

Stack Overflow用户

发布于 2015-11-29 06:58:35

ObjectOutputStreamObjectInputStream是用于对象序列化的特殊流。

但是,当您执行stream.write(bytes);时,您尝试将ObjectOutputStream用作常规流,用于写入4000字节,而不是用于写入字节数组对象。当像这样将数据写入ObjectOutputStream时,它们将被专门处理。

来自ObjectOutputStream

(强调我的)

原语数据,不包括可序列化字段和外部数据,是在块数据记录中写入ObjectOutputStream的.块数据记录由报头和数据组成。块数据头由标记和标头后面的字节数组成。连续的原始数据写入被合并到一个块数据记录中。块数据记录使用的阻塞因子为1024字节.每个块数据记录将被填充到1024字节,或者在块数据模式终止时被写入。

我希望从这一点可以看出,你为什么要接受这种行为。

我建议您要么使用BufferedOutputStream而不是ObjectOutputStream,要么,如果您真的想使用ObjectOutputStream,那么使用writeObject()而不是write()。相应的应用于输入。

票数 8
EN

Stack Overflow用户

发布于 2015-11-29 06:34:19

我建议您使用 Statement处理关闭资源,使用BufferedInputStreamBufferedOutputStream添加缓冲,然后使用writeObjectreadObject序列化byte[]。就像,

代码语言:javascript
复制
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();
}

然后读到

代码语言:javascript
复制
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();

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33980038

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档