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

发布于 2024-11-03 04:04:42 字数 176 浏览 1 评论 0原文

我有一个包含字节、字符和对象的文件,所有这些都需要写入然后读取。利用 Java 的不同 IO 流来写入和读取这些数据类型的最佳方法是什么?

更具体地说,是否有适当的方法来添加分隔符并识别这些分隔符,然后触发应使用什么流?我相信我需要一些关于在同一文件中使用多个流的澄清,这是我以前从未研究过的。彻底的解释将是一个足够的答案。

I have a file that contains bytes, chars, and an object, all of which need to be written then read. What would be the best way to utilize Java's different IO streams for writing and reading these data types?

More specifically, is there a proper way to add delimiters and recognize those delimiters, then triggering what stream should be used? I believe I need some clarification on using multiple streams in the same file, something I have never studied before. A thorough explanation would be a sufficient answer.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

仙女山的月亮 2024-11-10 04:04:42

正如 EJP 已经建议的那样,使用 ObjectOutputStream 和 ObjectInputStream 并将其他元素包装为对象。我给出一个答案,这样我就可以展示一个例子(很难在评论中做到这一点)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

请参见此处非常清晰的示例:读取写入

As EJP already suggested, use ObjectOutputStream and ObjectInputStream an0d wrap your other elements as an object(s). I'm giving as an answer so I could show an example (it's hard to do it in comment) EJP - if you want to embed it in your question, please do and I'll delete the answer.

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

Write to file:

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

Read from file

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

see very clear example here: Read and Write

苯莒 2024-11-10 04:04:42

重新设计文件。目前没有合理的方法来实现它。例如,该对象预设了一个 ObjectOutputStream,它有一个标头 - 它会去哪里?您如何知道在哪里从字节切换到字符?

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

Redesign the file. There is no sensible way of implementing it as presently designed. For example the object presupposes an ObjectOutputStream, which has a header - where's that going to go? And how are you going to know where to switch from bytes to chars?

I would probably use an ObjectOutputStream for the whole thing and write everything as objects. Then Serialization solves all those problems for you. After all you don't actually care what's in the file, only how to read and write it.

窗影残 2024-11-10 04:04:42

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

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

Can you change the structure of the file? It is unclear because the first sentence of your question contradicts being able to add delineators. If you can change the file structure you could output the different data types into separate files. I would consider this the 'proper' way to delineate the data streams.

If you are stuck with the file the way it is then you will need to write an interface to the file's structure which in practice is a shopping list of read operations and a lot of exception handling. A hackish way to program because it will require a hex editor and a lot of trial and error but it works in certain cases.

追星践月 2024-11-10 04:04:42

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

Why not write the file as XML, possibly with a nice simple library like XSTream. If you are concerned about space, wrap it in gzip compression.

柒七 2024-11-10 04:04:42

如果您可以控制文件格式,并且它不是一个特别大的文件(即 < 1 GiB),您是否考虑过使用 Google 的 Protocol Buffers?

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

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

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

If you have control over the file format, and it's not an exceptionally large file (i.e. < 1 GiB), have you thought about using Google's Protocol Buffers?

They generate code that parses (and serializes) file/byte[] content. Protocol buffers use a tagging approach on every value that includes (1) field number and (2) a type, so they have nice properties such as forward/backward compatability with optional fields etc. They are fairly well optimized for both speed and file size, adding only ~2 bytes of overhead for a short byte[], with ~2-4 additional bytes to encode the length on larger byte[] fields (VarInt encoded lengths).

This could be overkill, but if you have a bunch of different fields & types, protobuf is really helpful. See: http://code.google.com/p/protobuf/.

An alternative is Thrift by Facebook, with support for a few more languages although possibly less use in the wild last I checked.

提笔落墨 2024-11-10 04:04:42

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

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);

If the structure of your file is not fixed, consider using a wrapper per type. First you need to create the interface of your wrapper classes….

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

Then you create the MyWrapperVisitor interface…

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

Then you create your wrapper classes…

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);

    }
}
.
.
.

And finally you read your objects…

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);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文