【问题标题】:Java, UTF-8, and Windows consoleJava、UTF-8 和 Windows 控制台
【发布时间】:2010-09-08 11:17:43
【问题描述】:

我们尝试在 Windows 上使用 Java 和 UTF-8。应用程序在控制台上写入日志,我们希望将 UTF-8 用于日志,因为我们的应用程序具有国际化日志。

可以配置 JVM,使其生成 UTF-8,使用 -Dfile.encoding=UTF-8 作为 JVM 的参数。它工作正常,但在 Windows 控制台上的输出是乱码。

然后,我们可以将控制台的代码页设置为 65001(chcp 65001),但是在这种情况下,.bat 文件不起作用。这意味着当我们尝试通过我们的脚本(名为 start.bat)启动我们的应用程序时,绝对没有任何反应。命令简单返回:

C:\Application> chcp 65001
Activated code page: 65001
C:\Application> start.bat

C:\Application>

但是没有chcp 65001就没有问题,可以启动应用了。

有什么提示吗?

【问题讨论】:

  • start.bat文件的文本编码是什么?

标签: java windows utf-8 console


【解决方案1】:

试试chcp 65001 && start.bat

chcp 命令更改代码页,65001 是 Windows 7 及更高版本下 UTF-8 的 Win32 代码页标识符。代码页或字符编码指定如何将 Unicode 代码点转换为字节序列或再次转换回来。

【讨论】:

  • 这必须与 -Dfile.encoding=UTF-8 一起使用才能正常工作。
  • @AxelFontaine 我尝试使用 -Dfile.encoding=UTF-8 但是在使用平方根符号时,符号后面的最后 2 个数字会重复。例如,而不是√125,输出将是√12525
【解决方案2】:

Windows 上的 Java 默认不支持 unicode 输出。我已经编写了一个解决方法,通过使用 JNA 库调用 Native API。该方法将调用 WriteConsoleW 以在控制台上输出 unicode。

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 println(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);
            if(successful){
                System.out.println();
            }
        }
        if (!successful) {
            System.out.println(message);
        }
    }
}

【讨论】:

    【解决方案3】:

    我们在 Linux 中遇到了一些类似的问题。我们的代码采用 ISO-8859-1(大部分与 cp-1252 兼容),但控制台是 UTF-8,导致代码无法编译。只需将控制台更改为 ISO-8859-1 就会使 UTF-8 中的构建脚本中断。我们找到了几个选择:
    1-定义一些标准编码并坚持下去。那是我们的选择。我们选择将所有内容保留在 ISO-8859-1 中,修改构建脚本。
    2- 在开始任何任务之前设置编码,即使在构建脚本中也是如此。像埃里克森所说的一些代码。在 Linux 中是这样的:

    lang=pt_BR.ISO-8859-1 /usr/local/xxxx
    

    我的eclipse还是这样。两者都运作良好。

    【讨论】:

    • 似乎倒退了一步,坚持(和修改)到 iso-8859-1 而不是 utf-8 。但可能你有你的理由。
    【解决方案4】:

    【讨论】:

    • Windows 7 开始支持它。
    【解决方案5】:

    您是否尝试过 PowerShell 而不是旧的 cmd.exe。

    【讨论】:

    • PowerShell 仍然使用相同的控制台,所以它和 cmd.exe 一样陈旧而垃圾。
    猜你喜欢
    • 2010-12-12
    • 1970-01-01
    • 2014-09-27
    • 2018-06-18
    • 1970-01-01
    • 2015-11-26
    • 1970-01-01
    • 2012-05-06
    • 1970-01-01
    相关资源
    最近更新 更多