转换流

通常,Window默认的编码方式是GBK,Java项目一般建议设为UTF-8编码。这时候读取文件可能出现乱码。事实上实际应用中编码格式不匹配的场景非常多。

转换流可以指定编码方式,用于解决乱码问题。

OutputStreamWriter
InputStreamReader

字符编码:Character Encoding:自然语言的字符,与二进制数之间的对应规则。

文件流读取时使用的编码方式和文件本身编码方式不同时,会造成读取出来时出现乱码。

字符集 :Charset:系统支持的所有字符的集合,包括数字、文字、标点符号、图形符号等。一套字符集至少有一套字符编码。常见字符集有ASCII字符集、GBK字符集、Unicode字符集等。

ASCII字符集

|--ASCII(American Standard Code for Information Interchange,美国信息交换标准代码)是基于拉丁字母的一套电脑编码系统,用于显示现代英语,主要包括控制字符(回车键、退格、换行键等)和可显示字符(英文大小写字符、阿拉伯数字和西文符号)。

|--|--基本的ASCII字符集,使用7位(bits)表示一个字符,共128字符。

|--|--ASCII的扩展字符集使用8位(bits)表示一个字符,共256字符,方便支持欧洲常用字符。

ISO-8859-1字符集

|--拉丁码表,别名Latin-1,用于显示欧洲使用的语言,包括荷兰、丹麦、德语、意大利语、西班牙语等。

|--ISO-8859-1使用单字节编码,兼容ASCII编码。

GBxxx字符集:GB乃“国标”之意,是为了显示中文而设计的一套字符集。

|--GB2312:简体中文码表。一个小于127的字符的意义与原来相同。但两个大于127的字符连在一起时,就表示一个汉字,大约包含7000多个简体汉字,还有数学符号、希腊字母、日文假名,连在ASCII里本来就有的数字、标点、字母都统统重新编了两个字节长的编码,这便是所谓的"全角"字符,而原来在127号以下的那些就叫"半角"字符了。

|--GBK:最常用的中文码表。是在GB2312标准基础上的扩展规范,使用了双字节编码方案,共收录了21003个汉字,完全兼容GB2312标准,同时支持繁体汉字以及日韩文字等。Windows操作系统默认使用GBK编码。

|--GB18030:最新的中文码表。收录汉字7万多个,采用多字节编码,每个字可以由1个、2个或4个字节组成。支持中国国内少数民族的文字,同时支持繁体汉字以及日韩汉字等。

Unicode字符集

Unicode编码系统为表达任意语言的任意字符而设计,是业界的一种标准,也称为统一码、标准万国

码。

有三种编码方案,UTF-8、UTF-16和UTF-32。最为常用的UTF-8编码。

|--UTF-8,可以用来表示Unicode标准中任何字符,它是电子邮件、网页及其他存储或传送文字的应用中,优先采用的编码。互联网工程工作小组(IETF)要求所有互联网协议都必须支持UTF-8编码。

UTF-8使用1至4个字节为进行编码(最大可占用6字节),编码规则:

  1. 128个ASCII字符,一个字节编码。
  2. 拉丁文等字符,两个字节编码。
  3. 大部分常用字(含中文),使用三个字节编码,基本等同于GBK。
  4. 还有一些字符使用四字节编码。

参考【utf-8中的汉字占用多少字节】:https://www.cnblogs.com/zxz1987/articles/6544593.html

看看UTF-8编码占了几个字节:

public class TestCharEncoding {
public static void main(String[] args) throws Exception {
String[] strArr = { "A", "Ω", "壹" };
for (String s : strArr) {
System.out.println("s:" + s.getBytes("utf-8").length);
}
}
}

运行结果

s:1
s:2
s:3

示例代码:转换流可以读写各种编码的文件,而纯字符流则可能读出乱码。

  • 使用FileInputStream类读取文件流,
  • 利用InputStreamReader将字节流转化为字符流,同时指定文件流的编码方式,
  • 再将字符流放入 BufferedReader中进行操作。

File → FileOutputStream → OutputStreamWriter(指定编码) → BufferedWriter

File → FileInputStream → InputStreamReader(指定编码) → BufferedReader

