Java readChar()方法显示日语字符
我试图编写一个代码,根据用户输入的索引从文件中提取一个单词,但问题是Java readChar()方法显示日语字符,java,randomaccessfile,Java,Randomaccessfile,我试图编写一个代码,根据用户输入的索引从文件中提取一个单词,但问题是RandomAccessFile类中的readChar()方法返回的是日语字符,我必须承认,这不是我第一次在联想笔记本上看到这个,有时在一些安装向导上,我可以看到一些普通字符和日语字符混合的东西,你认为它是来自笔记本电脑还是来自代码 代码如下: package com.project; import java.io.*; import java.util.StringTokenizer; public class Main
RandomAccessFile
类中的readChar()
方法返回的是日语字符,我必须承认,这不是我第一次在联想笔记本上看到这个,有时在一些安装向导上,我可以看到一些普通字符和日语字符混合的东西,你认为它是来自笔记本电脑还是来自代码
代码如下:
package com.project;
import java.io.*;
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args) throws IOException {
int N, i=0;
char C;
char[] charArray = new char[100];
String fileLocation = "file.txt";
BufferedReader buffer = new BufferedReader(new InputStreamReader(System.in));
do {
System.out.println("enter the index of the word");
N = Integer.parseInt(buffer.readLine());
if (N!=0) {
RandomAccessFile word = new RandomAccessFile(new File(fileLocation), "r");
do {
word.seek((2*(N-1))+i);
C = word.readChar();
charArray[i] = C;
i++;
}while(charArray[i-1] != ' ');
System.out.println("the word of index " + N + " is: " );
for (char carTemp : charArray )
System.out.print(carTemp);
System.out.print("\n");
}
}while(N!=0);
buffer.close();
}
}
我得到这个输出:
瑯潕啰灰灥敲牃䍡慳獥攨⠩⤍ഊੴ瑯潌䱯潷睥敲牃䍡慳獥攨⠩⤍ഊ捯潭浣捡慴琨⡓却瑲物楮湧朩⤍ഊ捨桡慲牁䅴琨⡩楮湴琩⤍ഊੳ獵畢扳獴瑲物楮湧木⠠獴瑡慲牴琠楮湤摥數砬Ⱐ敮湤搠楮湤摥數砩⤍ഊੴ瑲物業洨⠩Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 100 out of bounds for length 100
at Main.main(Main.java:21)
char
是16位,即2字节
seek
查找字节边界
如果文件包含字符,则它们的偏移量为偶数:0、2、4
表达式(2*(N-1))+i
为偶数,如果i
为偶数;如果是奇数,你肯定会在一个字符的中间着陆,从而读取垃圾。
i
从零开始,但递增1,即半个字符
您的seek参数可能应该是(2*(N-1+i))
替代说明:您的文件根本不包含
字符
;例如,您创建了一个ASCII文件,其中字符是单字节
在这种情况下,错误是试图使用readChar
函数读取ASCII(一种过时的字符编码)
但是,如果文件包含ASCII,那么在seek参数中乘以2的目的就不明确了。它显然没有什么用处。有很多错误的地方,所有这些都与基本的误解有关 首先:磁盘上的一个文件——不要在意Java或任何其他编程语言中的
文件
接口;文件本身-不存储文本,也不能存储文本。曾经它存储字节。也就是说,原始数据(在每台数十年来一直相关的机器上,但历史上有其他方法)以位量化,这些位被组织成8个字节的组,称为字节
文本是一种抽象;对某些特定字节值序列的解释。它从根本上和不可避免地依赖于编码。因为这不是一个博客,我不想在这里给你上历史课,但我只想说Java的char
类型只存储了一个文本字符。它存储一个无符号的两字节值,该值可能表示一个文本字符。由于Unicode中的文本字符数超过了两个字节所能表示的数量,因此有时需要数组中两个相邻的char
s来表示文本字符。(当然,可能有一些代码滥用了char
类型,仅仅是因为有人想要一个与short
相当的未签名版本。我甚至可能自己写过一些。那个时代对我来说是一个模糊的时代。)
无论如何,要点是:使用.readChar()
将从文件中读取两个字节,并将它们存储到char[]
中的char
中,相应的数值将与您想要的数值不同-除非您的文件恰好使用Java本机使用的相同编码,打电话来
如果不知道文件编码,您将无法正确阅读和解释文件。句号。你充其量只能欺骗自己相信你能读到它。您也不能对文本文件进行“随机访问”(即,根据文本的若干字符进行索引),除非所讨论的编码是恒定宽度。(当然,除此之外,您不能仅计算给定文本字符所在文件中的字节距离;这取决于前面的字符占用了多少字节,这取决于它们是哪些字符。)许多文本编码不是恒定宽度,坦率地说,这是目前大多数任务的明智默认建议,但事实并非如此。在这种情况下,你所描述的问题就是运气不佳
无论如何,一旦知道了文件的编码,在Java中从文件中检索文本字符的预期方法是使用一个读卡器类,例如:
InputStreamReader是从字节流到字符流的桥梁:它读取字节并使用指定的字符集将其解码为字符。它使用的字符集可以通过名称指定,也可以显式指定,或者可以接受平台的默认字符集
(这里,charset
只是指Java用来表示文本编码的类的实例。)
您可以稍微篡改一下问题描述:查找字节偏移量,然后获取从该偏移量开始的文本字符。但是,不能保证“从该偏移量开始的文本字符”有任何意义,或者实际上可以被解码。如果偏移发生在一个字符的多字节编码的中间,剩下的部分不一定是有效的编码文本。 < P>我将文件的编码更改为UTF16,并修改了程序,以便显示正确的索引,表示每个单词的开头,现在它工作正常,谢谢各位。
import java.io.*;
public class Main {
public static void main(String[] args) throws IOException {
int N, i=0, j=0, k=0;
char C;
char[] charArray = new char[100];
String fileLocation = "file.txt";
BufferedReader buffer = new BufferedReader(new InputStreamReader(System.in));
DataInputStream in = new DataInputStream(new FileInputStream(fileLocation));
boolean EOF=false;
do {
try {
j++;
C = in.readChar();
if((C==' ')||(C=='\n')){
System.out.print(j+1+"\t");
}
}catch (IOException e){
EOF=true;
}
}while (EOF!=true);
System.out.println("\n");
do {
System.out.println("enter the index of the word");
N = Integer.parseInt(buffer.readLine());
if (N!=0) {
RandomAccessFile word = new RandomAccessFile(new File(fileLocation), "r");
do {
word.seek((2*(N-1+i)));
C = word.readChar();
charArray[i] = C;
i++;
}while(charArray[i-1] != ' ' && charArray[i-1] != '\n');
System.out.print("the word of index " + N + " is: " );
for (char carTemp : charArray )
System.out.print(carTemp);
System.out.print("\n");
i=0;
charArray = new char[100];
}
}while(N!=0);
buffer.close();
}
}
也许这与编码有关?(小错误-您编写了
“/n”
,而不是“\n”
,或者只是System.out.println()
)是否可以尝试将它们打印为整数而不是字符?您计算的seek参数是什么?您正在读取的文件中有什么?它是如何编码的?如果是unicode,可能是搜索将您置于字符中间。你对什么word.seek((2*(N-1))+i)有什么想法代码>是什么?我不认为这会把你带到一个词的边界。而且,你知道什么时候停止阅读的逻辑似乎有缺陷。行charArray[i++]=C代码>放置下一个