Reading single InputStream from multiple methods

后端 未结 3 433
轮回少年
轮回少年 2021-01-26 18:21

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.

相关标签:
3条回答
  • 2021-01-26 18:47

    You're not doing anything wrong. Just make sure that the method opening a stream/reader also closes it, in a finally block.

    0 讨论(0)
  • 2021-01-26 18:54

    If you need a BufferedReader, I think you need to create it in in main method:

    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 :(
    }
    
    0 讨论(0)
  • 2021-01-26 19:00

    The problem is in creating two BufferedReaders 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.

    In other words, your claim that:

    Nope. fetchHeaders() only reads first line of CSV containing Headers.

    is incorrect. It only uses that much data, but it reads more from the InputStreamReader.

    As Ilya said, you should only create one BufferedReader on top of the original InputStreamReader, and pass that into both methods.

    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.

    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.
    }
    
    0 讨论(0)
提交回复
热议问题