2

我有一个包含字节、字符和对象的文件,所有这些都需要先写入然后再读取。利用 Java 的不同 IO 流来写入和读取这些数据类型的最佳方法是什么?更具体地说,是否有适当的方法来添加分隔符并识别这些分隔符,然后触发应该使用什么流?我相信我需要对在同一个文件中使用多个流进行一些澄清,这是我以前从未研究过的。一个彻底的解释将是一个足够的答案。谢谢!

4

6 回答 6

2

正如EJP已经建议的那样,使用 ObjectOutputStream 和 ObjectInputStream an0d 将您的其他元素包装为一个对象。我给出一个答案,所以我可以举一个例子(在评论中很难做到)EJP - 如果你想将它嵌入你的问题,请这样做,我会删除答案。

class MyWrapedData implements serializeable{
    private String string1;
    private String string2;
    private char   char1;
    // constructors
    // getters setters
}

写入文件:

ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(fileName));
out.writeObject(myWrappedDataInstance);
out.flush();

从文件中读取

ObjectInputStream in = new ObjectInputStream(new FileInputStream(fileName));
Object obj = in.readObject();
MyWrapedData wraped = null;
if ((obj != null) && (obj instanceof MyWrappedData))
    wraped = (MyWrapedData)obj;
// get the specific elements from the wraped object

在这里看到非常清楚的例子读写

于 2011-04-23T22:32:42.947 回答
1

重新设计文件。没有明智的方式来按照目前的设计来实现它。例如,该对象预设了一个 ObjectOutputStream,它有一个标头 - 它将去哪里?你怎么知道在哪里从字节切换到字符?

我可能会为整个事情使用 ObjectOutputStream 并将所有内容都写为对象。然后序列化为您解决所有这些问题。毕竟,您实际上并不关心文件中的内容,而只关心如何读取和写入它。

于 2011-04-23T13:27:29.313 回答
0

你能改变文件的结构吗?目前尚不清楚,因为您问题的第一句话与能够添加轮廓线相矛盾。如果您可以更改文件结构,您可以将不同的数据类型输出到单独的文件中。我认为这是描述数据流的“正确”方式。

如果您坚持使用文件的方式,那么您将需要为文件结构编写一个接口,这实际上是一个读取操作和大量异常处理的购物清单。一种骇人听闻的编程方式,因为它需要一个十六进制编辑器和大量的试验和错误,但它在某些情况下有效。

于 2011-04-23T15:16:21.797 回答
0

为什么不将文件编写为 XML,可能使用 XSTream 之类的简单库。如果您担心空间,请将其包装在 gzip 压缩中。

于 2011-04-23T18:32:25.150 回答
0

如果您可以控制文件格式,并且它不是特别大的文件(即 < 1 GiB),您是否考虑过使用 Google 的协议缓冲区?

它们生成解析(和序列化)文件/字节[]内容的代码。协议缓冲区对包括 (1) 字段编号和 (2) 类型的每个值都使用标记方法,因此它们具有很好的属性,例如与可选字段的向前/向后兼容性等。它们针对速度和文件大小进行了相当好的优化,为短字节 [] 仅增加约 2 个字节的开销,并增加约 2-4 个字节来对较大的 byte[] 字段的长度进行编码(VarInt 编码长度)。

这可能有点矫枉过正,但如果你有一堆不同的字段和类型,protobuf 真的很有帮助。请参阅:http ://code.google.com/p/protobuf/ 。

另一种选择是 Facebook 的 Thrift,它支持更多的语言,尽管我上次检查时在野外使用的可能更少。

于 2011-04-23T22:10:31.477 回答
0

如果文件的结构不固定,请考虑对每种类型使用包装器。首先,您需要创建包装类的接口……。

接口 MyWrapper 扩展 Serializable {
    无效接受(MyWrapperVisitor 访客);
}

然后创建 MyWrapperVisitor 接口……</p>

接口 MyWrapperVisitor {
    无效访问(MyString 包装器);
    无效访问(MyChar 包装器);
    无效访问(MyLong 包装器);
    无效访问(MyCustomObject 包装器);
}

然后你创建你的包装类......</p>

类 MyString 实现 MyWrapper {
    公共最终字符串值;

    公共MyString(字符串值){
        极好的();
        this.value = 值;
    }

    @覆盖
    公共无效接受(MyWrapperVisitor 访问者){
        访客.visit(this);

    }
}
.
.
.

最后你阅读了你的对象……</p>

final InputStream in = new FileInputStream(myfile);
final ObjectInputStream objIn = new ObjectInputStream(in);
最终的 MyWrapperVisitor 访问者 = 新的 MyWrapperVisitor() {
    @覆盖
    公共无效访问(MyString 包装器){
        //你的逻辑在这里

    }
    .
    .
    .
};

//在这里循环你所有的对象
最终 MyWrapper 包装器 = (MyWrapper) objIn.readObject();
wrapper.accept(访客);
于 2011-05-31T16:59:01.967 回答