[英]Java's charsets / character encoding
我有一個西班牙文件,所以它充滿了以下字符:
á é í ó ú ñ Ñ Á É Í Ó Ú
我必須閱讀該文件,所以我這樣做:
fr = new FileReader(ficheroEntrada);
BufferedReader rEntrada = new BufferedReader(fr);
String linea = rEntrada.readLine();
if (linea == null) {
logger.error("ERROR: Empty file.");
return null;
}
String delimitador = "[;]";
String[] tokens = null;
List<String> token = new ArrayList<String>();
while ((linea = rEntrada.readLine()) != null) {
// Some parsing specific to my file.
tokens = linea.split(delimitador);
token.add(tokens[0]);
token.add(tokens[1]);
}
logger.info("List of tokens: " + token);
return token;
當我讀取令牌列表時,所有特殊字符都消失了,並被這種字符替換:
Ó = Ó
Ñ = Ñ
等等...
發生了什么? 我從未遇到過charsets的問題(我假設是charset問題)。 是因為這台電腦嗎? 我能做什么?
任何額外的建議將不勝感激,我正在學習! 謝謝!
您需要指定相關的字符編碼。
BufferedReader rEntrada = new BufferedReader(
new InputStreamReader(new FileInputStream(fr), "UTF-8"));
發生了什么?
建議使用UTF-8編碼進行讀寫的答案應該可以解決您的問題。 我的答案更多的是關於將來發生的事情以及如何診斷類似的問題。
首先是http://www.utf8-chartable.de上的UTF-8字符表。 頁面上有一個下拉菜單,可讓您瀏覽Unicode的不同部分。 你的一個問題是Ó
。 檢查圖表顯示,如果你的文件是用UTF-8編碼的,那么字符是U+00D3 LATIN CAPITAL LETTER O WITH ACUTE
,UTF-8序列是兩個字節,hex c3 93
現在讓我們檢查一下http://en.wikipedia.org/wiki/ISO/IEC_8859-1上的ISO-8859-1字符集,因為這也是一個流行的字符集。 然而,這是那些單字節字符集之一。 每個有效字符由單個字節表示,與UTF-8不同,其中字符可以由1,2或3個字節表示。
請注意,C3處的字符看起來像Ã但93處沒有字符。所以您的默認編碼可能不是ISO-8859-1。
接下來,請訪問http://en.wikipedia.org/wiki/Windows-1252查看Windows 1252。 這幾乎與ISO-8859-1相同,但用一些有用的字符填充一些空格。 我們有一場比賽。 Windows 1252中的序列C3 93正好是字符串Ó
這一切告訴我的是,您的文件是UTF-8編碼的,但您的Java環境配置了Windows 1252,因為它是默認編碼。 如果修改代碼以顯式指定字符集(“UTF-8”)而不是使用默認值,則代碼在不同環境中失敗的可能性會降低。
請記住 - 這可能就像其他方式一樣容易發生。 如果您有一個主要是西班牙文本的文件,它可以很容易地成為ISO-8859-1或Windows 1252編碼文件。 在這種情況下,在您的機器上運行的代碼可以正常運行並將其切換為“UTF-8”編碼會創建一組不同的亂碼。
這是您獲得相互矛盾的建議的部分原因。 不同的人基於他們的平台遇到了不同的不匹配,因此發現了不同的修復。
如果有疑問,我在emacs中讀取文件並切換到hexl-mode,這樣我就可以在文件中看到確切的二進制數據。 我相信有更好,更現代的方法來做到這一點。
最后的想法 - 可能值得閱讀絕對最低每個軟件開發人員,絕對必須知道Unicode和字符集(沒有借口!
您的默認編碼錯誤。 您可能需要閱讀UTF8或latin1。 請參閱此代碼段以在流上設置編碼。 另請參見Java,默認編碼
public class Program {
public static void main(String... args) {
if (args.length != 2) {
return ;
}
try {
Reader reader = new InputStreamReader(
new FileInputStream(args[0]),"UTF-8");
BufferedReader fin = new BufferedReader(reader);
Writer writer = new OutputStreamWriter(
new FileOutputStream(args[1]), "UTF-8");
BufferedWriter fout = new BufferedWriter(writer);
String s;
while ((s=fin.readLine())!=null) {
fout.write(s);
fout.newLine();
}
//Remember to call close.
//calling close on a BufferedReader/BufferedWriter
// will automatically call close on its underlying stream
fin.close();
fout.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
根據我的經驗,文本文件應該基於西方編碼來讀寫:ISO-8859-1。
BufferedReader rEntrada = new BufferedReader(new InputStreamReader(new FileInputStream(fr),“ISO-8859-1”));
其他答案為您提供了正確的方向。 只想添加Guava及其Files.newReader(File,Charset)幫助器方法使得創建這樣一個BufferedReader很多可讀(請原諒雙關語):
BufferedReader rEntrada = Files.newReader(new File(ficheroEntrada), Charsets.UTF_8);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.