gpt4 book ai didi

java - InputStreamReader 缓冲问题

转载 作者:搜寻专家 更新时间:2023-10-30 21:29:38 26 4
gpt4 key购买 nike

我正在从一个文件中读取数据,不幸的是,该文件具有两种类型的字符编码。

有标题和正文。 header 始终采用 ASCII 格式,并定义了主体编码所用的字符集。

header 的长度不固定,必须通过解析器运行以确定其内容/长度。

该文件也可能非常大,因此我需要避免将整个内容都放入内存。

所以我从一个 InputStream 开始。我最初用一个带有 ASCII 的 InputStreamReader 包装它并解码标题并提取正文的字符集。一切顺利。

然后我用正确的字符集创建一个新的 InputStreamReader,将它放在同一个 InputStream 上并开始尝试读取正文。

不幸的是,javadoc 证实了这一点,InputStreamReader 可能会选择预读以提高效率。因此,标题的阅读会咀嚼部分/全部主体。

有人对解决这个问题有什么建议吗?会手动创建一个 CharsetDecoder 并一次输入一个字节,但这是一个好主意(可能包装在自定义 Reader 实现中?)

提前致谢。

编辑:我的最终解决方案是编写一个没有缓冲的 InputStreamReader,以确保我可以在不咀嚼主体部分的情况下解析 header 。虽然这不是非常有效,但我用 BufferedInputStream 包装了原始 InputStream,所以这不会成为问题。

// An InputStreamReader that only consumes as many bytes as is necessary
// It does not do any read-ahead.
public class InputStreamReaderUnbuffered extends Reader
{
private final CharsetDecoder charsetDecoder;
private final InputStream inputStream;
private final ByteBuffer byteBuffer = ByteBuffer.allocate( 1 );

public InputStreamReaderUnbuffered( InputStream inputStream, Charset charset )
{
this.inputStream = inputStream;
charsetDecoder = charset.newDecoder();
}

@Override
public int read() throws IOException
{
boolean middleOfReading = false;

while ( true )
{
int b = inputStream.read();

if ( b == -1 )
{
if ( middleOfReading )
throw new IOException( "Unexpected end of stream, byte truncated" );

return -1;
}

byteBuffer.clear();
byteBuffer.put( (byte)b );
byteBuffer.flip();

CharBuffer charBuffer = charsetDecoder.decode( byteBuffer );

// although this is theoretically possible this would violate the unbuffered nature
// of this class so we throw an exception
if ( charBuffer.length() > 1 )
throw new IOException( "Decoded multiple characters from one byte!" );

if ( charBuffer.length() == 1 )
return charBuffer.get();

middleOfReading = true;
}
}

public int read( char[] cbuf, int off, int len ) throws IOException
{
for ( int i = 0; i < len; i++ )
{
int ch = read();

if ( ch == -1 )
return i == 0 ? -1 : i;

cbuf[ i ] = (char)ch;
}

return len;
}

public void close() throws IOException
{
inputStream.close();
}
}

最佳答案

为什么不使用 2 个 InputStream?一个用于阅读标题,另一个用于阅读正文。

第二个 InputStream 应该跳过头字节。

关于java - InputStreamReader 缓冲问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2631507/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com