java - 大型 ByteBuffer 的 BufferedReader?

标签 java nio bufferedreader bytebuffer

有没有一种方法可以使用 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
  }
}

最佳答案

不清楚您为什么要使用字节缓冲区作为开始。如果你有一个 InputStream 并且你想为它读取行,为什么不使用 InputStreamReader 包裹在 BufferedReader ?让 NIO 参与进来有什么好处?

ByteArrayOutputStream 上调用 toString() 对我来说听起来是个坏主意,即使你有足够的空间:最好将它作为字节数组获取并包装它在一个 ByteArrayInputStream 中,然后是一个 InputStreamReader,如果你真的必须有一个 ByteArrayOutputStream。如果您真的想要调用toString(),至少使用采用字符编码名称的重载 - 否则它将使用系统默认值,即可能不是您想要的。

编辑:好的,所以你真的想使用 NIO。您最终仍在写入 ByteArrayOutputStream,因此您最终会得到一个包含数据的 BAOS。如果您想避免复制该数据,则需要从 ByteArrayOutputStream 派生,例如:

public class ReadableByteArrayOutputStream extends ByteArrayOutputStream
{
    /**
     * Converts the data in the current stream into a ByteArrayInputStream.
     * The resulting stream wraps the existing byte array directly;
     * further writes to this output stream will result in unpredictable
     * behavior.
     */
    public InputStream toInputStream()
    {
        return new ByteArrayInputStream(array, 0, count);
    }
}

然后您可以创建输入流,将其包装在 InputStreamReader 中,然后将其包装在 BufferedReader 中,然后就可以了。

关于java - 大型 ByteBuffer 的 BufferedReader?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1045632/

相关文章:

java - 如何在 AEM 中以编程方式获取复制代理?

c# - 在 C#/Java 中获取实时市场/股票报价

java - 如何使用android中的 Intent 打开存储中的特定文件夹

java - Netty Nio 在 Java 中读取来自 ChannelFuture 的即将到来的消息

java - 方法计算文件中的单词数

java - 为什么我的 BufferedReader 读取给定文件中不存在的文本?

java - BufferedReader 从未就绪(Java 中的 Socket 编程)

java - 如何为 AWS Lambda 函数指定自定义配置?

java - 读取Java目录中的所有文件(为文件分配优先级)

java - 在 Kotlin 中使用 BufferedReader 的最佳方式