Java:在一个InputStream上使用两个Readers

时间:2013-08-16 20:14:58

标签: java inputstream bufferedreader buffering

我的应用程序可以编辑一种名为 TDAEntry 的文本文件。每个此类条目都基于描述其格式的另一种类型的文件,称为 TDAForm TDAEntry 文本文件中的第一行是它所属表单的名称,然后是其余数据(文本格式)。

现在打开这样的文件,这是我的代码,简化:

InputStream entryInput = new FileInputStream(file);

BufferedReader entryReader = new BufferedReader(
    new InputStreamReader(entryInput)); // PROBLEMATIC #1

String formName = entryReader.readLine();

TDAForm form = new TDAForm(formName);

// create an entry with the right form and the data which follows in entryInput
TDAEntry entry = new TDAEntry(form, entryInput); // PROBLEMATIC #2

这是问题所在。在阅读InputStreamReader的源代码时,您最终会阅读此类的代码:

http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/sun/nio/cs/StreamDecoder.java#StreamDecoder.read(char%5B%5D%2Cint%2Cint)

是缓冲的,这意味着它将提前读取大约8000个字节。这导致InputStream在“有问题的#2”行处于空白并且位于错误的位置,而我希望它继续,好像只读取了文件的第一行。在 TDAEntry 的构造函数中,我可能想在流上构建另一种读者,或者做其他事情。

一个明显的解决方案是编写一个新的解码器,它不会占用前面的字节。但我想知道是否有更简单的方法来做到这一点。你会如何解决这个问题,或者你是否建议另一种编程结构来完成同样的事情?

非常感谢!

3 个答案:

答案 0 :(得分:4)

直接传入读者。它将继续阅读它停止的地方:

TDAEntry entry = new TDAEntry(form, entryReader); 

答案 1 :(得分:1)

您可以尝试将FileInputStream包装到BufferedInputStream中,因为缓冲版本支持mark()和reset()。

答案 2 :(得分:0)

如果您只想限制缓冲区,则无需编写自己的类。您可以使用第二个构造函数,即new BufferedReader(new InputStreamReader(entryInput), 20);来限制缓冲区大小。

这并不一定是解决此问题的最佳方法。基本上在空中切换流是一个非常糟糕的主意。您可以创建自己的InputStream实现,同时读取标题和条目。