vscode java encoding problem

lunchbox 发布于 2024-03-21 754 次阅读


编码与输出

编码,就是固定的字节约定以及字符的对应关系。在计算机中,字符是以数字形式存储的,不同的编码方式,字符对应的数字也不同。常见的编码方式有ASCII、GB2312、GBK、UTF-8等。在不同的编码展示方式中,需要首先确认编码方式,才能以正确的形式被展现出来。
在windows中,中国区的中文环境下,cmd与poewershell都是 936代码页,是以GBK为基础编码的。
虽然默认的代码页是 936(即 GBK),但是它们实际上可以显示和处理 Unicode 字符。这是因为 Windows 的命令行环境在内部使用 Unicode(具体来说是 UTF-16)来处理字符串。
当你在命令行中输入非 GBK 字符(如 "ǎΩあ一😀")时,Windows 会首先使用当前的输入法(通常是基于 Unicode 的)来接收这些字符,然后将它们转换为 Unicode 字符串。当这些字符被 echo 命令输出时,Windows 会尝试将这些 Unicode 字符转换为当前代码页(即 GBK)中的字符。如果这些字符在 GBK 中不存在,Windows 会使用一个特殊的字符(通常是 "?")来代替它们。

java环境

##java18 以后默认encoding是UTF-8 但是输出不是 所以要手动设置-Dstdout.encoding=UTF-8 -Dstderr.encoding=UTF-8
javac -encoding UTF-8  
java -Dfile.encoding=UTF-8 -Dstdout.encoding=UTF-8 -Dstderr.encoding=UTF-8

vscode中:
通过Language Support for Java或者 coderunner运行时,终端(terminal)默认使用的cmd/powershell。

## 检查当前代码页
chcp
## GBK
chcp 936
## UTF-8
chcp 65001

通过以上脚本来切换环境,可以查看到以下案例的区别所在。

import java.nio.charset.Charset;

public class ShowEncode {
    public static void main(String[] args) {
        String utf8String = new String("这是一个测试!ǎΩあ一😀".getBytes(),  Charset.forName("utf8"));
        System.out.println(utf8String);
        Charset defaultCharset = Charset.defaultCharset();
        System.out.println(defaultCharset);
    }
}

注意test runner for java 中所使用的输出窗口默认便是 utf-8编码。所以在使用test测试时,要注意编码的问题。

import java.nio.charset.Charset;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

public class TestT {
    @Test
    public void showEncode(){
        String utf8String = new String("这是一个测试!ǎΩあ一😀".getBytes(), Charset.forName("utf8"));
        // String utf8String = "这是一个测试!";
        System.out.println(utf8String);
        Charset defaultCharset = Charset.defaultCharset();
        System.out.println(defaultCharset);
        Assertions.assertNotNull(utf8String);
    }
}

最后附上vscode的部分设置,与自动设置windows11下 cmd与powershell编码的脚本

{
    //code runner
    "code-runner.executorMap": {
        //适用于单文件 com.example.$fileNameWithoutExt com.example需要自己修改成对应的路径
        "java": "cd $dir && javac -encoding UTF-8 -d $workspaceRoot/out $fileName  && java -Dfile.encoding=UTF-8 -Dstdout.encoding=UTF-8 -Dstderr.encoding=UTF-8 -cp $workspaceRoot/out com.example.$fileNameWithoutExt",
    },
    // Language Support for Java
    "java.configuration.runtimes": [
        {
            "name": "JavaSE-1.8",
            "path": "D:/work/jdk",
        },
        {
            "name": "JavaSE-21",
            "path": "D:/work/jdk-21.0.2",
            "default": true
        },
    ],
    "java.jdt.ls.vmargs": "-Dfile.encoding=UTF-8 -Dstdout.encoding=UTF-8 -Dstderr.encoding=UTF-8",
    //test runner for java
    "java.test.config": {
        "vmArgs": [
            "-Dstdout.encoding=UTF-8",
            "-Dstderr.encoding=UTF-8",
            "-Dfile.encoding=UTF-8"
        ]
    }
}

自动切换编码及问题

##cmd自动切换65001设置
##powershell自动切换65001设置

切换65001后,使用中文来echo是否有问题?能不能显示emoji?

不推荐的编码改变方式

Windows设置-时间和语言-日期、时间和区域格式设置-其他日期、时间和区域设置
进入控制面板的时钟和区域
更改日期、时间或数字格式-管理-非Unicode程序的语言-使用unicode utf8

会造成某些软件无法正常使用,我就遇到汉化过后的游戏打不开的情况。所以极力不推荐这种方式。

java环境常用插件汇总

Extension Pack for Java,Lombok Annotations Support for VS Code,SonarLint,Snyk Security
Spring Boot Extension Pack
Project Manager
GitHub Copilot,GitHub Copilot Chat