从零开始学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编码格式。如果你现在想不起来,可以回过头去看看哦。

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

相关推荐
yuanbenshidiaos29 分钟前
c++---------数据类型
java·jvm·c++
向宇it32 分钟前
【从零开始入门unity游戏开发之——C#篇25】C#面向对象动态多态——virtual、override 和 base 关键字、抽象类和抽象方法
java·开发语言·unity·c#·游戏引擎
Lojarro1 小时前
【Spring】Spring框架之-AOP
java·mysql·spring
莫名其妙小饼干1 小时前
网上球鞋竞拍系统|Java|SSM|VUE| 前后端分离
java·开发语言·maven·mssql
isolusion1 小时前
Springboot的创建方式
java·spring boot·后端
zjw_rp1 小时前
Spring-AOP
java·后端·spring·spring-aop
Oneforlove_twoforjob2 小时前
【Java基础面试题033】Java泛型的作用是什么?
java·开发语言
TodoCoder2 小时前
【编程思想】CopyOnWrite是如何解决高并发场景中的读写瓶颈?
java·后端·面试
向宇it2 小时前
【从零开始入门unity游戏开发之——C#篇24】C#面向对象继承——万物之父(object)、装箱和拆箱、sealed 密封类
java·开发语言·unity·c#·游戏引擎
小蜗牛慢慢爬行2 小时前
Hibernate、JPA、Spring DATA JPA、Hibernate 代理和架构
java·架构·hibernate