用于大ByteBuffer的BufferedReader?
有没有一种方法可以使用 BufferedReader 读取 ByteBuffer,而不必先将其转换为 String? 我想将相当大的 ByteBuffer 作为文本行读取,出于性能原因,我想避免将其写入磁盘。 在 ByteBuffer 上调用 toString 不起作用,因为生成的 String 太大(它会抛出 java.lang.OutOfMemoryError:Java 堆空间)。 我本以为 API 中会有一些东西可以将 ByteBuffer 包装在合适的阅读器中,但我似乎找不到合适的东西。
这是一个简短的代码示例,说明了我正在做的事情):
// 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
}
}
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
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
目前尚不清楚为什么要使用字节缓冲区来开始。 如果您有一个
InputStream
并且想要读取它的行,为什么不使用包装在BufferedReader
中的InputStreamReader
? 蔚来汽车介入有什么好处?即使您有足够的空间,在
ByteArrayOutputStream
上调用toString()
对我来说听起来也是个坏主意:最好将其作为字节数组并将其包装在ByteArrayInputStream
,然后是InputStreamReader
,如果您确实必须有一个ByteArrayOutputStream
。 如果您确实想要调用toString()
,至少使用重载,该重载采用要使用的字符编码的名称 - 否则它将使用系统默认值,即可能不是你想要的。编辑:好的,所以你真的想使用 NIO。 最终您仍然会写入
ByteArrayOutputStream
,因此您最终会得到一个包含数据的 BAOS。 如果您想避免复制该数据,则需要从ByteArrayOutputStream
派生,例如如下所示:然后您可以创建输入流,将其包装在
InputStreamReader< /code>,将其包装在
BufferedReader
中,然后就可以了。It's not clear why you're using a byte buffer to start with. If you've got an
InputStream
and you want to read lines for it, why don't you just use anInputStreamReader
wrapped in aBufferedReader
? What's the benefit in getting NIO involved?Calling
toString()
on aByteArrayOutputStream
sounds 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 aByteArrayInputStream
and 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
ByteArrayOutputStream
eventually, 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.你可以使用 NIO,但这里没有真正的需要。 正如乔恩·斯基特建议的那样:
You can use NIO, but there's no real need here. As Jon Skeet suggested:
这是一个示例:
您可以像这样使用它:
This is a sample:
And you can use it like this: