Java 从多个方法读取单个InputStream
我已经在类中的单个方法中初始化了InputStream,并将其传递给下一个方法进行处理。InputStream本质上封装了用于处理的CSV文件 另一个方法调用两个不同的方法,传递相同的InputStream,一个用于检索头,另一个用于处理内容。结构如下所示:Java 从多个方法读取单个InputStream,java,inputstream,java-io,Java,Inputstream,Java Io,我已经在类中的单个方法中初始化了InputStream,并将其传递给下一个方法进行处理。InputStream本质上封装了用于处理的CSV文件 另一个方法调用两个不同的方法,传递相同的InputStream,一个用于检索头,另一个用于处理内容。结构如下所示: main() { FileInputStream fis = new FileInputStream("FileName.CSV"); BufferedInputStream bis = new BufferedInputStrea
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
我正在建立一个完整的程序,可以模拟以下问题:
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);
}
}
}
}
你没有做错什么。只需确保打开流/读取器的方法也会在finally块中关闭它。您没有做错任何事情。只需确保打开流/读取器的方法也会在finally块中关闭它。如果需要BufferedReader,我认为需要在main方法中创建它:
main() {
FileInputStream fis = new FileInputStream("FileName.CSV");
BufferedInputStream bis = new BufferedInputStream(fis);
InputStreamReader isr = new InputStreamReader(bis);
BufferedReader br = new BufferedReader(isr);
processCSV(br);
}
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 :(
}
如果您需要BufferedReader,我认为您需要在main方法中创建它:
main() {
FileInputStream fis = new FileInputStream("FileName.CSV");
BufferedInputStream bis = new BufferedInputStream(fis);
InputStreamReader isr = new InputStreamReader(bis);
BufferedReader br = new BufferedReader(isr);
processCSV(br);
}
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 :(
}
问题在于在同一个
读取器
上创建两个缓冲读取器。当您从BufferedReader
读取数据时,它很可能会将比返回的数据更多的数据读入其缓冲区(因此得名)。换句话说,即使您只从BufferedReader
读取了一行数据,InputStreamReader
可能从中读取了更多的数据-因此,如果您再次从该InputStreamReader
读取数据,您将丢失该数据。数据已经从InputStreamReader
有效地被吸入到BufferedReader
,因此将数据输出到客户端代码的唯一方法是从该BufferedReader
读取数据
换句话说,您的声明:
没有。fetchHeaders()只读取包含标题的CSV的第一行
这是不正确的。它只使用了那么多数据,但它从InputStreamReader
读取的数据更多
正如Ilya所说,您应该只在原始的InputStreamReader
上创建一个BufferedReader
,并将其传递到这两个方法中
fetchHeaders
然后可以使用该BufferedReader
读取一行,而processContentRows
此时可以使用BufferedReader
执行它喜欢的操作-就其所需知,它只是一个Reader
因此,稍微修改一下伊利亚的例子:
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.
}
问题在于在同一个读取器
上创建两个缓冲读取器。当您从BufferedReader
读取数据时,它很可能会将比返回的数据更多的数据读入其缓冲区(因此得名)。换句话说,即使您只从BufferedReader
读取了一行数据,InputStreamReader
可能从中读取了更多的数据-因此,如果您再次从该InputStreamReader
读取数据,您将丢失该数据。数据已经从InputStreamReader
有效地被吸入到BufferedReader
,因此将数据输出到客户端代码的唯一方法是从该BufferedReader
读取数据
换句话说,您的声明:
没有。fetchHeaders()只读取包含标题的CSV的第一行
这是不正确的。它只使用了那么多数据,但它从InputStreamReader
读取的数据更多
正如Ilya所说,您应该只在原始的InputStreamReader
上创建一个BufferedReader
,并将其传递到这两个方法中
fetchHeaders
然后可以使用该BufferedReader
读取一行,而processContentRows
此时可以使用BufferedReader
执行它喜欢的操作-就其所需知,它只是一个Reader
因此,稍微修改一下伊利亚的例子:
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.
}
请在fetchHeaders和processContentRows中显示一些代码。例如,fetchHeaders是否真的会一直读取到数据结束,而不是在报头结束时停止读取?否。fetchHeaders()只读取包含标题的CSV的第一行。语句是br.readLine(),它不在循环中。那么,你能想出一个简短但完整的程序来演示这个问题吗?嗨,Jon,我用示例程序编辑了我的文章。您现在可以签出吗?请在fetchHeaders和processContentRows中显示一些代码。例如,fetchHeaders是否真的会一直读取到数据结束,而不是在报头结束时停止读取?否。fetchHeaders()只读取包含标题的CSV的第一行。语句是br.readLine(),它不在循环中。那么,你能想出一个简短但完整的程序来演示这个问题吗?嗨,Jon,我用示例程序编辑了我的文章。您现在可以签出吗?流在main()中打开,在main()中关闭。其他方法只是使用适当的读取方法来读取内容。流在main()中打开,在main()中关闭。其他方法只是使用适当的读取方法来读取内容。问题在于fetchHeaders()使用的是BufferedReader。processContentRows()使用其他读取器来处理这些行。好的,BufferedReader也是一个读取器。您可以像使用InputStreamReader一样将其包装到自定义读取器中。这也可能会给您带来一些性能改进(因为缓冲)。@mayur:Ilya的回答是正确的,但我添加了我自己的代码示例,更详细一些,更完整一些(IMO)。问题在于fetchHeaders()使用的是BufferedReader。processContentRows()使用其他读取器来处理这些行。好的,BufferedReader也是一个读取器。您可以像使用InputStreamReader一样将其包装到自定义读取器中。这也可能会给您带来一些性能改进(因为缓冲)。@mayur:Ilya的回答是正确的,但我添加了我自己的代码示例,更详细一些,更完整一些(IMO)