Is there a way to read a ByteBuffer with a BufferedReader without having to turn it into a String first? I want to read through a fairly large ByteBuffer as lines of text and for performance reasons I want to avoid writing it to the disk. Calling toString on the ByteBuffer doesn’t work because the resulting String is too large (it throws java.lang.OutOfMemoryError: Java heap space). I would have thought there would be something in the API to wrap a ByteBuffer in a suitable reader, but I can’t seem to find anything suitable.
Here’s an abbreviated code sample the illustrates what I am doing):
// input stream is from Process getInputStream()
public String read(InputStream istream)
{
ReadableByteChannel source = Channels.newChannel(istream);
ByteArrayOutputStream ostream = new ByteArrayOutputStream(bufferSize);
WritableByteChannel destination = Channels.newChannel(ostream);
ByteBuffer buffer = ByteBuffer.allocateDirect(writeBufferSize);
while (source.read(buffer) != -1)
{
buffer.flip();
while (buffer.hasRemaining())
{
destination.write(buffer);
}
buffer.clear();
}
// this data can be up to 150 MB.. won't fit in a String.
result = ostream.toString();
source.close();
destination.close();
return result;
}
// after the process is run, we call this method with the String
public void readLines(String text)
{
BufferedReader reader = new BufferedReader(new StringReader(text));
String line;
while ((line = reader.readLine()) != null)
{
// do stuff with line
}
}
It’s not clear why you’re using a byte buffer to start with. If you’ve got an
InputStreamand you want to read lines for it, why don’t you just use anInputStreamReaderwrapped in aBufferedReader? What’s the benefit in getting NIO involved?Calling
toString()on aByteArrayOutputStreamsounds like a bad idea to me even if you had the space for it: better to get it as a byte array and wrap it in aByteArrayInputStreamand then anInputStreamReader, if you really have to have aByteArrayOutputStream. If you really want to calltoString(), at least use the overload which takes the name of the character encoding to use – otherwise it’ll use the system default, which probably isn’t what you want.EDIT: Okay, so you really want to use NIO. You’re still writing to a
ByteArrayOutputStreameventually, so you’ll end up with a BAOS with the data in it. If you want to avoid making a copy of that data, you’ll need to derive fromByteArrayOutputStream, for instance like this:Then you can create the input stream, wrap it in an
InputStreamReader, wrap that in aBufferedReader, and you’re away.