从零开始学Java之如何解决Java及I/O流的字符编码问题

作者 :孙玉昌,昵称【一一哥 】,另外【壹壹哥】也是我哦

千锋教育高级教研员、CSDN博客专家、万粉博主、阿里云专家博主、掘金优质作者

前言

在前面的两篇文章中,壹哥 给大家讲解了字节流和字符流的使用,但在进行文件读写时,如果文件的内容涉及到了中文,就有可能会出现乱码问题,这是怎么回事呢?所以在今天的文章中,壹哥会给大家分析一下计算机中的编码问题,以及在IO流中如何设置编码,快来看看吧。

------------------------------前戏已做完,精彩即开始----------------------------

全文大约【2400】 字,不说废话,只讲可以让你学到技术、明白原理的纯干货!本文带有丰富的案例及配图视频,让你更好地理解和运用文中的技术概念,并可以给你带来具有足够启迪的思考......

配套开源项目资料

Github: github.com/SunLtd/Lear...

Gitee: gitee.com/sunyiyi/Lea...

一. 编码方式

1. 简介

计算机里的任意文字和符号,在输出前其实都会设置对应的字符编码。而所谓的字符编码,则是一种将字符集中的字符映射到二进制编码的方式。而字符编码的过程又可以分为编码和解码,编码是把数据信息从一种形式或格式转换为另一种形式的过程,解码则是编码的逆过程。

在不同的字符编码中,同一个字符对应的二进制编码可能是不同的。因此,当不同的程序或操作系统使用不同的字符编码时,就可能导致字符集不兼容的问题。所以一个文本信息,在输入时采用UTF-8编码,则输出时也应该使用UTF-8解码,否则就有可能会出现乱码问题。尤其是针对中文内容,更是要保证编码和解码时采用一致的格式。这就好比两个人交谈,一个人说中文,另一个人说英语,语言不同就无法沟通。当然,有些编码之间可以相互兼容,此时同一个西文采用不同的编码可能并不会产生乱码。

2. 常用的编码格式

目前在Java开发中,比较常见的编码格式有ASCII、ISO-8859-1、GBK/GB2312、Unicode、 UTF-8、UTF-16、UTF-32等编码:

  • ASCII编码: ASCII码是一种7位的编码方式,最多可以表示128种不同的字符,包括英文字母、数字和符号等。在Java中,常用的ASCII码其实是采用ISO-8859-1的编码方式。
  • ISO-8859-1编码:单字节编码,是对ASCII码的扩充实现,最多可以表示0~255之间的字符范围,包括拉丁字母、希腊字母、标点符号和其他特殊符号等;
  • GBK/GB2312编码:中文的国标编码,用来表示汉字,属于双字节编码。GBK可以表示简体中文和繁体中文,GB2312只能表示简体中文,GBK会兼容GB2312。
  • Unicode编码 :这是为解决全球字符通用编码而设计的一种编码规范,它可以表示世界上几乎所有的字符,包括中文、日文、韩文等,Java内部就采用此编码。UTF-8和 UTF-16都是对这种规范的具体实现,但此编码不兼容ISO-8859-1编码。Java中常用的Unicode编码方式是UTF-8、UTF-16和UTF-32等。其中,UTF-8是一种变长的编码方式 ,可以表示Unicode字符集中的任意字符,每个字符占用1~4个字节。UTF-16是一种固定长度的编码方式 ,每个字符占用2个字节,适合于表示中文等字符数量较少的语言。UTF-32是一种固定长度的编码方式,每个字符占用4个字节,适合于表示字符数量较多的语言。

3. Java中文乱码问题

我们在进行Java开发时,经常会遇到中文乱码,如果出现了中文乱码,可以按照以下几种方式进行解决。

3.1 setProperty方法设置编码方式

在Java程序中,我们可以使用System.setProperty()方法设置编码方式,例如:

java 复制代码
System.setProperty("file.encoding","UTF-8");

3.2 JPanel设置中文字体

如果我们是进行JPanel开发,例如在使用JLabel和JTextField等组件时,可以使用如下代码来支持中文字体:

java 复制代码
JLabel label = new JLabel("中文"); 
label.setFont(new Font("宋体", Font.PLAIN, 14));

3.3 在HTTP头信息中设置中文编码

而在进行Web开发时,可以在HTTP头信息中设置编码,如下所示:

java 复制代码
response.setContentType("text/html;charset=UTF-8");

