Java调用操作系统命令的输出乱码问题解决

news2024/11/20 15:23:42

本篇解决的问题

使用Java 的Runtime调用操作系统的命令,出现异常时使用getErrorStream()获取错误信息的字节流,转换该字节流为字符串显示时,出现乱码。

Java调用操作系统命令

这里以Windows 操作系统为例, 调用cd 命令切换路径。

使用Java调用操作系统本身的命令使用Runtime 的exec() 方法,执行的命令以 cmd.exe /c 开头,后面接上需要执行的语句, 代码如下:

		Runtime rt = Runtime.getRuntime();
		Process pr = rt.exec("cmd.exe /c cd errorpath");

如何获取执行的结果呢? 甚至如果执行失败, 获取执行的错误信息。

  • Process 的 waitFor() 方法用于等待进程完成,然后获取返回码
  • 错误信息也可以通过Process 的getErrorStream()方法获取错误的字节流,通过Java的字节流和字符串的转换可以错误信息的字符串, 完整的代码如下所示:
		int exitCode = pr.waitFor();   // 等待进程完成,然后获取返回码
		if (exitCode == 0) {
		    System.out.println("命令执行成功!");
		} else {
		    System.out.println("命令执行失败, 返回码: " + exitCode);
		    try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(pr.getErrorStream()))) {
		        String line;
		        StringBuilder content = new StringBuilder();
		        while ((line = bufferedReader.readLine()) != null) {
		            content.append(line);
		            content.append(System.lineSeparator()); // 添加行分隔符,如果需要的话
		        }
		        String errorText = content.toString();	        
		        // 打印或处理错误消息
		        System.out.println("错误信息:"+errorText);
		    }
		}

问题描述

上面的代码为了演示错误的场景直接切换到一个不存在的目录,在某些环境下(操作系统、JVM)是正常的, 但是在笔者的机器上,在Eclipse中执行的时候,错误信息的显示确是乱码, 界面如下:

在这里插入图片描述

在命令行直接执行该命令的时候,效果如下:
在这里插入图片描述

可以看到这里的操作系统使用的是中文的字符。

如何查看Windows操作系统的字符集

查看Windows 操作系统的默认字符集,可以通过如下步骤:

  1. 打开控制面板
  2. 点击区域和语言选项(在某些Windows版本中可能叫做区域或者时钟,语言和区域)。
  3. 查看系统的区域设置
    如下图:
    在这里插入图片描述

注意: 这里查看的只是区域设置, 并不是直接的字符集。 是否还有其他方式查看呢?比如说命令行。
Windows的命令行有一个 systeminfo 命令可以用来查看操作系统的一些设定,执行的结果如下:

在这里插入图片描述

这个命令看到的结果和上面使用控制面板看到的基本一样, 可以查看当前系统的区域语言设置。但并不是直接的字符集。系统字符集通常从区域语言设置和其他系统配置片断中获取,但这些信息并不直接等于字符集。也就是说在Windows命令行中(CMD),不能直接获取当前的字符编码,但可以查看当前的区域语言设置,它影响了系统非Unicode程序使用的字符集。

如果系统区域设置(system locale)是 zh_CN,那么表示系统使用的是简体中文(中国)。在这种设置下,Windows系统通常使用GBK作为默认的字符编码, 注意是“通常”,并不是一定。如何能坐实操作系统使用的字符集呢?

使用Maven查看语言设置和字符集

如果当前的机器安装了Maven ,可以使用Maven查看版本的命令其实可以看到这两种的设置:
在命令行输入:

mvn -v

命令的输入如下:
在这里插入图片描述

以上可以看到操作系统的语言区域和字符集分别是 zh_CN和GBK

Java 的字符集是如何设定

Windows操作系统支持多种不同的字符集,每个应用程序可能使用不同的设置。如果你在Java中创建一个新的进程,那么该进程的默认字符集设置将会继承自Java应用的设置。可以通过Charset.defaultCharset()查询到Java使用的默认字符集。

如果想在Java程序中获取Windows的默认字符集,可以使用System.getProperty(“file.encoding”),这一命令将返回运行Java程序的JVM的系统字符集。在大多数情况下,这应当等同于Windows的系统字符集。然而,这将取决于你的JVM启动参数和环境变量。
所以在Java中获取默认字符集的方式有两种:

  1. 通过System获取文件编码的系统属性System.getProperty("file.encoding")
  2. 通过Charset获取
    具体的代码方式如下:
		System.out.println(System.getProperty("file.encoding"));  
		System.out.println(Charset.defaultCharset());

这里的输出是:

UTF-8
UTF-8

注意: 这两种方式返回的字符编码可能不一样,也可能一样,但是书写并不一致, 可能一个是UTF8,另一个是UTF-8, 但这都不是最主要的, 最主要的是这里的场景下, 为什么不是上面的 GBK? 直接说结论吧:

不管是在Eclipse还是在其他任何环境下运行Java程序,编码配置可能会受到多种因素的影响,包括JVM配置和操作系统设定等。

