Java Scanner读取文件存对象到ArrayList仅能获取最后一条如何解决
问题原因
你的代码存在两个核心问题:
- 创建
Song对象、添加到ArrayList的逻辑放在了while循环外部,整个文件扫描全程只会生成1个Song实例,存储的自然是所有字段最后被赋值的结果,也就是最后一首歌曲的信息。 - 之前你把对象创建逻辑直接移到循环内报错,是因为没有找对创建对象的时机:每首歌的信息是跨多行存储的,需要等某首歌的歌手、歌名、完整歌词全部读取完成后才能创建对象,不能每读一行就生成一个对象。
修复方案
按照你文件的格式(每首歌按ARTIST→TITLE→LYRICS+后续歌词行的顺序存储,下一首的ARTIST行是上一首结束的标记),调整逻辑如下:
- 每次读到新的
ARTIST行时,先判断之前已经有读取完成的歌曲信息,就先把上一首生成Song对象加入列表,再重置缓存字段存储新歌信息 - 循环结束后额外加一次添加操作,把最后一首没有被触发添加的歌曲加入列表
- 优化歌词拼接逻辑,避免重复拼接内容
修正后的代码:
public static void main(String[] args) throws FileNotFoundException { // 读取歌曲文件构建歌曲列表 File text = new File("short.txt"); Scanner scnr = new Scanner(text); String artist = ""; String title = ""; String lyrics = ""; ArrayList<Song> song_list = new ArrayList<Song>(); while (scnr.hasNextLine()) { String next = scnr.nextLine(); if (next.startsWith("ARTIST")) { // 读到新的歌手行,说明上一首已经读完,先把上一首加入列表 if (!artist.isBlank() && !title.isBlank()) { Song songs = new Song(artist, title, lyrics); song_list.add(songs); // 重置缓存字段,准备存新歌 artist = ""; title = ""; lyrics = ""; } artist = next.substring(8, next.length() - 1); } else if (next.startsWith("TITLE")) { title = next.substring(7, next.length() - 1); } else if (next.startsWith("LYRICS")) { lyrics = next.substring(8) + "\n"; } else { // 非标记行都是歌词内容,直接拼接 lyrics += next + "\n"; } } // 循环结束后,把最后一首歌曲加入列表 if (!artist.isBlank() && !title.isBlank()) { Song songs = new Song(artist, title, lyrics); song_list.add(songs); } // 验证输出所有歌曲 for (Song s : song_list) { System.out.println(s); } scnr.close(); }
额外说明
Scanner扫描过的内容默认不会重读,不需要额外加计数变量再开循环处理,只要在一次扫描过程中按规则缓存信息、触发对象创建就能拿到全量数据。
内容的提问来源于stack exchange,提问作者lozercold
相关产品推荐
相关产品推荐

