从多个方法中读取单个InputStream

时间:2011-08-04 10:09:50

标签: java inputstream java-io

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

3 个答案:

答案 0 :(得分:4)

问题在于在同一BufferedReader之上创建两个Reader。当您从BufferedReader读取数据时,它可能读取的数据超过它返回的数据,进入其缓冲区(因此名称)。换句话说,即使您只读取了BufferedReader中的一行,InputStreamReader也可能从中读取了更多数据 - 因此,如果您再次从中读取 { {1}} 然后你会错过这些数据。数据已经InputStreamReader <{1}}实际上被吸引,因此将其发送到客户端代码的唯一方法是读取它来自InputStreamReader

换句话说,您声称:

  

不。 fetchHeaders()只读取包含标题的CSV的第一行。

不正确。只有使用那么多数据,但BufferedReader读取更多。

正如Ilya所说,你应该只在原BufferedReader之上创建一个InputStreamReader,并将其传递给两种方法。

BufferedReader然后可以使用InputStreamReader来读取一行,而fetchHeaders可以使用BufferedReader执行它所喜欢的行 - 它只是{{1}只要它需要知道。

所以稍微修改Ilya的例子:

processContentRows

答案 1 :(得分:1)

你没有做错任何事。只需确保打开流/阅读器的方法也会在finally块中关闭它。

答案 2 :(得分:1)

如果你需要一个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 :(
}