Java:使用RandomAccessFile时如何正确分割文本文件的换行?
问题分析与解决方案
核心错误原因
raf.readLine()每次只读取单独一行内容,返回的字符串里不含换行符\n,所以str.split("\n")得到的数组永远只有1个元素,直接取data[1]必然触发数组越界。- 你的文本是每4行对应一组数据(名称、楼层、价格、位置),但代码里每次读一行就处理,逻辑完全错配,导致
floors等变量要么取到不存在的数组元素,要么内容不符合预期。
修复后的代码示例
import java.io.RandomAccessFile; import java.io.FileNotFoundException; import java.io.IOException; import java.text.DecimalFormat; public class FileProcessor { public static void main(String[] args) { DecimalFormat df = new DecimalFormat("#.00"); try (RandomAccessFile raf = new RandomAccessFile("domy.txt", "rw")) { String str; // 每4行读取一组完整数据 while ((str = raf.readLine()) != null) { String name = str; String floors = raf.readLine(); String price = raf.readLine(); String location = raf.readLine(); // 防止文件末尾数据不完整,提前终止 if (floors == null || price == null || location == null) { break; } System.out.println(name + " " + floors + " " + price + " " + location); if ("1".equals(floors) && "Wies".equals(location)) { int floorsInt = Integer.parseInt(floors); double priceDouble = Double.parseDouble(price); String newPrice = df.format(priceDouble * 0.9); // 计算当前组数据的起始指针位置:当前指针减去4行内容总长度+4个换行符(按LF单字节计算) long startPos = raf.getFilePointer() - (name.length() + floors.length() + price.length() + location.length() + 4); raf.seek(startPos); // 写入修改后的数据,保持换行分隔 raf.writeBytes(name + "\n" + floorsInt + "\n" + newPrice + "\n" + location + "\n"); } } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
关键修复点
- 读取逻辑修正:连续读取4行作为一组数据,直接赋值给对应变量,完全不需要split操作。
- 空值校验:处理前检查4行数据是否完整,避免文件末尾数据缺失导致的异常。
- 指针位置校准:修改数据时准确计算当前组的起始位置,确保覆盖正确的内容;注意换行符字节数(Windows系统是
\r\n占2字节,若你的文件是该格式,需把+4改为+8)。 - 空指针防护:用
"1".equals(floors)代替floors.equals("1"),避免floors为null时抛出空指针异常。
额外注意事项
writeBytes()会按ASCII编码写入字符串,若文本包含非ASCII特殊字符(比如波兰语字符),可能出现乱码,建议改用writeUTF()和readUTF(),但需注意文件格式兼容性。- 如果修改后的内容长度和原内容不一致,会覆盖后续的文件内容。比如原价格是
1000000.00(9字符),打折后是900000.00(8字符),会残留一个字节的旧内容,这种情况建议先把所有内容读入内存修改后再整体写回。
内容的提问来源于stack exchange,提问作者Janek
相关产品推荐
相关产品推荐

