小编典典

从多种方法读取单个InputStream

java

我已经在一个类的单个方法中初始化了InputStream,并将其传递给下一个方法进行处理。InputStream本质上封装了CSV文件以进行处理。

另一个方法调用传入同一个InputStream的2个不同方法,一个用于检索标头,另一个用于处理内容。该结构如下所示:

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);
            }
        }
    }
  }

阅读 285

收藏
2020-11-30

共1个答案

小编典典

问题在于在BufferedReader同一对象上创建两个Reader。当您从中读取数据时BufferedReader,它可能会读取比返回的数据更多的内容到其缓冲区中(因此而得名)。换句话说,即使您仅从中读取了一行BufferedReaderInputStreamReader可能仍从中读取了很多数据-
因此,如果您再次读取 该行InputStreamReader,则会丢失该数据。该数据有效地被吸 InputStreamReader
BufferedReader,因此让出来给客户端代码的唯一方法是从阅读它BufferedReader

换句话说,您声称:

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

是不正确的。它仅 使用 那么多的数据,但会 从中读取 更多数据InputStreamReader

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

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.
}
2020-11-30