解决Java源代码在CMD控制台编译运行乱码问题的全面指南

问题描述:

解决Java源代码在CMD控制台编译运行乱码问题的全面指南

在学习“java 基本数据类型”的相关知识点时,在 cmd 控制台中进行不同文本编辑器编写的 java 源代码文件的编译和运行操作,多次出现了乱码的情况。

1、字符编码

字符编码的产生背景在此处不做进一步阐述。简单来讲讲当下主流语言的字符编码是如何演变的。

字符编码规定了人类自然语言与计算机语言相互转换的方式。我们编写的各种高级编程语言程序无法直接存储到计算机磁盘中,因为计算机磁盘中的数据是二进制格式的。所以,一个.java 文件从文本编辑器保存到磁盘时需要经过一次编码,编码方式可以是上图中的任何一种,也可以是其他任何字符编码方式。存储在磁盘中经编码后的文本是一个个字节,被称作字节流。当用不同的应用程序打开.java 文件时,应用程序首先对从磁盘输入到内存里的字节流文件进行解码操作,接着读取该文件中所描述的内容,之后再进行其他的操作。如上图呈现,不同体系的编码彼此不兼容,同一体系的新版本与老版本之间也可能不兼容。所以,若要确保能正确获取文件中所描述的内容,就必须明确解码方式与编码方式相同(或者解码方式兼容编码方式),如此才不会得到怪异的内容。

java 源文件需通过 javac 进行编译,从而生成 class 文件。java 虚拟机能够执行这个 class 文件,并输出相应的结果。编辑器在保存文本之前对文本编码所用的格式决定了 java 源文件的编码格式;有一个可指定的参数决定了 javac 读取 java 源文件所用的格式;所用输出方法内部的参数决定了虚拟机的输出格式;当前活动代码页(chcp 936 或 chcp 65001)的设置决定了控制台如何读取虚拟机传递过来的数据;只有这一系列编码解码过程前后所用的字符编码相同或者后面步骤兼容前面步骤,才能在控制台正确显示我们想要的字符串。我们用几个简单示例来阐述在 window 10 企业版环境下,控制台输出中文字符串时如何解决乱码问题。

2、示例

编辑器的默认字符编码是什么?如何查看已有的文件编码?又如何改变源文件的编码呢?

这里主要针对 GBK(中文简体)这种格式进行探究,同时也针对 UTF-8(国际通用)这种格式进行探究。

准备工作包括:使用编辑器,并且用这些编辑器分别创建与之对应的默认编码格式的 java 源文件。

编辑器

Notepad

EditPlus

Notepad++

Sublime Text3

文件名

Notepad.java

EditPlus.java

Notepad11.java

Sublime.java

测试代码:

//此处类名设置为对应的编辑器的名字,便于区分
public class Notepad11       
{
主要方法是 public static void main,它接收一个字符串数组参数 args。
	{
		int num1=10;
		float num2=num1;
		System.out.println(num2);
主要是测试中文字符串的输出。接下来的编辑器名字被设置为相应的编辑器名称,这样便于进行区分。
我创建了一个字符串,这个字符串是用 Notepad++创建的,并且是中文字符串。
		System.out.println(str);
打印的内容为 "Hello world!" 。
	}
}

目前我用过 4 个编辑器,我认为用 Notepad++查看和修改 java 源文件字符编码格式是最直接且最清晰正确的。我用这 4 个编辑器分别创建了对应名称的测试文件,并以各自默认的字符编码进行保存。接着用 Notepad++分别打开这四个文件来查看其编码方式,如下图所示:

Notepad默认字符编码

EditPlus默认字符编码

Notepad++默认字符编码

Sublime Text 3 默认字符编码

经过测试得出四种编辑器默认保存新建文本的字符编码格式。如果是打开已有文本且在保存前手动改变了文本的字符编码,那么保存时就会以当前使用的字符编码存储。

编辑器

Notepad

EditPlus

Notepad++

Sublime Text3

文件名

Notepad.java

EditPlus.java

Notepad11.java

Sublime.java

默认保存文件字符编码

ANIS

ANIS

UTF-8

UTF-8

这些编辑器在正确读取并打开 java 源文件后,能够将文件转码,以你想要的字符编码重新保存。存在一个隐藏的坑。Notepad(Windows 自带的记事本)在选择另存为 UTF-8 格式时,系统实际存储的格式是 UTF-8 BOM 。关于这两者的区别,需自行百度。

我把上文中的示例文件 Notepad.java(此刻为 ANSI 格式)用记事本另存成了 UTF-8 格式。

打开 Notepad++编辑器,然后打开这个重新编码之后的 Notepad.java 文件,接着就可以显示其字符编码格式为 UTF-8-BOM 。

小结:在此处明确了 4 大编辑器保存 java 源文件时所采用的默认字符编码。知晓了怎样去查看一个 java 源文件的字符编码。也清楚了最终如何将一个 java 源文件另存为我们期望的字符编码。

