簡體   English   中英

使用 utf-8 編碼的 utf-8 讀取文件不起作用,但使用“windows-1252”或“iso-8859-1”讀取相同的文件可以

[英]Reading a file using utf-8 that is encoded in utf-8 doesn't work, but reading the same file using “windows-1252” or “iso-8859-1” does

這里發生了什么? 為什么當我使用 utf-8 讀取文件時,控制台中會出現 output 問號?

這是一個最小的工作示例:

圖片

import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
    
import static org.apache.commons.io.FileUtils.readFileToString;
import static org.apache.commons.io.FileUtils.writeStringToFile;
    
public class Main {
    
    public static void main(String... args) throws IOException {
    
        System.out.println("---------");
        System.out.println(Charset.defaultCharset());
        System.out.println("æ ø å");
        System.out.println("æ ø å");
        System.out.println("æ ø å");
    
        File inputFile  = new File(System.getProperty("user.dir") + "/input.md");
        File outputFile = new File(System.getProperty("user.dir") + "/output.md");
    
        String content, encoding;
    
        System.out.println("--------- windows-1252");
        encoding = "windows-1252";
        content = readFileToString(inputFile, encoding);
        System.out.println(content);
    
    
        System.out.println("--------- iso-8859-1");
        encoding = "iso-8859-1";
        content = readFileToString(inputFile, encoding);
        System.out.println(content);
    
    
        System.out.println("--------- utf-8");
        encoding = "utf-8";
        content = readFileToString(inputFile, encoding);
        System.out.println(content);
    
    
        writeStringToFile(outputFile, content, encoding);
    
    }
    
}

其中input.md包含:(以 UTF-8 編碼)

This is input.md. 'æ' 'ø' 'å'

運行上面的代碼產生

---------
windows-1252
æ ø å
æ ø å
æ ø å
--------- windows-1252
This is file C. 'æ' 'ø' 'å'.
--------- iso-8859-1
This is file C. 'æ' 'ø' 'å'.
--------- utf-8
This is file C. '�' '�' '�'.

為什么我在使用 讀取文件時會得到 �? 這特別奇怪,因為該文件是在 UTF-8 中編碼的

更新:我的控制台設置為“UTF-8”:

圖片

這是從輸入文件中提取的字符串中每個字符的十六進制值的屏幕截圖:

圖片

這是一個更好的十六進制隔離截圖:

圖片

代碼對我來說看起來不錯,您的output.md文件看起來不錯。 所以這很可能只是控制台 output 的問題。

您正在試驗的 Unicode 字符在 Windows-1252 和 ISO-8859-1 中被編碼為相同的單字節( æ = 0xE6ø = 0xF8å = 0xE5 ),但在 ZAE3B3DF9970B49B6523E608 æ = 0xC3 0xA6 759 中被編碼為多個字節( æ = 0xC3 0xA6 , ø = 0xC3 0xB8 , å = 0xC3 0xA5 )。

以 Windows-1252 或 ISO-8859-1 讀取 UTF-8 編碼文件將單獨解碼每個字節,為每個字節生成一個包含單獨charstring ,並且這些char將具有與字節相同的數值。 因此,您應該得到一個包含字符0x00C3 0x00A60x00C3 0x00B80x00C3 0x00A5string 將這些char作為 Windows-1252 輸出到控制台應該顯示為æ ø Ã¥ ,而不是æ ø å

另一方面,將 UTF-8 編碼文件讀取為 UTF-8 將正確解碼文件,生成帶有string char0x00F80x00E60x00E5 將該string寫入 UTF-8 編碼文件應生成正確的字節序列( 0xC3 0xA60xC3 0xB80xC3 0xA5 ),但輸出與 Windows-1252 相同的string可能會導致數據丟失,但您應該會看到預期的æ ø å ,因為 Windows-1252 確實支持那些 Unicode 字符。

因此,您的結果實際上與我的預期相反。 即使Charset.defaultCharset()正在報告 Windows-1252,我懷疑您的控制台實際上是在為其 output 使用不同的字符集。

我建議您打印出content字符串的各個char的數值,以准確了解input.md是如何被每種編碼實際解碼的。 應該得到我上面提到的char值。

對於有類似問題的人來說,問題在於控制台的編碼(正如@Remy Lebeau 所指出的那樣)。

我按照這個答案解決了這個問題

實際上,我在評論中關注了@Nicolas 對提到的答案的回答:

這也可以從 Help > Edit custom VM options... 訪問,然后重新啟動 IntelliJ。 我真的嘗試了一切:在 IntelliJ 中隨處更改編碼設置,更改屬性文件設置的 JVM 選項,build.gradle 文件,IntelliJ,運行配置,環境變量等。還嘗試更改系統范圍的編碼,但沒有任何效果

現在我得到了預期的 output:

在此處輸入圖像描述

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM