读取文件的Java代码输出多余字符及序号错误问题求助
Java逐字符读取文件的两个问题及修复方案
问题说明
这段代码用于逐字符读取文本文件并打印行号、字符序号和对应字符,但存在两个明显问题:
- 序号更新逻辑错误:比如从"1 : 5 o"跳转至下一行时,本该先输出"2 : 0 "再到"2 : 1 C",实际却先输出了错误的"1 : 6 "
- 文件末尾会读取到莫名的"?"字符
原代码
public class FileReaderDemo { // 补充原代码遗漏的类定义与全局变量 private static int curr = 0; private static int line = 1; private static int ch = 0; private static BufferedReader br; private static char currChar; public static void main(String[] args) { Scanner scanner = new Scanner(System.in); String fileName = ""; System.out.print("Enter the file name: "); fileName = scanner.nextLine(); if (fileName.equalsIgnoreCase("quit") || fileName.equalsIgnoreCase("exit")) { System.out.println("Exitting..."); return; } while (!fileName.equalsIgnoreCase("quit") || !fileName.equalsIgnoreCase("exit")) { try { File file = new File(fileName); FileReader fr = new FileReader(file); br = new BufferedReader(fr); while (curr != -1) { System.out.println(position() + currentChar()); } } catch (FileNotFoundException e) { System.out.println("file not found, check file name"); break; } System.out.print("Enter the file name: "); fileName = scanner.nextLine(); if (fileName.equalsIgnoreCase("quit") || fileName.equalsIgnoreCase("exit")) { System.out.println("Exitting..."); return; } } scanner.close(); } public static String position() { String pos = line + " : " + ch + " "; return pos; } public static void nextChar(BufferedReader br) { try { curr = br.read(); if (curr == 13) { line++; ch = 0; System.out.println(line + " : " + ch + ""); nextChar(br); } else { ch++; } } catch (IOException e) { System.out.println("invalid file input"); } } public static char currentChar() { nextChar(br); currChar = (char) curr; return currChar; } }
测试输入文本
Hello COSC 455!
错误输出结果
Enter the file name: input.txt 1 : 1 H 1 : 2 e 1 : 3 l 1 : 4 l 1 : 5 o 2 : 0 1 : 6 2 : 1 C 2 : 2 O 2 : 3 S 2 : 4 C 2 : 5 2 : 6 4 2 : 7 5 2 : 8 5 2 : 9 ! 3 : 0 2 : 10 3 : 1 ?
问题分析与修复
问题1:序号输出错误的根源及解决
错误原因:
nextChar()处理回车符(ASCII 13)时直接打印新行序号,后续currentChar()会再次调用nextChar(),同时position()输出的是更新前的字符序号,导致重复输出和序号混乱。- 只处理了Windows系统的回车符(CR=13),未处理Unix系统的换行符(LF=10),导致换行后的空字符被错误计数。
- 字符序号
ch的递增时机错误,不管是否是换行符都直接递增,导致换行后的空行被计为上一行的最后一个序号。
修复方案:
- 移除
nextChar()中的打印逻辑,统一由main循环处理输出,避免重复打印。 - 同时处理CR(13)和LF(10):遇到CR时先读取后续的LF,再更新行号并重置
ch为0;遇到LF时直接更新行号重置ch。 - 调整
ch的递增逻辑:只有当读取的字符不是换行符且不是文件结束符(-1)时,才递增ch。
- 移除
问题2:末尾出现"?"的根源及解决
- 错误原因:文件读取到末尾时,
br.read()返回-1,代码依然将其强制转换为char,而(char)-1对应的Unicode字符就是?。 - 修复方案:在
currentChar()中判断curr是否为-1,此时返回空字符,后续main循环跳过输出;同时在main循环中提前判断curr是否为-1,避免处理文件结束符。
修复后的完整代码
import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.util.Scanner; public class FileReaderFixed { private static int curr; private static int line = 1; private static int ch = 0; private static BufferedReader br; public static void main(String[] args) { Scanner scanner = new Scanner(System.in); String fileName = ""; System.out.print("Enter the file name: "); fileName = scanner.nextLine(); if (fileName.equalsIgnoreCase("quit") || fileName.equalsIgnoreCase("exit")) { System.out.println("Exitting..."); return; } while (!fileName.equalsIgnoreCase("quit") && !fileName.equalsIgnoreCase("exit")) { try { File file = new File(fileName); FileReader fr = new FileReader(file); br = new BufferedReader(fr); // 重置状态变量,确保每次读新文件都是初始状态 line = 1; ch = 0; curr = br.read(); while (curr != -1) { String pos = position(); char c = currentChar(); // 避免输出文件结束符的转换字符 if (curr != -1) { System.out.println(pos + c); } } } catch (FileNotFoundException e) { System.out.println("file not found, check file name"); break; } catch (IOException e) { System.out.println("invalid file input"); } System.out.print("Enter the file name: "); fileName = scanner.nextLine(); if (fileName.equalsIgnoreCase("quit") || fileName.equalsIgnoreCase("exit")) { System.out.println("Exitting..."); return; } } scanner.close(); } public static String position() { return line + " : " + ch + " "; } public static void nextChar() throws IOException { curr = br.read(); if (curr == 13) { // 处理Windows的CRLF,跳过后续的LF curr = br.read(); line++; ch = 0; } else if (curr == 10) { // 处理Unix的LF line++; ch = 0; } else if (curr != -1) { // 不是换行符也不是文件结束,递增字符序号 ch++; } } public static char currentChar() throws IOException { nextChar(); if (curr == -1) { // 文件结束时返回空字符,后续main循环跳过输出 return '\0'; } return (char) curr; } }
修复后的预期输出
Enter the file name: input.txt 1 : 1 H 1 : 2 e 1 : 3 l 1 : 4 l 1 : 5 o 2 : 0 2 : 1 C 2 : 2 O 2 : 3 S 2 : 4 C 2 : 5 2 : 6 4 2 : 7 5 2 : 8 5 2 : 9 ! 3 : 0
内容的提问来源于stack exchange,提问作者beatmaister
相关产品推荐
相关产品推荐

