如何在Java中读取相同的文件两次?

时间:2015-12-04 10:45:38

标签: java file bufferedreader java-io

我想反击文件的行,在第二遍中我想采取每一行并操纵它。它没有编译错误,但它不能进入​​第二个while ((line = br.readLine()) != null)。 是否有不同的方法来获取文件的行(电影)并存储在数组中?

        BufferedReader br = null;

        try { // try to read the file
            br = new BufferedReader(new FileReader("movies.txt"));
            String line;
            int numberOfMovies = 0;
            while ((line = br.readLine()) != null) {
                numberOfMovies++;
            }
            Movie[] movies = new Movie[numberOfMovies]; // store in a Movie
                                                        // array every movie of
                                                        // the file
            String title = "";
            int id = 0;
            int likes = 0;
            int icounter = 0; // count to create new movie for each line
            while ((line = br.readLine()) != null) {
                line = line.trim();
                line = line.replaceAll("/t", "");
                line = line.toLowerCase();
                String[] tokens = line.split(" "); // store every token in a
                                                    // string array
                id = Integer.parseInt(tokens[0]);
                likes = Integer.parseInt(tokens[tokens.length]);
                for (int i = 1; i < tokens.length; i++) {
                    title = title + " " + tokens[i];
                }
                movies[icounter] = new Movie(id, title, likes);
                icounter++;
            }


        } catch (IOException e) {
            e.printStackTrace();
        }

6 个答案:

答案 0 :(得分:6)

这里有两件事:

  1. MovieArrayList是一次性结构:一旦你将它们读到最后,你需要explicitly rewind它们(如果它们支持倒带),或者你需要关闭它们(总是关闭你的流和读者!)并打开一个新的。

  2. 但是在这种情况下,两次传递完全没必要,只需使用动态增长的结构来收集NOT EXISTS个对象而不是数组:例如select * from tablename t1 where not exists (select 1 from tablename t2 where t2.uid = t1.uid and t2.version > t1.version)

    < / LI>

答案 1 :(得分:5)

最简单的方法是再次重置br

try { // try to read the file 
    br = new BufferedReader(new FileReader("movies.txt"));
    String line; int numberOfMovies = 0;
    while (br.hasNextLine()){
        numberOfMovies++;
    }
    br.close();
    Movie[] movies = new Movie[numberOfMovies];
    // store in a Movie
    // array every movie of
    // the file
    String title = "";
    int id = 0;
    int likes = 0;
    int icounter = 0;
    // count to create new movie for each line
    br = new BufferedReader(new FileReader("movies.txt"));
    while ((br.hasNextLine()) {
        line = line.trim();
        line = line.replaceAll("/t", "");
        line = line.toLowerCase();
        String[] tokens = line.split(" ");
        // store every token in a
        // string array
        id = Integer.parseInt(tokens[0]);
        likes = Integer.parseInt(tokens[tokens.length]);
        for (int i = 1; i < tokens.length; i++) {
            title = title + " " + tokens[i];
        }
        movies[icounter] = new Movie(id, title, likes);
        icounter++;
    }
} catch (IOException e) { e.printStackTrace(); }

我将br.nextLine() != null更改为br.hasNextLine(),因为在这种情况下,它更短,更合适。此外,它不会占用一条线。

答案 2 :(得分:1)

如果使用相同的Reader,一旦到达第二个循环,所有内容都已读取。

关闭第一个Reader,然后创建另一个Reader以再次读取。

答案 3 :(得分:1)

首先,不需要两次读取文件。

其次,为什么不使用java.nio.file.Files类来读取您的文件。

它有一个方法readAllLines(Path path, Charset cs)可以返回List<String>

然后,如果您想知道在列表中调用size()方法的行数,您可以使用该列表构建Movie个对象。

List<Movie> movieList = new ArrayList<>();

for (String line : Files.readAllLines(Paths.get("movies.txt"), Charset.defaultCharset())) {

     // Construct your Movie object from each individual line and add to the list of Movies

     movieList.add(new Movie(id, title, likes));
}

Files类的使用也减少了样板代码,因为当它完成读取意味着您不需要finally块来关闭任何内容时它将处理关闭资源。

答案 4 :(得分:0)

您正在浏览包含BufferedReader的文件,直到下一行指向null。由于您的BufferedReadernull,它甚至不会输入第二个while((line = br.readline) != null),因为第一个读取行是null

尝试获取新的BufferedReader。像这样的东西:

...
int id = 0;
int likes = 0;
int icounter = 0;
br = new BufferedReader(new FileReader("movies.txt")) //Re-initialize the br to point 
                                                      //onto the first line again
while ((line = br.readLine()) != null)
...

修改 首先关闭读者..

答案 5 :(得分:0)

这是本帖子中已有的其他几个答案的组合,但这就是我如何重写代码以填充List。这双重解决了以下问题:1)需要两次读取文件2)使用BufferedReader删除样板文件,同时使用Java8 Streams尽可能简洁地初始化List:

private static class Movie {
    private Movie(int id, String title, int likes) {
        //TODO: set your instance state here
    }
}

private static Movie movieFromFileLine(String line) {
    line = line.trim();
    line = line.replaceAll("/t", "");
    line = line.toLowerCase();
    String[] tokens = line.split(" "); // store every token in a

    String title = "";
    int id = Integer.parseInt(tokens[0]);
    int likes = Integer.parseInt(tokens[tokens.length]);
    for (int i = 1; i < tokens.length; i++) {
        title = title + " " + tokens[i];
    }
    return new Movie(id, title, likes);
}

public static void main(String[] args) throws IOException {
    List<Movie> movies = Files.readAllLines(Paths.get("movies.txt"), Charset.defaultCharset()).stream().map
            (App::movieFromFileLine).collect(Collectors.toList());
    //TODO: Make some magic with your list of Movies
}

对于绝对需要两次读取源(文件,URL或其他)的情况,您需要知道内容很可能在第一次和第二次读数之间发生变化并准备好处理那些差异。

如果您可以合理地假设源的内容适合内存并且您的代码完全期望在Readers / InputStream的多个实例上工作,那么您可以首先考虑使用{{{I]的适当IOUtils.copy方法。 3}}读取源的内容并将其复制到ByteArrayOutputStream以创建一个可以反复重读的byte []。