sdicola
sdicola

Reputation: 962

Java NIO ByteBuffer: put and get strings

I've the following test code. I'd like to know how I can put, and get a String using a Java NIO ByteBuffer. I've added two comments where I need help.

package testPipe;

import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;

public class TestMemBuff {

    static final String dataFile = "invoicedata";
    static final double[] prices = { 19.99, 9.99, 15.99, 3.99, 4.99 };
    static final int[] units = { 12, 8, 13, 29, 50 };
    static final String[] descs = { "Java T-shirt", "Java Mug",
            "Duke Juggling Dolls", "Java Pin", "Java Key Chain" };

    public static Charset charset = Charset.forName("UTF-8");
    public static CharsetEncoder encoder = charset.newEncoder();
    public static CharsetDecoder decoder = charset.newDecoder();

    public static void main(String[] args) throws UnsupportedEncodingException {

        double price;
        int unit;
        String desc;
        double total = 0.0;

        ByteBuffer buf = ByteBuffer.allocate(1024);


        for (int i = 0; i < prices.length; i++) {
            buf.putDouble(prices[i]);
            buf.putInt(units[i]);
            buf.asCharBuffer().put(descs[i]);           // Is it correct?
        }

        buf.flip();

        // INPUT
        while (buf.hasRemaining()) {

            price = buf.getDouble();
            unit = buf.getInt();
            desc =  buf.asCharBuffer().toString();       //This must be wrong!
            System.out.format("You ordered %d" + " units of %s at $%.2f%n",
                    unit, desc, price);
            total += unit * price;
        }
    }

}

This is the output when I execute it:

You ordered 12 units of ????
[...]

and so on.

Thanks for your attention

Upvotes: 2

Views: 13663

Answers (2)

user3161880
user3161880

Reputation: 1055

Writing part:

for (int i = 0; i < prices.length; i++) {
    buf.putDouble(prices[i]);
    buf.putInt(units[i]);

    byte[] descsBytes = descs[i].getBytes();
    buf.putInt(descsBytes.length);
    buf.put(descsBytes);
}

Reading part:

while (buf.hasRemaining()) {

    price = buf.getDouble();
    unit = buf.getInt();

    int len = buf.getInt();
    byte[] bytes = new byte[len]; 
    buf.get(bytes);
    desc = new String(bytes);

    System.out.format("You ordered %d" + " units of %s at $%.2f%n",
                unit, desc, price);
    total += unit * price;
}

Upvotes: 7

Robert Panzer
Robert Panzer

Reputation: 1519

ByteBuffer.asCharBuffer() has a somewhat own behaviour. It creates a new buffer that shares the content with the ByteBuffer but has an own, independent position & limit. So put() and get() on the CharBuffer do not change the position on the ByteBuffer!

So I would refrain from using ByteBuffer.asCharBuffer() at all as long as this is not exactly what you need.

So the solution would be to write and read the bytes into the original ByteBuffer:

buf.putInt(descs[i].length);
buf.put(descs[i].getBytes());`

To read the string again read the length and allocate the byte[] yourself:

int stringLength = buf.getInt();
byte[] bytes = new byte[stringLength];
buf.get(bytes);
desc = new String(bytes);

Upvotes: 1

Related Questions