使用不同IO流写入/读取文件的正确方法是什么

时间:2011-04-23 13:04:58

标签: java file-io iostream inputstream outputstream

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

6 个答案:

答案 0 :(得分: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

在此处查看非常明确的示例:ReadWrite

答案 1 :(得分:1)

重新设计文件。没有明智的方法来实现它目前的设计。例如,对象预先假定一个ObjectOutputStream,它有一个标题 - 这将是什么?你怎么知道在哪里从字节切换到字符?

我可能会将ObjectOutputStream用于整个事物并将所有内容写为对象。然后Serialization为您解决所有这些问题。毕竟,你实际上并不关心文件中的内容,只关心如何读写它。

答案 2 :(得分:0)

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

如果您按照文件的方式处理文件,那么您将需要编写一个文件结构的接口,实际上这是一个读取操作的购物清单和许多异常处理。一种破解性的编程方式,因为它需要一个十六进制编辑器和大量的反复试验,但它在某些情况下有效。

答案 3 :(得分:0)

为什么不把文件写成XML,可能还有一个很好的简单库,比如XSTream。如果你担心空间,请用gzip压缩包装。

答案 4 :(得分:0)

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

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

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

另一种选择是Facebook的Thrift,支持更多语言,但最后我检查的可能性较少。

答案 5 :(得分:0)

如果文件的结构未修复,请考虑使用每种类型的包装器。首先,您需要创建包装类的接口......

interface MyWrapper extends Serializable {
    void accept(MyWrapperVisitor visitor);
}

然后创建MyWrapperVisitor接口......

interface MyWrapperVisitor {
    void visit(MyString wrapper);
    void visit(MyChar wrapper);
    void visit(MyLong wrapper);
    void visit(MyCustomObject wrapper);
}

然后你创建你的包装类......

class MyString implements MyWrapper {
    public final String value;

    public MyString(String value) {
        super();
        this.value = value;
    }

    @Override
    public void accept(MyWrapperVisitor visitor) {
        visitor.visit(this);

    }
}
.
.
.

最后你读了你的对象......

final InputStream in = new FileInputStream(myfile);
final ObjectInputStream objIn = new ObjectInputStream(in);
final MyWrapperVisitor visitor = new MyWrapperVisitor() {
    @Override
    public void visit(MyString wrapper) {
        //your logic here

    }
    .
    .
    .
};

//loop over all your objects here
final MyWrapper wrapper = (MyWrapper) objIn.readObject();
wrapper.accept(visitor);