从多个方法读取单个InputStream
我已经在类中的单个方法中初始化了一个InputStream,并将其传递给下一个方法进行处理。 InputStream基本上封装了CSV文件以进行处理。
另一种方法调用2个不同的方法,在同一个InputStream中传递一个用于检索头,另一个用于处理内容。 该结构看起来如下所示:
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); } } } }
问题是在同一个Reader
上创建两个BufferedReader
。 当您从BufferedReader
读取数据时,它可能会读取比它返回的数据更多的内容到其缓冲区(因此名称)。 换句话说,即使您只从BufferedReader
读取一行, InputStreamReader
也可能从中读取了更多数据 – 因此,如果您再次从该InputStreamReader
读取,那么您将错过该数据。 数据实际上已从 InputStreamReader
吸引到 BufferedReader
,因此将其传递给客户端代码的唯一方法是从BufferedReader
读取数据。
换句话说,你声称:
不。 fetchHeaders()只读取包含Headers的第一行CSV。
是不正确的。 它只使用那么多数据,但它从InputStreamReader
读取更多数据。
正如Ilya所说,您应该只在原始InputStreamReader
之上创建一个BufferedReader
,并将其传递给两个方法。
然后fetchHeaders
可以使用BufferedReader
读取一行,而processContentRows
可以在那时使用BufferedReader
做它喜欢的东西 – 它只是一个Reader
,只要它需要知道。
所以稍微修改Ilya的例子:
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. }
你没有做错任何事。 只需确保打开流/阅读器的方法也会在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 :( }