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

时间:2014-07-09 05:52:57

标签: 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 总是

第二种方法

            // 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”这个词,以及其他我不想在文件中写入的信息。我在这里看到的只是他们的价值观。在这个例子中,它是:'c',7,3,4'p','e','n'。我想只将这个7字节写入文件,而不是其他对我有用的信息。

3 个答案:

答案 0 :(得分:2)

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

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

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

但还有其他一些考虑因素。您的示例没有执行很多写操作。所以无论如何它可能会非常快。任何优化都可能是不成熟的优化。优化往往会使代码更复杂,更难理解。要了解您的ByteBuffer代码,读者需要了解ByteBuffer如何 如果您更改了文件格式,则更有可能引入FileOutputStream代码的错误(例如,缓冲区太小)。

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

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

ByteBuffer

答案 1 :(得分:0)

这两种方法的区别仅在于分配的字节缓冲区。

如果您对文件的不必要的写操作感到担忧,那么您已经可以使用BufferedOutputStream,内部分配缓冲区,如果您多次写入相同的输出流,则效率肯定更高而不是每次手动分配缓冲区。

答案 2 :(得分:0)

在FileOutputStream周围的BufferedOutputStream周围使用DataOutputStream是最简单的。

注意:您无法挤压" shortData'变成一个字节。使用DataOutputStream的各种原语,并在读取它们时使用相应的DataInputStream。