java - RandomAccessFile 方法将用户输入保存到文件的问题
问题描述
我对用户的输入有疑问。我需要将用户的输入保存到二进制文件中,当我读取它并在屏幕上显示它时,它无法正常工作。我不想放几百行,所以我会尝试以更紧凑的形式来描述它。项目属性中 NetBeans 中的编码为“UTF-8”
我在 NetBeans 控制台或 cmd 控制台中获得了用户的输入。然后我将它保存到由字符串组成的对象中,然后将它添加到我的班级ArrayList<Ksiazka>
所在Ksiazka
的位置(基本上是一本书的属性)。然后我将整个 ArrayList 对象保存到文件 baza.bin。我通过循环遍历整个类对象列表,Ksiazka
一个一个地获取每个字符串并使用方法将其保存到文件 baza.bin 中writeUTF(oneOfStrings)
。当我尝试读取文件 baza.bin 时,我看到的是问号而不是特殊字符(ą、ć、ę、ł、ń、ó、ś、ź)。我认为文件和输入数据的编码存在差异,但老实说,我不知道如何解决这个问题。
这些是我班级的属性Ksiazka
:
private String id;
private String tytul;
private String autor;
private String rok;
private String wydawnictwo;
private String gatunek;
private String opis;
private String ktoWypozyczyl;
private String kiedyWypozyczona;
private String kiedyDoOddania;
这是从用户读取数据的方法:
static String podajDana(String[] tab, int coPokazac){
System.out.print(tab[coPokazac]);
boolean podawajDalej = true;
String linia = "";
Scanner klawiatura = new Scanner(System.in, "utf-8");
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;
}
String[] tab
只是我希望能够在屏幕上显示的字符串数组,每个集合(数组)都有自己的功能,int coPokazac
是我想要显示的数组中的行数。
这个将所有数据保存ArrayList<Ksiazka>
到文件 baza.bin 中:
static void zapiszZmiany(ArrayList<Ksiazka> bazaKsiazek){
try{
RandomAccessFile plik = new RandomAccessFile("baza.bin","rw");
for(int i = 0; i < bazaKsiazek.size(); i++){
plik.writeUTF(bazaKsiazek.get(i).zwrocId());
plik.writeUTF(bazaKsiazek.get(i).zwrocTytul());
plik.writeUTF(bazaKsiazek.get(i).zwrocAutor());
plik.writeUTF(bazaKsiazek.get(i).zwrocRok());
plik.writeUTF(bazaKsiazek.get(i).zwrocWydawnictwo());
plik.writeUTF(bazaKsiazek.get(i).zwrocGatunek());
plik.writeUTF(bazaKsiazek.get(i).zwrocOpis());
plik.writeUTF(bazaKsiazek.get(i).zwrocKtoWypozyczyl());
plik.writeUTF(bazaKsiazek.get(i).zwrocKiedyWypozyczona());
plik.writeUTF(bazaKsiazek.get(i).zwrocKiedyDoOddania());
}
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!");
}
}
我认为这两种方法中的一种存在问题(我在读取它时做错了,或者在使用 将数据保存到文件时出错了writeUTF()
),但即使我尝试了一些方法来解决它,它们都没有工作。
在与讲师快速交谈后,我得到了最多可以使用 JDK 8 的信息。
解决方案
您正在使用不同的技术进行阅读和写作,并且它们不兼容。
尽管有名字,但writeUTF
RandomAccessFile 的方法不会写入 UTF-8 字符串。从文档中:
以与机器无关的方式使用修改后的 UTF-8编码将字符串写入文件。
首先,将两个字节写入文件,从当前文件指针开始,就像通过
writeShort
给出后面字节数的方法一样。这个值是实际写出的字节数,而不是字符串的长度。在长度之后,按顺序输出字符串的每个字符,对每个字符使用修改后的 UTF-8 编码。
writeUTF 将写入一个两个字节的长度,然后将字符串写入为 UTF-8,除了'\u0000'
字符写入为两个 UTF-8 字节并且补充字符写入为两个 UTF-8 编码的代理项,而不是单个 UTF-8 代码点序列.
另一方面,您正在尝试使用new Scanner(System.in, "utf-8")
and读取该数据klawiatura.nextLine();
。这种方法不兼容,因为:
- 文本不是作为真正的 UTF-8 序列编写的。
- 在写入文本之前,写入了两个表示其数字长度的字节。它们不是可读的文本。
writeUTF
不写换行符。事实上,它根本不写任何终止序列。
最好的解决方案是删除 RandomAccessFile 的所有用法并用 Writer 替换它:
Writer plik = new FileWriter(new File("baza.bin"), StandardCharsets.UTF_8);
for (int i = 0; i < bazaKsiazek.size(); i++) {
plik.write(bazaKsiazek.get(i).zwrocId());
plik.write('\n');
plik.write(bazaKsiazek.get(i).zwrocTytul());
plik.write('\n');
// ...
推荐阅读
- flutter - 如何使用 Dart 将新用户推送到 Firebase 数据库?
- sed - 如何使用 sed 将字符串添加到文件中的特定行?
- flutter - 如何在颤动中从另一个屏幕进行更改
- npm - gatsby 的全新安装失败,找不到模块“检测端口”
- javascript - 当人们加入我的服务器时,这个不和谐的机器人不会工作?
- javascript - AssyncStorage 在构建时保存数据
- c# - 如何将变量从一个类引用到另一个类?
- python - 安装 libact 时找不到“lapacke.h”文件错误
- html - 我怎样才能让页面中间的这个边框更紧一点
- salesforce - Salesforce 编号字段默认值为(记录中的最高编号)+ 1