(2)、编译和运行过程中调整字符编码来解决中文乱码问题

已经讨论了查看 java 源文件字符编码的方法。在此基础上,当已知一个源文件的字符编码时,研究 javac 的解码方式以及控制台的 Codepage 参数对最终输出中文字符串的影响。

此处进行本次试验是通过临时改变参数来实现的。关于如何永久改变控制台 CodePage 以及 javac 解码方式参数的事宜,稍后再进行说明。

我画了一幅草图,用以大致表示从 Java 源文件到最后输出到控制台这一过程中文件的编码和解码所经历的情况。

看懂上图就大致明白了java的跨平台性是如何实现的。Java 虚拟机在操作系统上运行,java 应用程序在 java 虚拟机上运行。java 虚拟机默认的输出方式与所在平台的默认方式相对应。java 虚拟机(jvm)是为各个平台专门打造的,不具有跨平台性。运行在 Windows 上的 Java 虚拟机不能直接在苹果系统上运行。当一个.class 文件成功生成后,拿到运行在不同平台上的 jvm 中执行,在各平台默认参数未改变的情况下,最后各平台上输出的结果必定相同。各个不同的平台配置好各自量身定做的 Java 虚拟机后,所有用 java 语言编写的 java 应用程序就能达成跨平台一致性。

目前所学内容可使用的输出方法为 System.out.println() 。此方法会以操作系统的默认字符编码输出字节流。当下我所学的阶段尚不知如何修改该方法的默认参数。暂且把这当作已知条件,不会对后续试验产生影响。

从图中能够得知,对于红圈内部的编解码过程,我们眼下无法对其参数进行修改,不过我们只要知晓它默认所使用的是何种字符编码就可以了。接下来创建 2 个测试文件,这些文件的内容与上文的示例代码是一样的。

文件名

UTF8.java

GBK.java

字符编码

UTF-8(chcp 65001)

GBK(chcp 936)

上面有两幅图,源文件采用的是 GBK 编码。在使用 javac 时,它采用系统默认的 GBK 解码方式,从而生成了 class 文件。其中,第一幅图的 cmd 活动页编码为 936,能够将所有字符都正确显示出来。而第二幅图把 cmd 活动页临时修改为 65001,然后直接运行之前编译好的 class 文件,得到的结果如图所示,数字和英文字母都能正确显示,但是中文全部显示为乱码。先删除文件夹中已存在的 GBK.class 文件,然后通过 cmd 以 chcp 65001 来重新生成一个新的 GBK.class,其输出结果与第二图一致。由此可知,cmd 的活动代码页参数对 java 原文件的编译没有影响,但对 jvm 输出字节流的解码方式有影响。所以要想得到正确的中文显示,就应当让 cmd 的活动代码页保持为默认的 936 。在下图中,代码页都是 936 。

上图中,源文件的格式是 UTF8 。而 javac 的解码格式为 GBK 。在这种情况下进行编译,成功生成了一个 UTF.class 文件。然而,当运行这个文件后,输出结果中数字和英文字母以及标点符号是正确的,但中文全部显示为乱码。这能得到很好的解释。GBK 编码和 Unicode 编码里都有 ASCII 编码,并且 ASCII 编码在 GBK 和 Unicode 编码中被分配的编码是相同的。测试代码中所涉及的数字、标点符号以及英文字母,全都在 ASCII 编码所表示的范围之内。所以在编译过程中,javac 能够以 GBK 格式正确地识别 UTF8.java 中的数字、标点符号和英文字母,而中文部分却读取到了错误的内容。最终,class 文件被运行并输出到控制台里。其中,数字是正确的,标点也是正确的,英文字母同样正确,然而中文字符串却全部呈现为乱码。

测试二:将 javac 的解码格式设定为 UTF-8。然后,分别使用 GBK 格式的源文件和 UTF-8 格式的源文件进行编译测试。

上图是对用 GBK 格式编码的源文件进行 UTF8 格式解码。编译进行到第 8 行时遇到了注释。// 后面的中文无法被识别。每出现一个无法识别的错误就会报一次错。

上图显示,源文件的编码格式是 UTF-8,javac 的解码方式也是 UTF-8,两者前后相互对应,能够正确读取,也能输出正确结果。

总结:在 win 10 企业版平台中,要解决 java 程序的中文输出乱码问题。

本人是新入行的,就像一枚小白。这是我第一次写博客,在理解方面难免会有不到位的地方。希望各路大神能够不吝赐教。

你可能想看:
« 上一篇
下一篇 »

相关推荐

java中什么是冒泡,冒泡算法

2026年09月06日

27阅读

java中冒号,java双冒号

2026年09月06日

26阅读

java中的->,java中的是什么意思

2026年09月06日

24阅读

java中的super用法,Java中super的说明

2026年09月06日

28阅读

java中反射的应用,java中反射的应用场景

2026年09月06日

26阅读

java中开关的定义,Java关键字有哪些

2026年09月06日

26阅读