在Java中,系统默认的字符编码由JVM本身决定,通常与宿主操作系统的区域设置和字符编码设置相同。

系统默认的字符编码是在JVM启动时就被确定下来的,通常是 JVM 根据操作系统的环境设置来决定的。但是 JVM 的默认字符编码也可以通过 JVM 启动参数来改变,如 -Dfile.encoding=UTF-8。
也就是说Java除了可以继承操作系统的字符集外,也可以自行设定字符集。
JVM的字符编码也是可以改变的。

  • 在 Eclipse 中,这可以在 “Run Configurations” -> “Arguments” -> “VM arguments” 中设置。例如添加 -Dfile.encoding=GBK。
  • 也可以通过设置 JVM 的启动参数来实现

字符集的设定

既然上面Java的字符集编码是UTF-8, 那么这里出现乱码的原因是否是字节流转换为字符串时编码的问题呢?
于是想到是否 在InputStreamReader读取字节流的时候转为UTF-8的编码就可以了呢?
于是代码修改为如下:

new InputStreamReader(pr.getErrorStream(),StandardCharsets.UTF_8))

到时, 到这输出的还是乱码。
于是想: 在cmd命令行输出的是中文, 是否字节流转换成GBK的编码就可以了呢?

在 Java 中,StandardCharsets 是一个预定义字符集的工具类,它定义了一些常用的字符集实例。但是,GBK 并没有被包含在 StandardCharsets 里。StandardCharsets 只定义了以下这些常用字符集:US-ASCII、ISO-8859-1、UTF-8、UTF-16BE、 UTF-16LE 和 UTF-16。

如果需要使用 GBK 编码,那么就不能从 StandardCharsets 查找到,而需要直接使用字符串 “GBK” 来代替。例如,如果需要将一个 InputStream 根据 GBK 编码转换为 Reader ,可以使用如下方式:

InputStream inputStream = ...; // 输入流
Reader reader = new InputStreamReader(inputStream, "GBK");

这段代码将会根据 GBK 编码创建一个新的 InputStreamReader。

需要注意的是,字符编码字符串 “GBK” 是大小写不敏感的,你也可以写为 “gbk”。然而,因为大写字符通常更容易阅读和理解,所以 “GBK” 通常是更常用的写法。

字节流转换成GBK 之后, 就正常的输出中文错误信息了, 乱码问题解决了。

最终的解法

在执行操作系统命令, 获取返回信息或是错误信息的场景中, 为了解决乱码的问题,终极的解法就是定义一个获取字符集的方法,因为无法直接获取操作系统的字符集, 就先获取区域语言,如果是 zh_CN,就使用 GBK编码, 否则就使用UTF-8的编码。相关的其他场景也可以据此思路扩展此方法, 方法的定义如下:

	public static String getCharsetName() {
		String charaset = StandardCharsets.UTF_8.toString();
		Locale locale = Locale.getDefault();
		if ("zh_CN".equals(locale.toString())) {
			charaset = "GBK";
		}
		return charaset;
	}


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1046260.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SAP 销售订单审批状态参数设置

定义权限码 BS52 Spro->控制->内部订单->订单主数据->状态管理->定义状态管理授权码 创建状态参数文件 BS02 SPRO->销售与分销->销售->销售凭证->定义并分配状态参数文件->定义状态参数文件 1)命名,描述 设置对象类型:销…

记录一个iOS UITableView 正在刷新的时候修改数据源导致的崩溃

首先看一下崩溃堆栈信息 由于tableview 调用layoutsubViews 执行到代理方法 -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ 由于是崩溃在系统方法里面的,我们无法直接看到是因为调用哪个方法导致的崩溃 后来…

秦时明月沧海手游礼包码,秦时明月沧海兑换码

在玩《秦时明月沧海》手游时,你可能会遭到礼包码的诱惑。如果你还没找到可用的兑换码,这里有一些可供使用的礼包码,赶快领取吧! 关注【娱乐天梯】,获取内部福利号 1. 礼包码:QIN0809 包含:金镒…

面试打底稿⑤ 项目一的第一部分

简历原文 抽查部分 项目描述 该项目旨在服务广州地区的快递物流,实现了下单、快递员取派件、订单转运单、线路规划、网点设置等功能。 责任描述 登录系统优化,双token三验证模式实现设置token状态、提高登录安全性的效果 模拟问答 1.能简单介绍一下…

2023-9-27 JZ18 删除链表的结点

