Java Scanner读取文件统计行数 实现相邻行翻转输出问题求解
功能需求
扫描输入文件,将文件内容输出到控制台,输出时每一对相邻行的顺序反转;若文件总行数为奇数,则最后一行保持原有顺序不做修改。
原实现思路
最初的实现逻辑为:首先通过while (input.hasNextLine())循环统计文件的总行数,之后初始化长度等于总行数的String数组arrayLines,再通过第二个while循环逐行读取文件内容存入数组,后续遍历数组完成相邻行交换后输出结果。
问题说明
使用两次while (input.hasNextLine())逻辑时存在三个核心问题:
- 第一次统计行数的循环没有调用
nextLine()消费内容,Scanner游标不会向前移动,会直接进入死循环,count值会无限累加 - 就算第一次循环正常读完所有内容,Scanner读取游标会停在文件末尾,没有重置输入源的情况下,第二次循环无法读取到任何行内容
- 如果仅使用单次
while (input.hasNextLine())遍历,无法提前确定总行数,不能直接初始化定长数组存储内容
原问题附带有缺陷的实现代码如下:
public static void flipLines(Scanner input) { int count = 0; while (input.hasNextLine()) { count++; } String[] arrayLines = new String[count];; while (input.hasNextLine()) { for (int i = 0; i < count; i++) { arrayLines[i] = input.nextLine(); } } if (count % 2 == 0) { for (int i = 0; i < count; i = i + 2) { String temp = arrayLines[i]; arrayLines[i] = arrayLines[i + 1]; arrayLines[i + 1] = temp; } } else { for (int i = 0; i < count - 1; i = i + 2) { String temp = arrayLines[i]; arrayLines[i] = arrayLines[i + 1]; arrayLines[i + 1] = temp; } } System.out.println(); for (int i = 0; i < arrayLines.length; i++) { System.out.println(arrayLines[i]); } input.close(); }
可行解决方案
不需要绕两次读取文件的弯,也不用提前统计总行数,直接用支持动态扩容的ArrayList<String>存储读取到的行即可,单次遍历就能完成所有行的读取。后续做相邻行反转时也不需要单独判断总行数奇偶,把循环步长设为2、终止条件设为遍历到倒数第二行即可——如果总行数是奇数,最后一行不会进入交换逻辑,自然保持原有位置。
修正后的实现代码:
import java.util.ArrayList; import java.util.List; import java.util.Scanner; public class LineFlipper { public static void flipLines(Scanner input) { List<String> lines = new ArrayList<>(); // 单次遍历读取所有行,动态扩容不需要提前定长度 while (input.hasNextLine()) { lines.add(input.nextLine()); } input.close(); // 两两交换相邻行,步长为2 for (int i = 0; i < lines.size() - 1; i += 2) { String temp = lines.get(i); lines.set(i, lines.get(i + 1)); lines.set(i + 1, temp); } // 逐行输出结果 for (String line : lines) { System.out.println(line); } } }
注:如果坚持要用定长数组实现,也可以在第一次读取时把所有内容先存在
ArrayList里,读完之后调用toArray(new String[0])转成数组即可,本质和上面的逻辑没有区别,没必要做两次文件读取的冗余操作。
内容的提问来源于stack exchange,提问作者Agrim Chhibber
相关产品推荐
相关产品推荐

