我试图编写一段代码,根据用户输入的索引从文件中提取一个单词,但问题是,来自RandomAccessFile类的方法RandomAccessFile正在返回日语字符,我必须承认,这不是我第一次在联想笔记本上看到这种情况,有时在安装向导上我可以看到混合的东西,正常字符与日本字符混合,你认为它来自笔记本还是代码?
这是代码:
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)发布于 2020-09-21 02:26:59
有许多事情是错误的,所有这些都与根本的误解有关。
首先:磁盘上的文件--不管是File接口还是任何其他编程语言;文件本身--不存储文本,也不能存储文本。永远不会。它存储字节。也就是说,原始数据(在每台几十年来一直相关的机器上,但历史上有其他方法)被量化为bits,这些数据被组织成8组,称为字节。
文本是一种抽象;对的解释--某些特定的字节值序列。它从根本上和不可避免地取决于编码。因为这不是一个博客,所以我将在这里为您省去历史教训,但只需说一句:char类型而不是只是存储一个文本字符。它存储一个无符号的两字节值,它可以表示文本的字符.由于Unicode中的文本字符多于两个字节所能表示的字符,因此有时需要数组中两个相邻的char来表示文本的字符。(当然,可能有一些代码滥用char类型,仅仅是因为有人想要一个无签名的short。我甚至可能自己写了一些。那个时代对我来说是模糊的。)
无论如何,重点是:使用.readChar()将从您的文件中读取两个字节,并将它们存储到char[]中的一个char中,而相应的数值将不会与您想要的值完全相同--除非您的文件碰巧使用了与Java本机使用的编码相同的编码,称为乌特夫-16。
如果不知道文件编码,就无法正确读取和解释该文件。句号。你充其量可以欺骗自己相信你能读懂它。您还不能使用对文本文件进行“随机访问”--即根据文本的多个字符进行索引--除非所讨论的编码是恒定宽度。(当然,否则,您不能只计算到给定的文本字符所在的文件中的字节距离;它取决于前面的字符占用了多少字节,这取决于它们是哪些字符。)许多文本编码不是恒定宽度。坦率地说,最受欢迎的是目前大多数任务的默认建议,但事实并非如此。在这种情况下,对于你所描述的问题,你只是运气不佳。
无论如何,一旦您知道了文件的编码,在Java中从文件中检索文本字符的预期方法是使用读取器类之一,如InputStreamReader
InputStreamReader是从字节流到字符流的桥梁:它使用指定的字符集读取字节并将它们解码为字符。它使用的字符集可以通过名称指定,也可以显式地给出,或者可以接受平台的默认字符集。
(这里,charset简单地表示一个类的实例,该类用于表示文本编码。)
您可以使用来伪造您的问题描述:查找一个字节偏移量,然后从该偏移量开始获取文本字符。但是,不能保证“从该偏移量开始的文本字符”具有任何意义,或者实际上可以解码。如果偏移量恰好位于字符的多字节编码的中间,则其余部分不一定是有效的编码文本。
发布于 2020-09-21 01:53:42
char为16位,即2字节。
seek寻求一个字节边界。
如果文件包含字符,那么它们将处于偶数偏移: 0、2、4.
表达式(2*(N-1))+i)是偶数当且仅当i是偶数;如果奇怪,则肯定会落在字符中间,从而读取垃圾。
i从零开始,但增加1,即半个字符。
您的搜索论点可能应该是(2*(N-1+i))。
替代解释:您的文件根本不包含chars;例如,您创建了一个字符为单个字节的ASCII文件。
在这种情况下,错误试图使用readChar函数读取ASCII (一个过时的字符编码)。
但是,如果文件包含ASCII,那么在file参数中乘以2的目的是模糊的。显然没有什么用处。
发布于 2020-09-21 11:10:22
我将文件的编码改为UTF-16,并修改了程序以显示正确的索引,这些索引代表每个单词的开头,现在它运行良好,谢谢各位。
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();
}
}https://stackoverflow.com/questions/63984370
复制相似问题