You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中校验歌曲是否已存在于TXT文件时重复添加的问题

如何正确校验歌曲是否已存在于TXT文件中

当前要实现的功能是将Song对象信息写入TXT文件,写入前需要校验是否存在同名且同歌手的歌曲,但现有代码每次用相同测试对象运行都会重复添加,控制台多次输出"variable changed"。

原问题代码

static void addSong(Song song){
        Boolean SongAlreadyExists = true;

        // 逐字符比较至ARTIST字段,校验歌曲是否已存在
        String lineToAdd = "NAME:" + song.name + "|ARTIST:" + song.artist;
        
        try {
            FileReader fReader = new FileReader("songs.txt");
            BufferedReader bReader = new BufferedReader(fReader);
            String line;             

            while((line = bReader.readLine()) != null){
                for (int i=0; i < lineToAdd.length(); i++){
                    if (line.charAt(i) != lineToAdd.charAt(i)){
                        SongAlreadyExists = false;
                        System.out.println("variable changed");
                    }
                }
            }
            bReader.close();
            fReader.close();

        } catch (IOException exception){
            System.out.println("file not found");
        }

        // 若歌曲不存在,则将其添加至歌曲列表文本文件
        if (! (SongAlreadyExists)){
           System.out.println("Adding song");
            try {
                FileWriter fileWriter = new FileWriter("songs.txt", true);
                fileWriter.write("\nNAME:" + song.name + "|ARTIST:" + song.artist + "|ALBUM:" + song.album + "|YEAR:" + song.year + "|");
                fileWriter.close();
            } catch (Exception exception){
                System.out.println("error");
            }
        }
}

测试用TXT数据

NAME:TestName|ARTIST:TestArtist|ALBUM:TestAlbum|YEAR:2005|

问题根源

  • 初始值逻辑颠倒:SongAlreadyExists初始设为true,但正确逻辑应该是默认歌曲不存在,找到匹配项后再标记为存在。
  • 逐字符对比逻辑缺陷:
    1. 只要某一行和目标字符串有一个字符不同,就将SongAlreadyExists设为false,但后续如果遇到匹配行,这个值不会重新设为true。
    2. 文件中每行的长度比lineToAdd长(包含专辑、年份字段),逐字符对比到lineToAdd长度时,后续字符不匹配会直接触发判断,导致误判。
  • 未及时终止遍历:找到匹配歌曲后仍继续读取文件,既浪费资源又可能覆盖正确的标记状态。

正确实现思路

  1. 初始化songAlreadyExists为false,默认歌曲不存在。
  2. 对文件每行内容,通过分割字符串提取NAME和ARTIST字段,直接和待添加歌曲的对应字段对比,避免逐字符对比的局限性。
  3. 一旦找到匹配项,立即标记songAlreadyExists为true并终止循环,停止读取文件。
  4. 使用try-with-resources自动管理文件流,避免手动关闭流时出现异常导致资源泄漏。

修正后的代码

static void addSong(Song song) {
    boolean songAlreadyExists = false; // 初始默认歌曲不存在
    String targetName = song.name;
    String targetArtist = song.artist;

    // try-with-resources自动关闭流,无需手动调用close()
    try (BufferedReader bReader = new BufferedReader(new FileReader("songs.txt"))) {
        String line;
        while ((line = bReader.readLine()) != null) {
            // 按|分割每行的字段
            String[] fields = line.split("\\|");
            String currentName = "";
            String currentArtist = "";

            // 提取当前行的NAME和ARTIST字段值
            for (String field : fields) {
                if (field.startsWith("NAME:")) {
                    currentName = field.substring(5); // 截取NAME:之后的内容
                } else if (field.startsWith("ARTIST:")) {
                    currentArtist = field.substring(7); // 截取ARTIST:之后的内容
                }
            }

            // 对比名称和歌手,完全匹配则标记为已存在并终止循环
            if (targetName.equals(currentName) && targetArtist.equals(currentArtist)) {
                songAlreadyExists = true;
                break;
            }
        }
    } catch (IOException exception) {
        System.out.println("读取文件失败: " + exception.getMessage());
    }

    // 根据校验结果执行添加操作
    if (!songAlreadyExists) {
        System.out.println("添加歌曲");
        try (FileWriter fileWriter = new FileWriter("songs.txt", true)) {
            String newSongLine = "\nNAME:" + targetName + "|ARTIST:" + targetArtist + "|ALBUM:" + song.album + "|YEAR:" + song.year + "|";
            fileWriter.write(newSongLine);
        } catch (Exception exception) {
            System.out.println("写入文件失败: " + exception.getMessage());
        }
    } else {
        System.out.println("该歌曲已存在,无需重复添加");
    }
}

改进点说明

  • 字段精准对比:通过分割提取字段的方式,只对比关键的名称和歌手信息,不受行内其他字段影响,判断更准确。
  • 资源安全管理:try-with-resources会在代码块结束后自动关闭文件流,避免因异常导致的资源泄漏。
  • 逻辑高效清晰:找到匹配项后立即终止循环,减少不必要的IO操作;初始值和判断逻辑符合直观认知,更易维护。
  • 错误信息优化:捕获异常时输出具体错误内容,便于定位问题。

内容的提问来源于stack exchange,提问作者Abriel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 08:56:05