package com.paritytrading.nassau.binaryfile;

import static com.paritytrading.foundation.ByteBuffers.*;

import java.io.Closeable;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.WritableByteChannel;

/**
 * An implementation of a BinaryFILE writer.
 */
public class BinaryFILEWriter implements Closeable {

    private WritableByteChannel channel;

    private ByteBuffer header;

    /**
     * Create a BinaryFILE writer.
     *
     * @param stream an output stream
     */
    public BinaryFILEWriter(OutputStream stream) {
        this(Channels.newChannel(stream));
    }

    /**
     * Create a BinaryFILE writer.
     *
     * @param channel an output channel
     */
    public BinaryFILEWriter(WritableByteChannel channel) {
        this.channel = channel;

        this.header = ByteBuffer.allocate(2);
    }

    /**
     * Open a BinaryFILE writer.
     *
     * @param file the output file
     * @return a BinaryFILE writer
     * @throws IOException if an I/O error occurs
     */
    public static BinaryFILEWriter open(File file) throws IOException {
        FileOutputStream stream = new FileOutputStream(file);

        return new BinaryFILEWriter(stream.getChannel());
    }

    /**
     * Write a message.
     *
     * @param payload a buffer containing a message
     * @throws IOException if an I/O error occurs
     */
    public void write(ByteBuffer payload) throws IOException {
        header.clear();
        putUnsignedShort(header, payload.remaining());
        header.flip();

        do {
            channel.write(header);
        } while (header.hasRemaining());

        do {
            channel.write(payload);
        } while (payload.hasRemaining());
    }

    @Override
    public void close() throws IOException {
        channel.close();
    }

}

@@ -149,41 +149,8 @@
 le;%0A
-import java.io.FileOutputStream;%0A
 impo
@@ -188,28 +188,32 @@
 java.io.
-OutputStream
+RandomAccessFile
 ;%0Aimport
@@ -263,54 +263,11 @@
 els.
-Channels;%0Aimport java.nio.channels.WritableByt
+Fil
 eCha
@@ -396,258 +396,515 @@
 ate 
-WritableByteChannel channel;%0A%0A    private ByteBuffer header;%0A%0A    /**%0A     * Create a BinaryFILE writer.%0A     *%0A     * @param stream an output stream%0A     */%0A    public BinaryFILEWriter(OutputStream stream) %7B%0A        this(Channels.newChannel(stream))
+static final long DEFAULT_SIZE = 128 * 1024 * 1024;%0A%0A    private static final ByteBuffer EMPTY_BUFFER = ByteBuffer.allocate(0);%0A%0A    private RandomAccessFile file;%0A%0A    private FileChannel channel;%0A%0A    private long size;%0A%0A    private long position;%0A%0A    private ByteBuffer buffer;%0A%0A    private BinaryFILEWriter(RandomAccessFile file, long size) %7B%0A        this.file = file;%0A%0A        this.channel = file.getChannel();%0A%0A        this.size = size;%0A%0A        this.position = 0;%0A%0A        this.buffer = EMPTY_BUFFER
 ;%0A  
@@ -927,14 +927,12 @@
   * 
-Create
+Open
  a B
@@ -974,52 +974,45 @@
 ram 
-channel an output channel%0A     */%0A    public
+file the output file%0A     * @return a
  Bin
@@ -1022,122 +1022,184 @@
 FILE
-W
+ w
 riter
-(WritableByteChannel channel) %7B%0A        this.channel = channel;%0A%0A        this.header = ByteBuffer.allocate(2
+%0A     * @throws IOException if an I/O error occurs%0A     */%0A    public static BinaryFILEWriter open(File file) throws IOException %7B%0A        return open(file, DEFAULT_SIZE
 );%0A 
@@ -1279,32 +1279,88 @@
 the output file%0A
+     * @param size the size of the memory-mapped region%0A
      * @return a
@@ -1477,32 +1477,43 @@
 r open(File file
+, long size
 ) throws IOExcep
@@ -1531,118 +1531,74 @@
     
-FileOutputStream stream = new FileOutputStream(file);%0A%0A        return new BinaryFILEWriter(stream.getChannel()
+return new BinaryFILEWriter(new RandomAccessFile(file, %22rw%22), size
 );%0A 
@@ -1827,24 +1827,78 @@
     
-header.clear
+if (buffer.remaining() %3C 2 + payload.remaining())%0A            map
 ();%0A
+%0A
     
@@ -1918,20 +1918,20 @@
 edShort(
-head
+buff
 er, payl
@@ -1960,171 +1960,158 @@
     
-header.flip(
+buffer.put(payload
 );%0A
-%0A
     
+%7D%0A%0A
     
-do %7B%0A            channel.write(header);%0A        %7D while (header.hasRemaining());%0A%0A        do %7B%0A            channel.write(payload
+@Override%0A    public void close() throws IOException %7B%0A        file.setLength(position + buffer.position()
 );%0A
+%0A
         
 %7D wh
@@ -2110,84 +2110,49 @@
     
-%7D while (payload.hasRemaining());%0A    %7D%0A%0A    @Override%0A    public
+file.close();%0A    %7D%0A%0A    private
  void 
-close
+map
 () t
@@ -2183,22 +2183,115 @@
     
-channel.close(
+position += buffer.position();%0A%0A        buffer = channel.map(FileChannel.MapMode.READ_WRITE, position, size
 );%0A 

Improve BinaryFILE write performance