当前位置: 首页 > 面试题库 >

大字节缓冲区的BufferedReader吗?

巢德华
2023-03-14
问题内容

有没有一种方法可以使用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有什么好处?

调用toString()ByteArrayOutputStream像一个坏主意的声音对我来说,即使你必须为它的空间:更好地得到它作为一个字节数组,敷在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,然后就可以离开了。



 类似资料:
  • 问题内容: 根据文档,使用默认缓冲区大小,而第二个构造函数允许设置缓冲区大小。 public BufferedReader(Reader in) 创建使用默认大小的输入缓冲区的缓冲字符输入流。 但是,文档没有提到默认的缓冲区大小是多少。 BufferedReader的默认缓冲区大小是多少? 问题答案: 默认缓冲区大小为8192个字符 http://developer.android.com/ref

  • 根据文档,使用默认缓冲区大小,而第二个构造函数,允许设置缓冲区大小。 公共缓冲区读取器(读取器输入) 创建使用默认大小的输入缓冲区的缓冲字符输入流。 但是,文档没有提到默认缓冲区大小。 BufferedReader的默认缓冲区大小是多少?

  • 问题内容: 构造函数中的缓冲区大小是什么意思? 当我编写程序时: 输出: 然后,缓冲区大小是什么意思,正如我希望的那样,它只能读取两个字符。但事实并非如此。 问题答案: 顾名思义,缓冲输入。这意味着它会在将输入源传递给您之前从输入源读取到缓冲区。此处的缓冲区大小是指其缓冲的字节数。 从大多数来源读取输入非常慢。仅2个字节的缓冲区将损害性能,因为您的程序很可能大部分时间都在等待输入。缓冲区大小为2时

  • 问题内容: 我正在使用类在缓冲区中逐行读取。当读取缓冲区的最后一行时,我想再次从缓冲区的开头开始读取。我已经阅读过有关和的信息,我不确定它的用法,但我认为它们不能帮助我。 有人知道到达最后一行后如何从缓冲区的开头开始读取吗?像我们可以使用的? 问题答案: 标记/重置是您想要的,但是您不能真正在BufferedReader上使用它,因为它只能重置一定数量的字节(缓冲区大小)。如果您的文件大于该文件,

  • 我已经在网上搜索了几天这种现象,我可以找到一个类似问题的片段,这表明可能与底层的InputStreamReader和/或StreamDecoder有关,但这开始超出了我的专业知识。(见本链接) 所以我的问题是,我是否正确地实现了BufferedReader,以及如何解决我所看到的问题,以便在没有不必要的延迟的情况下获得每一行。

  • 我目前正在处理一些小的endian二进制数据,我已经到了一个尴尬的地步,需要将奇数字节转换成整数值。 现在使用类,我能够很好地使用函数读取int和long,它们分别读取4和8个字节。 然而,在本例中,我需要读取三个字节,并将它们转换为int。我尝试过使用(2字节1字节),但我认为这不是正确的方法。 我猜我需要对字节进行位移位才能得到正确的int值,但我总是对位移位感到困惑。 此外,我还以为字节缓冲