最近開發java控制台項目,由於用了第三方庫,必須使用utf8字符。當然在開發環境eclipse下,顯示是正常的:
但是windows的控制台,卻是輸出亂碼。
雖然不改,程序邏輯是正確,作為偏執狂還是翻閱了各種資料:
http://www.cnblogs.com/QQParadise/articles/1685177.htm
http://dustin.iteye.com/blog/77551
網上各種文章,不是用chcp改變控制台編碼,就是建議修改程序編碼為GBK。
參考了stackoverflow的一篇文章,找到一種使用Windows內核API的方案
http://stackoverflow.com/questions/54952/java-utf-8-and-windows-console
核心是封裝一個Console類
package demo; import com.sun.jna.Native; import com.sun.jna.Pointer; import com.sun.jna.ptr.IntByReference; import com.sun.jna.win32.StdCallLibrary; /** * For unicode output on windows platform * * @author Sandy_Yin * */ public class Console { private static Kernel32 INSTANCE = null; public interface Kernel32 extends StdCallLibrary { public Pointer GetStdHandle(int nStdHandle); public boolean WriteConsoleW(Pointer hConsoleOutput, char[] lpBuffer, int nNumberOfCharsToWrite, IntByReference lpNumberOfCharsWritten, Pointer lpReserved); } static { String os = System.getProperty("os.name").toLowerCase(); if (os.startsWith("win")) { INSTANCE = (Kernel32) Native .loadLibrary("kernel32", Kernel32.class); } } public static void print(String message) { if (!prePrint(message)) System.out.print(message); } protected static boolean prePrint(String message) { boolean successful = false; if (INSTANCE != null) { Pointer handle = INSTANCE.GetStdHandle(-11); char[] buffer = message.toCharArray(); IntByReference lpNumberOfCharsWritten = new IntByReference(); successful = INSTANCE.WriteConsoleW(handle, buffer, buffer.length, lpNumberOfCharsWritten, null); } return successful; } public static void println(String message) { // from // http://stackoverflow.com/questions/54952/java-utf-8-and-windows-console if (prePrint(message)) { System.out.println(); } else { System.out.println(message); } } }對輸出進行測試,使用命令:java -jar sample.jar,發現輸出還是一樣。

添加命令行參數,使用java -Dfile.encoding=utf8 -jar sample.jar,就達到效果了。

PS:此方法還存在一些缺陷,但並不是Console類造成的。上圖中“測試”前有一個空白的地方,這是應為使用utf8方式讀入非UTF8文件產生的。在文件開始會出現空格。
代碼下載
/Files/anic/utf8sample_source.zip/Files/anic/utf8sample_runtime.zip