从多个方法读取单个InputStream [英] Reading single InputStream from multiple methods
问题描述
我已经在类中的单个方法中初始化了一个InputStream,并将其传递给下一个方法进行处理。 InputStream基本上封装了CSV文件以供处理。
I have initialized an InputStream in a single method in a class and passing it to next method for processing. The InputStream essentially encapsulates CSV file for processing.
另一种方法调用2个不同的方法,传入相同的InputStream,一个用于检索头,另一个用于处理内容。该结构如下所示:
Another method calls 2 different methods passing in same InputStream one for retrieving headers and another for processing contents. The structure looks something as given below:
main() {
FileInputStream fis = new FileInputStream("FileName.CSV");
BufferedInputStream bis = new BufferedInputStream(fis);
InputStreamReader isr = new InputStreamReader(bis);
processCSV(isr);
}
processCSV(Reader isr) {
fetchHeaders(isr);
processContentRows(isr);
}
fetchHeaders(Reader isr) {
//Use BufferedReader to retrieve first line of CSV
//Even tried mark() and reset() here
}
processContentRows(Reader isr) {
//Cannot read the values, fetches null from InputStream :(
}
我在这里做错了什么?有什么方法可以在不同的方法调用中重用InputStream。
Am I doing something wrong here? Is there any way I can reuse InputStream across different method calls.
我正在制定可以模仿以下问题的完整程序:
I am putting up complete program that can mimic the issue below:
import java.io.FileInputStream;
import java.io.BufferedInputStream;
import java.io.InputStreamReader;
import java.io.BufferedReader;
public class MarkResetTest
{
public static void main(String a[])
{
FileInputStream fis = null;
BufferedInputStream bis = null;
InputStreamReader isr = null;
BufferedReader br = null;
BufferedReader br2 = null;
try {
fis = new FileInputStream("C:/Test/Customers.csv");
bis = new BufferedInputStream(fis);
isr = new InputStreamReader(bis, "Unicode");
System.out.println("BR readLine()");
br = new BufferedReader(isr);
//System.out.println(br.markSupported());
br.mark(1000);
System.out.println(br.readLine());
br.reset();
//System.out.println(br.readLine());
System.out.println("BR2 readLine()");
br2 = new BufferedReader(isr);
System.out.println(br2.readLine());
}
catch(Exception e) {
System.out.println("Exception::" + e);
}
finally {
try {
br.close();
isr.close();
bis.close();
fis.close();
}
catch(Exception e) {
System.out.println("Exception while closing streams :: " + e);
}
}
}
}
推荐答案
问题在于在同一个 Reader
之上创建两个 BufferedReader
。当您从 BufferedReader
读取数据时,它可能会读取超过它返回的数据到其缓冲区(因此名称)。换句话说,即使你只读了 BufferedReader
中的一行, InputStreamReader
也可能有一行从中读取更多数据 - 所以如果你再次从那个 InputStreamReader
中读取,那么你会错过这些数据。数据实际上是从 InputStreamReader
到 BufferedReader
,所以将其发送到客户端代码的唯一方法是从 BufferedReader
中读取它。
The problem is in creating two BufferedReader
s on top of the same Reader
. When you read data from BufferedReader
, it's likely to read more than the data it returns, into its buffer (hence the name). In other words, even though you've only read a single line from the BufferedReader
, the InputStreamReader
may have had a lot more data read from it - so if you read again from that InputStreamReader
then you'll miss that data. The data has effectively been sucked from the InputStreamReader
to the BufferedReader
, so the only way of getting it out to client code is to read it from that BufferedReader
.
换句话说,您声称:
不。 fetchHeaders()只读取包含标题的CSV的第一行。
Nope. fetchHeaders() only reads first line of CSV containing Headers.
不正确。只有使用那么多数据,但从 InputStreamReader
中读取更多。
is incorrect. It only uses that much data, but it reads more from the InputStreamReader
.
正如Ilya所说,你应该只在原来的 InputStreamReader
之上创建一个 BufferedReader
,并将其传递给两种方法。
As Ilya said, you should only create one BufferedReader
on top of the original InputStreamReader
, and pass that into both methods.
fetchHeaders
然后可以使用 BufferedReader
读取一行, processContentRows
可以用 BufferedReader
做它喜欢的东西 - 它是只要它需要知道读者
。
fetchHeaders
can then use that BufferedReader
to read a line, and processContentRows
can do what it likes with the BufferedReader
at that point - it's just a Reader
as far as it needs to know.
所以稍微修改Ilya的例子:
So to modify Ilya's example slightly:
public static void main(String[] args) {
FileInputStream fis = new FileInputStream("FileName.CSV");
BufferedInputStream bis = new BufferedInputStream(fis);
InputStreamReader isr = new InputStreamReader(bis);
BufferedReader br = new BufferedReader(isr);
processCSV(br);
}
private static void processCSV(BufferedReader reader) {
fetchHeaders(reader);
processContentRows(reader);
}
private static void fetchHeaders(BufferedReader reader) {
// Use reader.readLine() here directly... do *not* create
// another BufferedReader on top.
}
private static void processContentRows(Reader reader) {
// This could be declared to take a BufferedReader if you like,
// but it doesn't matter much.
}
这篇关于从多个方法读取单个InputStream的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!