2009-04-19 32 views
10

我使用以下代碼將中文字符保存到.txt文件中,但是當我用寫字板打開它時,我無法讀取它。如何保存中文字符到java文件?

StringBuffer Shanghai_StrBuf = new StringBuffer("\u4E0A\u6D77"); 
boolean Append = true; 

FileOutputStream fos; 
fos = new FileOutputStream(FileName, Append); 
for (int i = 0;i < Shanghai_StrBuf.length(); i++) { 
    fos.write(Shanghai_StrBuf.charAt(i)); 
} 
fos.close(); 

我該怎麼辦?我知道如果我將漢字剪切並粘貼到寫字板中,我可以將它保存到一個.txt文件中。我如何在Java中做到這一點?

+0

可能重複[什麼是字符編碼,爲什麼我應該打擾它](http://stackoverflow.com/questions/10611455/what-is-character-encoding-and - 爲什麼我應該打擾它) – Raedwald 2015-04-10 12:35:24

回答

10

有幾個因素在起作用:

  • 文本文件沒有用於描述其編碼的固有元數據(對於所有關於尖括號稅的討論,都有XML是流行的)
  • Windows的默認編碼仍然是一個8位(或雙字節)「ANSI」性格與價值觀的有限範圍內設置 - 寫在這個格式的文本文件是無法移植
  • 要從講一個Unicode文件ANSI文件,Windows應用程序依賴文件開頭處的byte order marknot strictly true - Raymond Chen explains)。理論上,BOM是告訴你數據的endianess(字節順序)。對於UTF-8,即使只有一個字節順序,Windows應用程序依靠標記字節自動發現它是Unicode(儘管您會注意到記事本在其打開/保存對話框中有一個編碼選項)。
  • 說Java因爲不自動寫入UTF-8 BOM而中斷,這是錯誤的。例如,在Unix系統上,將BOM寫入腳本文件是錯誤的,許多Unix系統使用UTF-8作爲默認編碼。有些時候,你不希望它在Windows上,或者說,當你將數據附加到現有的文件,如:fos = new FileOutputStream(FileName,Append);

這裏是UTF-8的數據可靠地附加到文件的方法:

private static void writeUtf8ToFile(File file, boolean append, String data) 
     throws IOException { 
    boolean skipBOM = append && file.isFile() && (file.length() > 0); 
    Closer res = new Closer(); 
    try { 
     OutputStream out = res.using(new FileOutputStream(file, append)); 
     Writer writer = res.using(new OutputStreamWriter(out, Charset 
      .forName("UTF-8"))); 
     if (!skipBOM) { 
     writer.write('\uFEFF'); 
     } 
     writer.write(data); 
    } finally { 
     res.close(); 
    } 
    } 

用法:

public static void main(String[] args) throws IOException { 
    String chinese = "\u4E0A\u6D77"; 
    boolean append = true; 
    writeUtf8ToFile(new File("chinese.txt"), append, chinese); 
    } 

注:如果文件已經存在,你選擇了追加和現有的數據不是 UTF-8編碼,唯一的代碼w ^虐待創造是一團糟。

下面是在這段代碼中使用的Closer類型:

public class Closer implements Closeable { 
    private Closeable closeable; 

    public <T extends Closeable> T using(T t) { 
    closeable = t; 
    return t; 
    } 

    @Override public void close() throws IOException { 
    if (closeable != null) { 
     closeable.close(); 
    } 
    } 
} 

此代碼如何基於字節順序標記讀取文件中的Windows風格的最好的猜測:

private static final Charset[] UTF_ENCODINGS = { Charset.forName("UTF-8"), 
     Charset.forName("UTF-16LE"), Charset.forName("UTF-16BE") }; 

    private static Charset getEncoding(InputStream in) throws IOException { 
    charsetLoop: for (Charset encodings : UTF_ENCODINGS) { 
     byte[] bom = "\uFEFF".getBytes(encodings); 
     in.mark(bom.length); 
     for (byte b : bom) { 
     if ((0xFF & b) != in.read()) { 
      in.reset(); 
      continue charsetLoop; 
     } 
     } 
     return encodings; 
    } 
    return Charset.defaultCharset(); 
    } 

    private static String readText(File file) throws IOException { 
    Closer res = new Closer(); 
    try { 
     InputStream in = res.using(new FileInputStream(file)); 
     InputStream bin = res.using(new BufferedInputStream(in)); 
     Reader reader = res.using(new InputStreamReader(bin, getEncoding(bin))); 
     StringBuilder out = new StringBuilder(); 
     for (int ch = reader.read(); ch != -1; ch = reader.read()) 
     out.append((char) ch); 
     return out.toString(); 
    } finally { 
     res.close(); 
    } 
    } 

