ken*_*nny 13 java unicode io utf-8 textfield
我有用UTF8编码的文本文件(用于特定于语言的字符).我需要使用RandomAccessFile来寻找特定的位置并从中读取.
我想逐行阅读.
String str = myreader.readLine(); //returns wrong text, not decoded
String str myreader.readUTF(); //An exception occurred: java.io.EOFException
Run Code Online (Sandbox Code Playgroud)
小智 17
您可以使用以下代码将readLine读取的字符串转换为UTF8:
public static void main(String[] args) throws IOException {
RandomAccessFile raf = new RandomAccessFile(new File("MyFile.txt"), "r");
String line = raf.readLine();
String utf8 = new String(line.getBytes("ISO-8859-1"), "UTF-8");
System.out.println("Line: " + line);
System.out.println("UTF8: " + utf8);
}
Run Code Online (Sandbox Code Playgroud)
?????? ?? ???????
Run Code Online (Sandbox Code Playgroud)
Line: ÐÑÐ¸Ð²ÐµÑ Ð¸Ð· УкÑаинÑ
UTF8: ?????? ?? ???????
Run Code Online (Sandbox Code Playgroud)
API 文档对 readUTF8 做了以下说明
从此文件中读入字符串。该字符串已使用修改后的 UTF-8 格式进行编码。
从当前文件指针开始读取前两个字节,就像通过 readUnsignedShort 一样。该值给出编码字符串中后续字节的数量,而不是结果字符串的长度。随后的字节将被解释为以修改后的 UTF-8 格式编码字符的字节,并转换为字符。
此方法会阻塞,直到读取所有字节、检测到流末尾或引发异常。
你的字符串是这样格式化的吗?
这似乎可以解释您的 EOF 异常。
您的文件是文本文件,因此您的实际问题是解码。
我知道的最简单的答案是:
try(BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream("jedis.txt"),"UTF-8"))){
String line = null;
while( (line = reader.readLine()) != null){
if(line.equals("Obi-wan")){
System.out.println("Yay, I found " + line +"!");
}
}
}catch(IOException e){
e.printStackTrace();
}
Run Code Online (Sandbox Code Playgroud)
或者您可以使用系统属性将当前系统编码设置file.encoding为 UTF-8。
java -Dfile.encoding=UTF-8 com.jediacademy.Runner arg1 arg2 ...
Run Code Online (Sandbox Code Playgroud)
如果您只需要该特定文件,您也可以在运行时将其设置为系统属性System.setProperty(...),但在这种情况下,我认为我更喜欢OutputStreamWriter.
通过设置系统属性,您可以使用FileReaderUTF-8 作为文件的默认编码。在本例中,适用于您读取和写入的所有文件。
如果您打算检测文件中的解码错误,您将被迫使用该InputStreamReader方法并使用接收解码器的构造函数。
有点像
CharsetDecoder decoder = Charset.forName("UTF-8").newDecoder();
decoder.onMalformedInput(CodingErrorAction.REPORT);
decoder.onUnmappableCharacter(CodingErrorAction.REPORT);
BufeferedReader out = new BufferedReader(new InpuStreamReader(new FileInputStream("jedis.txt),decoder));
Run Code Online (Sandbox Code Playgroud)
您可以在操作之间进行选择IGNORE | REPLACE | REPORT
编辑
如果您坚持使用RandomAccessFile,您将需要知道您要读取的行的确切偏移量。不仅如此,为了使用readUTF()方法读取,您应该使用方法写入文件writeUTF()。因为正如 JavaDocs 上面所述,此方法需要特定的格式,其中前 2 个无符号字节表示 UTF-8 字符串的字节长度。
因此,如果您这样做:
try(RandomAccessFile raf = new RandomAccessFile("jedis.bin", "rw")){
raf.writeUTF("Luke\n"); //2 bytes for length + 5 bytes
raf.writeUTF("Obiwan\n"); //2 bytes for length + 7 bytes
raf.writeUTF("Yoda\n"); //2 bytes for lenght + 5 bytes
}catch(IOException e){
e.printStackTrace();
}
Run Code Online (Sandbox Code Playgroud)
readUTF()只要您可以确定要读回的给定行的偏移量,使用 方法 从此文件读回就不会有任何问题。
如果您打开该文件,jedis.bin您会发现它是一个二进制文件,而不是文本文件。
现在,我知道"Luke\n"UTF-8 中是 5 个字节,"Obiwan\n"UTF-8 中是 7 个字节。该writeUTF()方法将在每个字符串前面插入 2 个字节。因此,前面"Yoda\n"有(5+2) + (7+2) = 16个字节。
所以,我可以这样做来到达最后一行:
try (RandomAccessFile raf = new RandomAccessFile("jedis.bin", "r")) {
raf.seek(16);
String val = raf.readUTF();
System.out.println(val); //prints Yoda
} catch (IOException e) {
e.printStackTrace();
}
Run Code Online (Sandbox Code Playgroud)
但是,如果您使用类编写文件,则这将不起作用,Writer因为编写者不遵循该方法的格式设置规则writeUFT()。
在这种情况下,最好的办法是二进制文件的格式是所有字符串占用相同的空间量(字节数,而不是字符数,因为字节数在 UTF 中是可变的) 8 取决于字符串中的字符),如果不是所有的空间都需要它,你可以填充它:
这样您就可以轻松计算给定线的偏移量,因为它们都占用相同的空间量。
| 归档时间: |
|
| 查看次数: |
15103 次 |
| 最近记录: |