Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java文件读取器编码问题_Java_File_Unicode_Encoding - Fatal编程技术网

Java文件读取器编码问题

Java文件读取器编码问题,java,file,unicode,encoding,Java,File,Unicode,Encoding,我试图使用java.io.FileReader读取一些文本文件并将其转换为字符串,但我发现结果编码错误,根本不可读 这是我的环境: Windows 2003,操作系统编码:CP1252 Java 5.0 我的文件是UTF-8编码或CP1252编码的,其中一些(UTF-8编码的文件)可能包含中文(非拉丁)字符 我使用以下代码来完成我的工作: private static String readFileAsString(String filePath) throws java.io

我试图使用java.io.FileReader读取一些文本文件并将其转换为字符串,但我发现结果编码错误,根本不可读

这是我的环境:

  • Windows 2003,操作系统编码:CP1252

  • Java 5.0

我的文件是UTF-8编码或CP1252编码的,其中一些(UTF-8编码的文件)可能包含中文(非拉丁)字符

我使用以下代码来完成我的工作:

   private static String readFileAsString(String filePath)
    throws java.io.IOException{
        StringBuffer fileData = new StringBuffer(1000);
        FileReader reader = new FileReader(filePath);
        //System.out.println(reader.getEncoding());
        BufferedReader reader = new BufferedReader(reader);
        char[] buf = new char[1024];
        int numRead=0;
        while((numRead=reader.read(buf)) != -1){
            String readData = String.valueOf(buf, 0, numRead);
            fileData.append(readData);
            buf = new char[1024];
        }
        reader.close();
        return fileData.toString();
    }
上面的代码不起作用。我发现文件阅读器的编码是CP1252,即使文本是UTF-8编码的。但是java.io.FileReader的JavaDoc说:

此类的构造函数假定 这是默认的字符编码 默认字节缓冲区大小为 合适

这是否意味着如果我使用FileReader,我不需要自己设置字符编码?但我现在确实得到了错误编码的数据,正确的处理方法是什么?谢谢。

是的,您需要指定要读取的文件的编码

是的,这意味着您必须知道要读取的文件的编码

不,没有通用的方法来猜测任何给定的“纯文本”文件的编码

始终使用平台默认编码,这通常不是一个好主意

因为Java11
FileReader
还获得了接受编码的构造函数:and


在早期版本的java中,您需要使用
,)

FileReader
使用java的平台默认编码,这取决于运行该语言环境的计算机的系统设置,通常是该语言环境中用户最常用的编码


如果此“最佳猜测”不正确,则必须明确指定编码。不幸的是,
FileReader
不允许这样做(API中的主要疏忽)。相反,您必须使用
新的InputStreamReader(新的FileInputStream(filePath),encoding)
并从有关文件的元数据中理想地获取编码。

由于Java 11,您可以使用:

public FileReader(String fileName, Charset charset) throws IOException;
对于Java 7+,您可以使用以下方法:

BufferedReader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8);
这是所有的字符集

例如,如果您的文件位于CP1252中,请使用

以下是IO和NIO的Java编码的其他规范名称


如果您不知道文件中的编码是否准确,您可以使用一些第三方LIB,如谷歌提供的这一工具,该工具非常简洁。

对于另一种语言,例如西里尔语,您可以使用以下内容:

FileReader fr = new FileReader("src/text.txt", StandardCharsets.UTF_8);

并确保您的
.txt
文件以
UTF-8
(但不是默认的
ANSI
)格式保存。干杯

带有InputStreamReader的FileInputStream比直接使用FileReader要好,因为后者不允许您指定编码字符集

下面是一个同时使用BufferedReader、FileInputStream和InputStreamReader的示例,这样您就可以从文件中读取行

List<String> words = new ArrayList<>();
List<String> meanings = new ArrayList<>();
public void readAll( ) throws IOException{
    String fileName = "College_Grade4.txt";
    String charset = "UTF-8";
    BufferedReader reader = new BufferedReader(
        new InputStreamReader(
            new FileInputStream(fileName), charset)); 

    String line; 
    while ((line = reader.readLine()) != null) { 
        line = line.trim();
        if( line.length() == 0 ) continue;
        int idx = line.indexOf("\t");
        words.add( line.substring(0, idx ));
        meanings.add( line.substring(idx+1));
    } 
    reader.close();
}
List words=new ArrayList();
列表含义=新的ArrayList();
public void readAll()引发IOException{
字符串fileName=“College_grade 4.txt”;
字符串charset=“UTF-8”;
BufferedReader reader=新的BufferedReader(
新的InputStreamReader(
新文件输入流(文件名,字符集));
弦线;
而((line=reader.readLine())!=null){
line=line.trim();
如果(line.length()==0)继续;
int idx=line.indexOf(“\t”);
添加(行子字符串(0,idx));
添加(行子字符串(idx+1));
} 
reader.close();
}

您还应该在循环中释放字符串.valueOf(),并直接使用StringBuffer.append(char[],int,int)。这节省了大量的char[]复制。还可以使用StringBuilder替换StringBuffer。不过,这些都不是关于你的问题,我不想这么说,但是你在粘贴部分之后读过JavaDoc吗?你知道,那部分说“要自己指定这些值,在FileInputStream上构造InputStreamReader。”?谢谢你的评论,实际上我读了JavaDoc,但我不确定的是我是否应该自己指定这些值,然后切换到“在FileInputStream上构造InputStreamReader”。是的,如果您知道该文件使用的不是平台默认编码,那么您必须告诉InputStreamReader使用哪种编码。“API中的主要疏忽”-感谢您的解释-我想知道为什么找不到我要找的构造函数!干杯John@BhanuSharma:这是另一个级别的编码问题,请检查文件名的来源,如果是硬编码,则检查编译器使用的编码。@BhanuSharma:文件名编码问题与此问题无关。请参阅许多现有的“为什么Unicode文件名不能在Java中工作”问题之一。扰流板:像FileReader这样的java.io API使用C标准库文件系统调用,这在Windows上不支持Unicode;考虑使用JavaNIO。“<代码>文件名> /CODE >使用java的平台默认编码,这取决于它运行的计算机的系统设置,并且通常是该区域中用户中最流行的编码。“我不会这么说。至少有两扇窗户。出于一些奇怪的技术/历史原因,JVM忽略了一个事实,即Unicode是Windows上“所有新应用程序”的编码,而总是将配置为旧应用程序后备的旧编码视为“平台默认值”。我甚至会说,如果Java应用程序在每次读取或写入时都没有显式指定编码文件/流/资源,它已损坏,因为它无法可靠地工作。InputStream is=new FileInputStream(filename);在这里,我得到了错误文件not found error,俄文文件名为+1,建议使用InputStreamReader,但是在代码块中使用链接会使复制和粘贴代码变得困难,如果可以更改,ThxB会吗
List<String> words = new ArrayList<>();
List<String> meanings = new ArrayList<>();
public void readAll( ) throws IOException{
    String fileName = "College_Grade4.txt";
    String charset = "UTF-8";
    BufferedReader reader = new BufferedReader(
        new InputStreamReader(
            new FileInputStream(fileName), charset)); 

    String line; 
    while ((line = reader.readLine()) != null) { 
        line = line.trim();
        if( line.length() == 0 ) continue;
        int idx = line.indexOf("\t");
        words.add( line.substring(0, idx ));
        meanings.add( line.substring(idx+1));
    } 
    reader.close();
}