package ahjava.io;
import java.io.*;
public class 转换流 {
public static final String FILE_NAME = "testMessyCode.txt";
public static final String CHARSET_NAME = "gbk";
// File->FileOutputStream->OutputStreamWriter(指定编码)->BufferedWriter
static void write(String msg) throws Exception {
File f = new File(FILE_NAME);
FileOutputStream fos = new FileOutputStream(f);
OutputStreamWriter osw = new OutputStreamWriter(fos, CHARSET_NAME);
BufferedWriter bw = new BufferedWriter(osw);
bw.write(msg);
// 关闭流(写文件的关闭顺序如果不对,会抛异常,读文件没有影响)
bw.close();
osw.close();
fos.close();
}
// File->FileInputStream->InputStreamReader(指定编码)->BufferedReader
static void read() throws Exception {
File f = new File(FILE_NAME);
FileInputStream fis = new FileInputStream(f);
InputStreamReader isr = new InputStreamReader(fis, CHARSET_NAME);
BufferedReader br = new BufferedReader(isr);
String str;
while ((str = br.readLine()) != null) // 逐行读取数据
{
System.out.println(CHARSET_NAME + "读取:" + str);
}
// 关闭流
br.close();
isr.close();
fis.close();
}
static void 纯字符流R_就怕货比货() {
File file = new File(FILE_NAME);
FileReader fr;
try {
fr = new FileReader(file);
BufferedReader br = new BufferedReader(fr);
String str;
while ((str = br.readLine()) != null) {
System.out.println("纯字符流读取:" + str);
}
br.close();
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception {
write("乱码?");
纯字符流R_就怕货比货();
read();
}
}

*控制台输入

场景:控制台输入文字,写入文件。

通常建议把Java工程设为UTF-8编码。这时候如果写文件,文件是UTF-8编码。

然而,Windows平台默认的编码方式是GBK,可以通过转换流以GBK的编码方式写文件。

以下代码就是以GBK的编码格式把用户在控制台的输入写入文件。

import java.io.*;
public class 控制台输入 {
public static void main(String[] args) throws IOException {
控制台写入文件();
}
static void 控制台写入文件() throws IOException {
/* 本例从控制台接受输入,然后写入到文件中,直到用户输入"!!!"为止 */
// 输出:FileOutputStream->OutputStreamWriter(指定编码)->BufferedWriter
FileOutputStream fos = new FileOutputStream("控制台写入文件.txt");
OutputStreamWriter osw = new OutputStreamWriter(fos, "GBK");
BufferedWriter bw = new BufferedWriter(osw);
// 输入:System.in(字节流)->InputStreamReader->BufferedReader
// 将控制台输入对象转化成字符流,并建立缓冲流
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
String str = br.readLine(); // 接受从控制台输入的一行字符串
while (!(str.equals("!!!"))) // 如果输入"!!!"则代表输入结束
{
bw.write(str); // 将从控制台输入的字符串写入到文件中
bw.newLine(); // 换新行
str = br.readLine(); // 再从控制台接受输入
}
// 关闭输入相关的流
br.close();
isr.close();
// 关闭输出相关的流
bw.close();
osw.close();
fos.close();
}
}

*想想,“控制台写入文件()”方法,能不能连续调用两次?

Java基础教程——转换流的更多相关文章

  1. java基础(24):转换流、缓冲流

    1. 转换流 在学习字符流(FileReader.FileWriter)的时候,其中说如果需要指定编码和缓冲区大小时,可以在字节流的基础上,构造一个InputStreamReader或者OutputS ...

  2. java基础 关于转换流

    转换流有两种:InputStreamReader:将字节流转换为字符流 OutputStreamWriter:将字符流转换为字节流 什么时候使用转换流?由以下分析: 流对象很多,首先要明确那个流对象. ...

  3. JAVA基础之转换流和缓冲流

    个人理解: 在理解的字符流和字节流的区别后.要是想读取指定的编码格式的文件时,特别是不是默认的格式时,就需要转换流了,需要注意的是字符流是需要清除缓冲区的:当需要快速的进行读取时,则需要缓冲流.存在即 ...

  4. Java基础 使用转换流进行文件的复制 / RandomAccessFile 类进行文件的复制

    笔记:  **使用转换流进行文件的复制 文本文件---字节流FileInputStream--> [InputStreamReader] -----字符流BufferedReader------ ...

  5. Java基础教程——打印流

    打印流 打印流可以把原本输出到控制台的信息输出到文件中.PrintStream是字节打印流(还有个对应的字符打印流是PrintWriter,这里不涉及) System类中有个变量: public fi ...

  6. Java基础教程——缓冲流

    缓冲流 "缓冲流"也叫"包装流",是对基本输入输出流的增强: 字节缓冲流: BufferedInputStream , BufferedOutputStream ...

  7. Java基础教程——字符流

    字符流 字节流服务文本文件时,可能出现中文乱码.因为一个中文字符可能占用多个字节. 针对于非英语系的国家和地区,提供了一套方便读写方式--字符流. java.io.Reader java.io.Wri ...

  8. Java基础教程:面向对象编程[2]

    Java基础教程:面向对象编程[2] 内容大纲 访问修饰符 四种访问修饰符 Java中,可以使用访问控制符来保护对类.变量.方法和构造方法的访问.Java 支持 4 种不同的访问权限. default ...

  9. Java基础教程:JDBC编程

    Java基础教程:JDBC编程 1.什么是JDBC JDBC 指 Java 数据库连接,是一种标准Java应用编程接口( JAVA API),用来连接 Java 编程语言和广泛的数据库. JDBC A ...

随机推荐

  1. 微信小程序日历签到

    近日做了一个项目需要用到日历插件,在网上找了一部分感觉跟项目不对口,所以就查考了其他的日历插件做了一个. 需求: 如图: 代码如下: index.wxml: <!--pages/pictrues ...

  2. Docker学习笔记之--.Net Core应用容器通过网桥连接Redis容器(环境:centos7)

    上节演示通过应用容器连接sql server容器,连接:Docker学习笔记之--.Net Core项目容器连接mssql容器(环境:centos7) 本节演示安装 redis容器,通过网桥连接 先决 ...

  3. U137971 公司搬迁 - 并查集 奇偶性

    题目描述 因为人员规模扩大,T公司准备搬到新的写字楼去,写字楼分为A座和B座,n名不同工号的员工x(p1,p2,p3...pn) 按照下面两个规则确定在A座或者B座进行办公:(1)如果工号为x的员工在 ...

  4. 扩展中国剩余定理(EXCRT)快速入门

    问题 传送门 看到这个问题感觉很难??? 不用怕,往下看就好啦 假如你不会CRT也没关系 EXCRT大致思路 先考虑将方程组两两联立解开,如先解第一个与第二个,再用第一个与第二个的通解来解第三个... ...

  5. Django做验证码登录

    验证码 关注公众号"轻松学编程"了解更多. 1.作用 在用户登录,注册以及一些敏感操作的时候,我们为了防止服务器被暴力请求,或爬虫爬取,我们可以使用验证码进行过滤,减轻服务器的压力 ...

  6. LWJGL3的内存管理,第一篇,基础知识

    LWJGL3的内存管理,第一篇,基础知识 为了讨论LWJGL在内存分配方面的设计,我将会分为数篇随笔分开介绍,本篇将主要介绍一些大方向的问题和一些必备的知识. 何为"绑定(binding)& ...

  7. 利用VS2017制作软件安装包与卸载程序

    本博客讲述如何利用VS2017制作安装包以及相应的卸载程序,并解决过程中可能遇到的问题 一.制作安装程序 1.打开VS2017,新建项目,选择如下图所示程序: 新建成功后,会出现如下图所示目录: 2. ...

  8. 前言「HarmonyOS应用开发基础篇」

    场景一.随着智能设备种类的不断增多,我们基本上每人都有好几台智能设备,比如智能手机,平板,耳机,音响,穿戴设备等等.这些设备都具有独立性,偶尔的组合也是我们通过手动去搭配,并且不一定能够完全组合在一起 ...

  9. TCP/IP协议与Socket

    1.计算机网络体系结构分层 OSI 参考模型注重"通信协议必要的功能是什么", TCP/IP 则更强调"在计算机上实现协议应该开发哪种程序". 2.TCP/IP ...

  10. 对List对象里的其中两个属性配套去重

    List<User> disList= list.stream().collect(Collectors.collectingAndThen(Collectors.toCollection ...