3.4 IO流中设置中文字符集

如果是进行IO流的开发,则需要使用正确的字符集读取和写入文件。例如,在使用InputStreamReader和OutputStreamWriter读取和写入文件时,需要指定正确的字符集,实例代码如下:

java 复制代码
//给InputStreamReader设置编码
InputStreamReader isr = new InputStreamReader(new FileInputStream("test.txt"),"UTF-8"); 

//给OutputStreamWriter设置编码
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("test.txt"),"UTF-8");

二. 利用转换流设置编码

1. 概述

我们在使用IO流进行文件读写时,也经常会遇到编码问题。这是因为不同的操作系统和应用程序中,使用的字符编码可能会不同,这样在读写文件时可能会导致出现乱码或者字符集不兼容的问题。针对IO流中的乱码问题,我们可以通过指定字符编码来解决编码问题。

另外我们知道,InputStreamReader是一种用于将字节输入流转换为字符输入流的转换流, OutputStreamWriter是一种用于将字节输出流转换为字符输出流的转换流,我们使用转换流可以指定输入输出所使用的字符编码,这样就可以在一定程度上避免乱码。

2. 输入流的编码设置

比如,我们在读取文本文件时,可以使用InputStreamReader将字节流转换为字符流,并指定文件的字符编码,代码如下:

java 复制代码
FileInputStream fis = new FileInputStream("example.txt");
InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
BufferedReader br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null) {
    System.out.println(line);
}

在上面的代码中,我们使用了UTF-8编码来读取example.txt文件。如果文件使用的是其他的字符编码,我们要相应地修改字符编码。

3. 输出流的编码设置

类似地,在写入文本文件时,我们也需要指定字符编码。例如:

java 复制代码
FileOutputStream fos = new FileOutputStream("example.txt");
OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8");
BufferedWriter bw = new BufferedWriter(osw);
bw.write("Hello, world!");
bw.newLine();
bw.close();

在上面的代码中,我们使用了UTF-8编码来写入文本文件。同样地,如果我们需要使用其他的字符编码,也可以相应地修改字符编码。

需要注意的是,如果文件的字符编码和指定的字符编码不匹配,就会导致读写出错或者出现乱码。因此,在进行文件读写时,一定要确认文件的字符编码,并相应地指定字符编码。

除了在读写文件时指定字符编码,还有一些其他的解决方案。例如,可以在程序中将字符编码转换为统一的编码,例如统一使用UTF-8编码。这样可以保证不同程序之间使用的字符编码一致,从而避免字符集不兼容的问题。另外,一些文本编辑器也提供了自动检测文件字符编码的功能,可以帮助我们确认文件的字符编码。

总之,我们在使用IO流进行文件读写时,要注意字符编码的问题。通过指定字符编码或者将字符编码转换为统一的编码,可以有效地避免字符集不兼容的问题。

------------------------------正片已结束,来根事后烟----------------------------

三. 结语

至此,壹哥 就把Java中的编码问题给大家简单讲解了一下,现在你知道该如何设置编码格式了吗?大家要注意,实际上我们在开发时,一般都是使用IDE工具进行开发,在安装配置工具时都会统一设置常用的编码格式。壹哥在之前讲解editplus、eclipse和intellij idea时,都已经给大家讲解了如何设置全局统一的UTF-8编码格式。如果你现在想不起来,可以回过头去看看哦。

如果你独自学习觉得有很多困难,可以加入壹哥的学习互助群,大家一起交流学习。

相关推荐
Asthenia04121 小时前
Spring扩展点与工具类获取容器Bean-基于ApplicationContextAware实现非IOC容器中调用IOC的Bean
后端
bobz9651 小时前
ovs patch port 对比 veth pair
后端
Asthenia04121 小时前
Java受检异常与非受检异常分析
后端
uhakadotcom2 小时前
快速开始使用 n8n
后端·面试·github
JavaGuide2 小时前
公司来的新人用字符串存储日期,被组长怒怼了...
后端·mysql
bobz9652 小时前
qemu 网络使用基础
后端
Asthenia04122 小时前
面试攻略:如何应对 Spring 启动流程的层层追问
后端
Asthenia04122 小时前
Spring 启动流程:比喻表达
后端
Asthenia04123 小时前
Spring 启动流程分析-含时序图
后端
ONE_Gua3 小时前
chromium魔改——CDP(Chrome DevTools Protocol)检测01
前端·后端·爬虫