readChar方法显示日语字符

问题描述

我正在尝试编写一个代码,该代码根据用户输入的索引从文件提取单词,但是问题是来自readChar()类的方法RandomAccessFile正在返回日语字符,我必须承认这不是我第一次在lenovo笔记本电脑上看到它,有时在某些安装向导中,我可以看到带有普通字符和日语字符混合的东西,您认为它来自笔记本电脑还是而不是代码

这是代码

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是偶数;如果是奇数,则一定要放在一个char的中间,从而读取垃圾。

i从零开始,但您增加了1,即半个字符。

您的搜索参数应该为(2*(N-1+i))


另一种解释:您的文件根本不包含chars;例如,您创建了一个ASCII文件,其中一个字符是一个字节。

在这种情况下,错误是试图使用readChar函数读取ASCII(过时的字符编码)。

但是,如果文件包含ASCII,则在seek参数中乘以2的目的是模糊的。它显然没有任何用处。

,

有很多错误,都与基本的误解有关。

首先:磁盘上的文件-不用担心Java或任何其他编程语言中的File接口;文件本身-也不会存储文本。曾经它存储字节。也就是说,原始数据(在数十年来一直与之相关的每台机器上,但是历史上还有其他方法可以做到)以位为单位进行量化,这些数据被分为8组,称为字节。

文本是一种抽象;对某些特殊的字节值序列的解释。从根本上和不可避免地,它取决于 encoding 。由于这不是博客,因此我将在这里为您保留历史课程,但是足以说明Java的char类型不会只是存储文本字符。它存储一个无符号的两个字节的值,其中可能表示文本字符。因为Unicode中的文本字符多于两个字节可以表示的字符,所以有时需要数组中两个相邻的char来表示文本字符。 (并且,当然,那里可能存在滥用char类型的代码,仅仅是因为有人想要与short等价的无符号等效物。我什至可能已经写了一些自己的东西。那个时代对我来说是一个模糊的时期。 )

无论如何,关键是:使用.readChar()将从文件中读取两个字节,并将它们存储到char中的char[]中,而相应的数值不是将会类似于您想要的东西-除非您的文件使用与Java本机使用的相同编码(称为UTF-16)进行编码。

不知道 的情况下,您 不能正确读取和解释文件。句号您最多只能自欺欺人以为自己可以阅读。您还 不能 具有对文本文件的“随机访问”权限-即,根据文本的字符数编制索引-除非所涉及的编码为恒定宽度。 (当然,否则,您不能只计算给定文本字符到文件的字节距离;这取决于前一个字符占用了多少字节,还取决于它们是哪个字符。)许多文本编码的宽度不是恒定的。坦率地说,One of the most popular并不是当今大多数任务的默认默认建议。在这种情况下,您根本就不了解所描述的问题。

无论如何,一旦您知道文件的编码,从Java中的文件中检索文本字符的预期方式就是使用Reader类之一,例如InputStreamReader

InputStreamReader是从字节流到字符流的桥梁:它读取字节,并使用指定的字符集将其解码为字符。它使用的字符集可以按名称指定,也可以明确指定,也可以接受平台的默认字符集。

(这里charset仅表示Java用于表示文本编码的类的实例。)

也许 可以稍微弄乱您的问题描述:寻求字节偏移量,然后从该偏移量开始获取文本字符。但是,不能保证“从该偏移量开始的文本字符”是有意义的,或者实际上可以完全解码。如果偏移量恰好在字符的多字节编码中间,则其余部分不一定是有效的编码文本。

,

我将文件的编码更改为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();


   }
}