题目链接: 删除链表的结点 import java.util.*;/** public class ListNode {* int val;* ListNode next null;* public ListNode(int val) {* this.val val;* }* }*/public class Solution {/*** 代码中的类名、方法名、参数名已经指定,请…

【C++】友元函数 ( 友元函数简介 | 友元函数声明 | 友元函数语法 | 友元函数声明不受访问控制限制 | 友元函数参数要求 )

文章目录 一、友元函数简介二、友元函数声明1、友元函数语法2、友元函数声明不受访问控制限制3、友元函数参数要求4、友元函数示例 三、完整代码示例 - 友元函数 一、友元函数简介 在 C 语言中 , " 友元函数 " 是 与 类 相关联的函数 , " 友元函数 " 不是…

【Verilog 教程】6.6Verilog 仿真激励

关键词:testbench,仿真,文件读写 Verilog 代码设计完成后,还需要进行重要的步骤,即逻辑功能仿真。仿真激励文件称之为 testbench,放在各设计模块的顶层,以便对模块进行系统性的例化调用进行仿真…

对象存储,从单机到分布式的演进

关于数据存储的相关知识,请大家关注“数据存储张”,各大平台同名。 通过《什么是云存储?从对象存储说起》我们对对象存储的历史、概念和基本使用有了一个大概的认识。而且我们以Minio为例,通过单机部署的模式实际操作了一下对象存储的GUI,感受了一下对象存储的用法。 在上…

word中使用latex多行公式,矩阵公式

\eqarray{H& [h(x_1)^T,\cdots,h(x_N)^T]^T \\ & [\matrix{g(w_1 x_1b_1) & \cdots & g(w_L x_1b_L) \\ \vdots & \ddots & \vdots \\ g(w_1 x_Nb_1) & \cdots & g(w_L x_Nb_L)}]_{N \times L}}&的引起的那条竖线可以通过backspace或者del…

人工智能AI 全栈体系(七)

第一章 神经网络是如何实现的 神经网络不仅仅可以处理图像,同样也可以处理文本。由于处理图像讲起来比较形象,更容易理解,所以基本是以图像处理为例讲解的。 七、词向量 图像处理之所以讲起来比较形象,是因为图像的基本元素是像…

VB6.0开发文件管理小数据库-基于ACCESS

今天的客户也是小客户,需要对文件的一些操作记录在数据库里面,这里采用的数据库ACCCESS,用的是VB自带的可视化数据管理器创建的mdb数据库文件。实现了数据的增删改查。简单方便。基本可以用这套代码模板实现大部分的数据库功能了。想研发或学…

自定义ElementPlus主题颜色

构建工具采用Vite CSS预处理器采用Sass 一.准备定制化的样式文件 1.安装Sass npm i sass -D 2.创建好文件目录 3.书写样式 ElementPlus默认样式. //index.scss/* 只需要重写你需要的即可 */ forward element-plus/theme-chalk/src/common/var.scss with ($colors: (prim…

腾讯云秒杀活动是什么?如何参与?

腾讯云是国内知名的云计算服务提供商之一,为了吸引更多的用户,腾讯云会不定期地推出各种各样的优惠活动,其中最受大家欢迎的就是“腾讯云秒杀活动”。本文将为大家详细介绍腾讯云秒杀活动参与方式以及购买攻略。 一、腾讯云秒杀活动是什么&am…

【操作系统】处理机调度的基本概念和三个层次、进程调度的时机和方式、调度器、闲逛线程

🐌个人主页: 🐌 叶落闲庭 💨我的专栏:💨 c语言 数据结构 javaEE 操作系统 Redis 石可破也,而不可夺坚;丹可磨也,而不可夺赤。 操作系统 一、处理机调度基本概念二、处理机…

【论文阅读】UniDiffuser: Transformer+Diffusion 用于图、文互相推理

而多模态大模型将能够打通各种模态能力,实现任意模态之间转化,被认为是通用式生成模型的未来发展方向。 最近看到不少多模态大模型的工作,有医学、金融混合,还有CV&NLP。 今天介绍: One Transformer Fits All Di…

七、装饰者模式

这里写自定义目录标题 1、项目需求2、解决方案13、解决方案24、装饰者模式定义5、装饰者模式原理6、装饰者模式解决上述需求7、装饰者模式在jdk应用的源码分析 1、项目需求 2、解决方案1 3、解决方案2 可以控制类的数量,不至于造成很多的类在增加或者删除调料种类…

100万级连接,石墨文档WebSocket网关如何架构?

说在前面 在40岁老架构师 尼恩的读者交流群(50)中,很多小伙伴拿到一线互联网企业如阿里、网易、有赞、希音、百度、滴滴的面试资格。 最近,尼恩指导一个小伙伴简历,写了一个《高并发网关项目》,此项目帮这个小伙拿到 字节/阿里/…

自学WEB后端05-Node.js后端服务链接数据库redis

嘿,亲爱的小伙伴们!😄 今天我要给大家分享一个超级方便且高效的 NoSQL 类型数据库——Redis!💡 它可不是一般的关系型数据库哦,而是以键值对形式存储数据的内存数据库。📚 快跟着我一起来学习如…

GEO生信数据挖掘(一)数据集下载和初步观察

检索到目标数据集后,开始数据挖掘,本文以阿尔兹海默症数据集GSE1297为例 目录 GEOquery 简介 安装并加载GEOquery包 getGEO函数获取数据(联网下载) 更换下载数据源 对数据集进行初步观察处理 GEOquery 简介 GEOquery是一个…

基于springboot+vue的旅游系统(前后端分离)

博主主页:猫头鹰源码 博主简介:Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容:毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目介绍…