用法:

public static void main(String[] args) throws IOException { 
    System.out.println(readText(new File("chinese.txt"))); 
    } 

(System.out使用默認編碼,所以無論它是否打印任何東西ble取決於你的平臺和configuration。)

4

如果你能依靠的是默認的字符編碼是UTF-8(或其他一些Unicode編碼),你可以使用以下命令:

Writer w = new FileWriter("test.txt"); 
    w.append("上海"); 
    w.close(); 

最安全的方法是始終明確指定編碼:

Writer w = new OutputStreamWriter(new FileOutputStream("test.txt"), "UTF-8"); 
    w.append("上海"); 
    w.close(); 

P.S.如果javac的-encoding參數配置正確,您可以在Java源代碼中使用任何Unicode字符,甚至作爲方法名和變量名。這使得源代碼比轉義的\uXXXX表單更具可讀性。

+0

我想,但是因爲我使用Netbeans,在我剪切並粘貼中文到java文件並保存後,它不會顯示出來(只看到? ?)當我重新打開Netbeans中的java文件時。 – Frank 2009-04-20 14:40:09

+0

也許NetBeans配置爲使用某種非Unicode編碼,或者編輯器的字體不具有全部Unicode字符。我不使用NetBeans,但從其幫助文件中可以看到,您在Project Properties |中設置了編碼來源|編碼。 – 2009-04-20 20:56:59

+0

如果使用其他編輯器保存該文件,是否確定使用哪種編碼保存了該文件? – 2009-04-20 20:58:04

1

以下是其中的一種。基本上,我們只是指定的轉換輸出字節到FileOutputStream中前完成,以UTF-8:

String FileName = "output.txt"; 

StringBuffer Shanghai_StrBuf=new StringBuffer("\u4E0A\u6D77"); 
boolean Append=true; 

Writer writer = new OutputStreamWriter(new FileOutputStream(FileName,Append), "UTF-8"); 
writer.write(Shanghai_StrBuf.toString(), 0, Shanghai_StrBuf.length()); 
writer.close(); 

我手動在http://www.fileformat.info/info/unicode/char/驗證了這一對圖像。將來,請遵循Java編碼標準,包括小寫變量名稱。它提高了可讀性。

1

試試這個,

StringBuffer Shanghai_StrBuf=new StringBuffer("\u4E0A\u6D77"); 
    boolean Append=true; 

    Writer out = new BufferedWriter(new OutputStreamWriter(
     new FileOutputStream(FileName,Append), "UTF8")); 
    for (int i=0;i<Shanghai_StrBuf.length();i++) out.write(Shanghai_StrBuf.charAt(i)); 
    out.close(); 
3

要非常小心與所提出的方法。即使指定文件的編碼如下:

Writer w = new OutputStreamWriter(new FileOutputStream(「test.txt」),「UTF-8」);

如果您在Windows等操作系統下運行,將無法正常工作。即使將file.encoding的系統屬性設置爲UTF-8也不能解決問題。這是因爲Java無法爲文件寫入字節順序標記(BOM)。即使在寫出文件時指定編碼,在Wordpad等應用程序中打開相同文件也會將文本顯示爲垃圾,因爲它不檢測BOM。我嘗試在Windows中運行示例(使用CP1252的平臺/容器編碼)。

下存在錯誤描述Java中的問題:

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058

暫時的解決方法是寫字節順序標記自己以確保文件在其他應用程序中打開正確。看到這個,詳細瞭解了BOM:

http://mindprod.com/jgloss/bom.html

和更正確的解決方案請訪問以下鏈接:

http://tripoverit.blogspot.com/2007/04/javas-utf-8-and-unicode-writing-is.html

相關問題