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

使用RandomAccessFile保存用户输入至二进制文件时特殊字符显示异常求助

解决波兰语特殊字符写入二进制文件后显示问号的问题

结合你提供的代码和JDK8的限制,我判断问题主要出在用户输入的编码处理环节——RandomAccessFile的writeUTF()和readUTF()是配对的Modified UTF-8实现,本身不会导致波兰语特殊字符(ą, ć, ę等)乱码,核心问题是输入读取时的编码与控制台实际编码不匹配,导致字符串在存入内存时就已经损坏了。

下面是具体的修复方案:

1. 修复输入读取的编码适配问题

Windows CMD(包括NetBeans内置控制台在Windows下的环境)默认使用的是CP1250编码(波兰语专属编码),而你的代码强制指定Scanner用UTF-8读取,这就导致输入的特殊字符被错误解码,最终存储的是损坏的字符,写入文件后自然显示为问号。

方案一:动态适配控制台编码

修改podajDana方法中的Scanner初始化逻辑,自动识别系统并使用对应编码:

static String podajDana(String[] tab, int coPokazac){
    System.out.print(tab[coPokazac]);
    boolean podawajDalej = true;
    String linia = "";
    
    // 动态获取控制台编码:Windows用CP1250,其他系统用默认UTF-8
    String encoding = System.getProperty("file.encoding");
    if (System.getProperty("os.name").toLowerCase().contains("win")) {
        encoding = "CP1250";
    }
    
    Scanner klawiatura = new Scanner(System.in, encoding);
    do{
        try {
            podawajDalej = false;
            linia = klawiatura.nextLine();
        } catch(NoSuchElementException e){
            System.err.println("Wystąpił błąd w czasie podawania wartości!" + " Spróbuj jeszcze raz!");
        } catch(IllegalStateException e){
            System.err.println("Wewnętrzny błąd programu typu 2! Zgłoś to jak najszybciej" + " razem z tą wiadomością");
        }
    }while(podawajDalej);
    return linia;
}

方案二:使用System.console()替代Scanner(更可靠)

System.console()会自动适配控制台的编码,避免手动指定编码的麻烦,同时处理输入的兼容性更好:

static String podajDana(String[] tab, int coPokazac){
    System.out.print(tab[coPokazac]);
    boolean podawajDalej = true;
    String linia = "";
    
    Console console = System.console();
    if (console != null) {
        // 使用Console读取,自动适配编码
        do{
            try {
                podawajDalej = false;
                linia = console.readLine();
            } catch(IOException e){
                System.err.println("Wystąpił błąd w czasie podawania wartości!" + " Spróbuj jeszcze raz!");
            }
        }while(podawajDalej);
    } else {
        // 回退到Scanner,适配Windows编码
        String encoding = System.getProperty("file.encoding");
        if (System.getProperty("os.name").toLowerCase().contains("win")) {
            encoding = "CP1250";
        }
        Scanner klawiatura = new Scanner(System.in, encoding);
        do{
            try {
                podawajDalej = false;
                linia = klawiatura.nextLine();
            } catch(NoSuchElementException e){
                System.err.println("Wystąpił błąd w czasie podawania wartości!" + " Spróbuj jeszcze raz!");
            } catch(IllegalStateException e){
                System.err.println("Wewnętrzny błąd programu typu 2! Zgłoś to jak najszybciej" + " razem z tą wiadomością");
            }
        }while(podawajDalej);
    }
    return linia;
}

2. 确认读取文件的方法正确

确保你读取baza.bin时,使用的是RandomAccessFile.readUTF()方法——因为writeUTF()写入的是Modified UTF-8格式,必须用对应的readUTF()才能正确解码,示例读取逻辑如下:

static ArrayList<Ksiazka> wczytajBaze(){
    ArrayList<Ksiazka> baza = new ArrayList<>();
    try{
        RandomAccessFile plik = new RandomAccessFile("baza.bin","r");
        while (plik.getFilePointer() < plik.length()) {
            Ksiazka ksiazka = new Ksiazka();
            ksiazka.ustawId(plik.readUTF());
            ksiazka.ustawTytul(plik.readUTF());
            ksiazka.ustawAutor(plik.readUTF());
            ksiazka.ustawRok(plik.readUTF());
            ksiazka.ustawWydawnictwo(plik.readUTF());
            ksiazka.ustawGatunek(plik.readUTF());
            ksiazka.ustawOpis(plik.readUTF());
            ksiazka.ustawKtoWypozyczyl(plik.readUTF());
            ksiazka.ustawKiedyWypozyczona(plik.readUTF());
            ksiazka.ustawKiedyDoOddania(plik.readUTF());
            baza.add(ksiazka);
        }
        plik.close();
    } catch (FileNotFoundException ex){
        System.err.println("Nie znaleziono pliku z bazą książek!");
    } catch (IOException ex){
        System.err.println("Błąd zapisu bądź odczytu pliku!");
    }
    return baza;
}

额外测试建议

  • 如果使用NetBeans运行程序,确保NetBeans的控制台编码确实是UTF-8:打开Tools -> Options -> Miscellaneous -> Encoding,确认设置为UTF-8。
  • 如果在CMD中手动运行程序,可以先执行chcp 65001切换到UTF-8编码,再启动程序,验证是否能正常读取特殊字符。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 04:37:31