javamappedbytebuffer

How to prevent MappedByteBuffer put from writing null characters at the end of file?


I am using Java's MappedByteBuffer with a fixed buffer size to write into a file, as part of an assignment. It should write character by character since the buffer size can be smaller than the line length. But the problem is that it writes the remaining positions of the buffer at the end of the file as null characters. How can I remove those null characters?

Here's an example code:

import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;

public class Main {
    public static void main(String[] args) throws IOException {
        int bufferSize = 20;
        RandomAccessFile file = new RandomAccessFile("test.txt", "rw");
        MappedByteBuffer buffer = file.getChannel().map(FileChannel.MapMode.READ_WRITE, 0, bufferSize);

        for (char c : "Line1".toCharArray()) {
            buffer.put((byte) c);
        }
        buffer.put((byte)'\n');
        for (char c : "Line2".toCharArray()) {
            buffer.put((byte) c);
        }
    }
}

And here's the output (opened with Sublime Text utf-8 encoding):


Solution

  • As indicated by Progman, truncating will fix the issue you are seeing. I duplicated what you saw using TextWrangler and show hidden characters, and then I redid it using the following code and the trailing nulls disappeared. The key change was to track the number of bytes actually written and then truncate the file to that length.

    int bufferSize = 20;
    int bytesWritten = 0;
    RandomAccessFile file = new RandomAccessFile("test.txt", "rw");
    MappedByteBuffer buffer = file.getChannel().map(FileChannel.MapMode.READ_WRITE, 0, bufferSize);
    
    for (char c: "Line1".toCharArray()) {
        buffer.put((byte) c);
        bytesWritten++;
    }
    buffer.put((byte)
        '\n');
    bytesWritten++;
    for (char c: "Line2".toCharArray()) {
        buffer.put((byte) c);
        bytesWritten++;
    }
    buffer.force(); //make sure all is written before messing with truncating
    file.getChannel().truncate(bytesWritten);