OnePunchMan
OnePunchMan

Reputation: 748

Is put-ing to a ByteBuffer then writing it to a file more efficient than writing the individual field

I want to write ONLY the values of the data members of an object into a file, so here I can can't use serialization since it writes a whole lot other information which i don't need. Here's is what I have implemented in two ways. One using byte buffer and other without using it.

Without using ByteBuffer: 1st method

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

Using byte buffer: One more thing is that the size of the data members will always remain fixed i.e. characterData= 1byte, shortData= 1byte, integerData= 2byte and stringData= 3byte. So the total size of this class is 7byte ALWAYS

2nd method

            // 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

I want know which one of the two methods is more optimized? And kindly give the reason also.

The above class DemoSecond is just a sample class.

My original classes will be of size 5 to 50 bytes. I don't think here size might be the issue. But each of my classes is of fixed size like the DemoSecond

Also there are so many files of this type which I am going to write in the binary file.

PS

if I use serialization it also writes the word "characterData", "shortData", "integerData","stringData" also and other information which I don't want to write in the file. What I am corcern here is about THEIR VALUES ONLY. In case of this example its:'c', 7, 3,4'p','e','n'. I want to write only this 7bytes into the file, NOT the other informations which is USELESS to me.

Upvotes: 0

Views: 136

Answers (3)

user207421
user207421

Reputation: 310957

It would be simplest to use a DataOutputStream around a BufferedOutputStream around the FileOutputStream.

NB You can't squeeze 'shortData' into a byte. Use the various primitives of DataOutputStream, and use the corresponding ones of DataInputStream when reading them back.

Upvotes: 0

Raedwald
Raedwald

Reputation: 48682

As you are doing file I/O, you should bear in mind that the I/O operations are likely to be very much slower than any work done by the CPU in your output code. To a first approximation, the cost of I/O is an amount proportional to the amount of data you are writing, plus a fixed cost for each operating system call made to do the I/O.

So in your case you want to minimise the number of operating system calls to do the writing. This is done by buffering data in the application, so the application performs few put larger operating system calls.

Using a byte buffer, as you have done, is one way of doing this, so your ByteBuffer code will be more efficient than your FileOutputStream code.

But there are other considerations. Your example is not performing many writes. So it is likely to be very fast anyway. Any optimisation is likely to be a premature optimisation. Optimisations tend to make code more complicated and harder to understand. To understand your ByteBuffer code a reader needs to understand how a ByteBuffer works in addition to everything they need to understand for the FileOutputStream code. And if you ever change the file format, you are more likely to introduce a bug with the ByteBuffer code (for example, by having a too small a buffer).

Buffering of output is commonly done. So it should not surprise you that Java already provides code to help you. That code will have been written by experts, tested and debugged. Unless you have special requirements you should always use such code rather than writing your own. The code I am referring to is the BufferedOutputStream class.

To use it simply adapt your code that does not use the ByteBuffer, by changing the line of your code that opens the file to

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

Upvotes: 2

Adrian Shum
Adrian Shum

Reputation: 40036

The two methods differ only in the byte buffer allocated.

If you are concerning about unnecessary write action to file, there is already a BufferedOutputStream you can use, for which buffer is allocated internally, and if you are writing to same outputstream multiple times, it is definitely more efficient than allocating buffer every time manually.

Upvotes: 0

Related Questions