在迭代文本文件时嵌套while循环的奇怪行为

时间:2017-09-28 16:29:26

标签: java loops while-loop

我是java的新手。我试图迭代几个.txt文件来比较文件的一行到第二个文件的每一行。这些是我的两个文件:listread.txtcsvread.txt

以下是我正在使用的代码:

try {
        BufferedReader csvReader = new BufferedReader(new FileReader("/data/csvread.txt"));
        BufferedReader listReader = new BufferedReader(new FileReader("/data/list.txt"));
        String csvItem, listItem;
        int count =0;
        while((csvItem = csvReader.readLine()) != null){
            System.out.println("before second loop:"+csvItem);
            while ((listItem = listReader.readLine())!= null) {
                System.out.println("list Item: "+listItem.toLowerCase().split("¬")[1]);
                System.out.println("csv Item: "+csvItem.toLowerCase());
                if(listItem.toLowerCase().split("¬")[1].contains(csvItem.toLowerCase())){
                        count++;
                }
             }
        }

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

当我运行此选项时,只会将csvread.txt中的第一行(存储在变量csvItem中)与listread.txt中的所有行进行比较。以下是输出示例:

before second loop:Record Category   
list item: provisions
csv Item: record category    
list item: request category
csv Item: record category    
list item: elevator
csv Item: record category    
list item: assessment
csv Item: record category    
list item: associates
csv Item: record category    
list item: score
csv Item: record category    
list item: attachments
csv Item: record category

它只使用list.txt文件的第一行迭代csvread.txt文件的所有行。不会移到csvread.txt的第二行,程序会在最后一行中抛出错误:

java.lang.ArrayIndexOutOfBoundsException: 1
    at test.main(test.java:52)

指的是System.out.println("list item: "+listItem.toLowerCase().split("¬")[1]);行。这句话与我猜的迭代无关。不知道为什么会抛出这个错误..

但是,当我注释掉第二个for循环时,它会在csvread.txt文件中的所有行上进行精细迭代。这是一个示例输出,只有第一个while循环和第二个循环注释掉:

before second loop:Record Category   
before second loop:Type 
before second loop:Name
before second loop:State
before second loop:Number
before second loop:ID (Self)
before second loop:Parent
before second loop:Title

仅当存在嵌套循环时才会出现此问题。当有一个循环时,根本没有问题。有人可以对这种奇怪的行为有所了解吗?我该如何克服它?

修改 我添加了一个if条件来检查该行是否包含¬,因为我在该字符上拆分了该行:

 if(listItem.contains("¬")){
        System.out.println("list item: "+listItem.toLowerCase().split("¬")[1]);
        System.out.println("csv Item: "+csvItem.toLowerCase());
        if(listItem.toLowerCase().split("¬")[1].contains(csvItem.toLowerCase())){
                count++;
         }
   }

不,我不再得到例外。但是,这种行为仍然很奇怪。这是添加if后的输出:

before second loop:Record Category   
    list item: provisions
    csv Item: record category    
    list item: request category
    csv Item: record category    
    list item: elevator
    csv Item: record category    
    list item: assessment
    csv Item: record category    
    list item: associates
    csv Item: record category    
    list item: score
    csv Item: record category    
    list item: attachments
    csv Item: record category
    before second loop:Type 
    before second loop:Name
    before second loop:State
    before second loop:Number
    before second loop:ID (Self)
    before second loop:Parent
    before second loop:Title

现在正在csvread.txt中迭代其他元素,但除了第一个元素之外,与listread.txt中的行的比较并没有变化。

任何帮助将不胜感激。谢谢!

3 个答案:

答案 0 :(得分:0)

使用嵌套循环时,内部循环会完全执行。然后执行控制来自内部循环并开始外部循环的下一次迭代。因此,如果要逐行比较两个文件的内容,则不应该有任何内部循环。以下是您在此案例中可能尝试执行的示例代码。虽然,我还没有测试过它。

try {
    BufferedReader csvReader = new BufferedReader(new FileReader("/data/csvread.txt"));
    BufferedReader listReader = new BufferedReader(new FileReader("/data/list.txt"));
    String csvItem, listItem;
    int count =0;
    while((csvItem = csvReader.readLine()) != null){
        System.out.println("before second loop:"+csvItem);
        listItem = listReader.readLine();
        if (listItem != null){
            if(listItem.toLowerCase().split("¬")[1].contains(csvItem.toLowerCase())){
                    count++;
            }
        }else{
            //The listItem has no more lines to compare, so ending the process.
            break;
        }
    }

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

我希望这会有所帮助。

注意:上面给出的答案是相信要求是逐行比较两个文件的内容。

答案 1 :(得分:0)

您对

的访问权限
listItem.toLowerCase().split("¬")[1]

很关键,因为你总是希望所有的线都有你的“¬”。如果不是这种情况,你的分割将不会返回一个数组,你访问位置[1]的returend数组失败并返回IndexOutOfBounds ....

答案 2 :(得分:0)

扩展了我在第一次迭代后指向文件末尾的listReader的评论。 BufferedReader没有提供移动文件指针的机制,因此一个简单的方法是将listReader的创建移到外部循环中:

try {
    BufferedReader csvReader = new BufferedReader(new FileReader("/data/csvread.txt"));
    // BufferedReader listReader = new BufferedReader(new FileReader("/data/list.txt"));
    String csvItem, listItem;
    int count =0;
    while((csvItem = csvReader.readLine()) != null){
        System.out.println("before second loop:"+csvItem);
        BufferedReader listReader = new BufferedReader(new FileReader("/data/list.txt"));
        while ((listItem = listReader.readLine())!= null) {
            System.out.println("list Item: "+listItem.toLowerCase().split("¬")[1]);
            System.out.println("csv Item: "+csvItem.toLowerCase());
            if(listItem.toLowerCase().split("¬")[1].contains(csvItem.toLowerCase())){
                    count++;
            }
         }
    }

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

所以每次迭代都会有一个新的listReader从文件的顶部开始。

但这可能是I / O太多了。如果list.txt的大小不是太大,那么可能只读一次,解析它,并存储在Set<String>中以供以后比较:

    try (BufferedReader listReader = new BufferedReader(new FileReader("/data/list.txt"));
            BufferedReader csvReader = new BufferedReader(new FileReader("/data/csvread.txt"))) {
        String listItem = null;
        Set<String> listItems = new HashSet<>();
        while ((listItem = listReader.readLine()) != null) {
            listItems.add(listItem.toLowerCase().split("¬")[1]);
        }

        String csvItem;
        int count = 0;
        while ((csvItem = csvReader.readLine()) != null) {
            System.out.println("before second loop:" + csvItem);

            for (String item : listItems) {
                System.out.println("list Item: " + item);
                System.out.println("csv Item: " + csvItem.toLowerCase());
                if (item.contains(csvItem.toLowerCase())) {
                    count++;
                }
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

还转移到试用资源,以确保csvReaderlistReader正确关闭。