从多个方法读取单个InputStream [英] Reading single InputStream from multiple methods

查看:117
本文介绍了从多个方法读取单个InputStream的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经在类中的单个方法中初始化了一个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 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.

换句话说,您声称:


不。 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