java - 放入 ByteBuffer 然后将其写入文件比写入单个字段更有效

标签 java java-io bytebuffer

我想将对象的数据成员的值写入文件,因此这里我不能使用序列化,因为它会写入很多内容其他我不需要的信息。这是我通过两种方式实现的。一种使用字节缓冲区,另一种则不使用它。

不使用 ByteBuffer: 第一种方法

public class DemoSecond {

    byte characterData;
    byte shortData;
    byte[] integerData;
    byte[] stringData;

    public DemoSecond(byte characterData, byte shortData, byte[] integerData,
        byte[] stringData) {
        super();
        this.characterData = characterData;
        this.shortData = shortData;
        this.integerData = integerData;
        this.stringData = stringData;
    }

    public static void main(String[] args) {
        DemoSecond dClass= new DemoSecond((byte)'c', (byte)0x7, new byte[]{3,4},
            new byte[]{(byte)'p',(byte)'e',(byte)'n'});

        File checking= new File("c:/objectByteArray.dat");
        try {
            if (!checking.exists()) {
                checking.createNewFile();
            }
            // POINT A
            FileOutputStream bo = new FileOutputStream(checking);
            bo.write(dClass.characterData);
            bo.write(dClass.shortData);
            bo.write(dClass.integerData);
            bo.write(dClass.stringData);
            // POINT B
            bo.close();
        } catch (FileNotFoundException e) {
                System.out.println("FNF");
                e.printStackTrace();
        } catch (IOException e) {
                System.out.println("IOE");
                e.printStackTrace();
        }
    }
}

使用字节缓冲区:另一件事是数据成员的大小将始终保持固定,即characterData = 1byte,shortData = 1byte,integerData = 2byte和stringData = 3byte。所以这个类的总大小是7byte ALWAYS

第二种方法

            // POINT A
            FileOutputStream bo = new FileOutputStream(checking);
            ByteBuffer buff= ByteBuffer.allocate(7);
            buff.put(dClass.characterData);
            buff.put(dClass.shortData);
            buff.put(dClass.integerData);
            buff.put(dClass.stringData);
            bo.write(buff.array());
            // POINT B

我想知道这两种方法哪一种更优化?并请说明理由。

上面的类DemoSecond只是一个示例类。

我的原始类的大小为 5 到 50 字节。我认为这里的尺寸可能不是问题。 但我的每个类都是固定大小的,例如 DemoSecond

还有很多这种类型的文件,我将在二进制文件中写入它们。

PS

如果我使用序列化,它还会写入单词“characterData”、“shortData”、“integerData”、“stringData”以及我不想写入文件的其他信息。我在这里关心的是仅他们的值(value)观。在此示例中,其为:'c', 7, 3,4'p','e','n'。我只想将这 7 个字节写入文件,而不是其他对我来说无用的信息。

最佳答案

当您进行文件 I/O 时,您应该记住,I/O 操作可能比 CPU 在输出代码中完成的任何工作慢得多。第一个近似值是,I/O 成本与您正在写入的数据量成正比,加上执行 I/O 的每个操作系统调用的固定成本。

因此,在您的情况下,您希望最大限度地减少进行写入操作的操作系统调用次数。这是通过在应用程序中缓冲数据来完成的,因此应用程序很少执行较大的操作系统调用。

正如您所做的那样,使用字节缓冲区是实现此目的的一种方法,因此您的 ByteBuffer 代码将比 FileOutputStream 代码更高效。

但还有其他考虑因素。您的示例没有执行很多写入操作。所以无论如何它可能会非常快。任何优化都可能是过早的优化。优化往往会使代码变得更加复杂且难以理解。要理解 ByteBuffer 代码,读者除了需要了解 FileOutputStream< 的所有内容之外,还需要了解 ByteBuffer 的工作原理/ 代码。如果您更改文件格式,则更有可能在 ByteBuffer 代码中引入错误(例如,缓冲区太小)。

通常会进行输出缓冲。因此,Java 已经提供了可以帮助您的代码,您应该不会感到惊讶。该代码将由专家编写、测试和调试。除非您有特殊要求,否则您应该始终使用此类代码而不是编写自己的代码。我指的代码是 BufferedOutputStream 类。

要使用它,只需调整不使用 ByteBuffer 的代码,方法是将打开文件的代码行更改为

 OutputStream bo = new BufferedOutputStream(new FileOutputStream(checking));

关于java - 放入 ByteBuffer 然后将其写入文件比写入单个字段更有效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24646231/

相关文章:

java - ByteBuffer 类的 rewind() 和 clear() 有什么区别?

Java:将 ArrayList<Byte> 转换为 ByteBuffer

java - 使用 Android Volley 发送图像或文本或两者

java - 同步对象序列化(Android)

java - 如何去掉输出到txt的程序状态?

java - 从文件中读取前 5 行,然后读取其余行

java - 是否可以将 Process stdout InputStream 读取到 NIO ByteBuffer 中?

java - HttpUrlConnection 到 HttpsUrlConnection,我可以只添加 's' 吗?

java - 使用 java 读取大型 xml 文件的最快 xml 阅读器

java - 接口(interface)如何返回其自身的严格实现