一、字节流读取中文时出现的问题:

文件中有中文时,用字节流读取会出现乱码的问题,因为一个中文为两个字节。

二、字符编码表

编码表:其实就是生活中字符和计算机二进制的对应关系表。

1、ascii: 一个字节中的7位就可以表示。对应的字节都是正数。0-xxxxxxx

2、iso-8859-1:拉丁码表 latin用了一个字节用的8位。1-xxxxxxx  负数。

3、GB2312:简体中文码表。包含6000-7000中文和符号。用两个字节表示。两个字节第一个字节是负数,第二个字节可能是正数

GBK:目前最常用的中文码表,2万的中文和符号。用两个字节表示,其中的一部分文字,第一个字节开头是1,第二字节开头是0

GB18030:最新的中文码表,目前还没有正式使用。

4、unicode:国际标准码表:无论是什么文字,都用两个字节存储。

Java中的char类型用的就是这个码表。char c = 'a';占两个字节。

Java中的字符串是按照系统默认码表来解析的。简体中文版 字符串默认的码表是GBK。

5、UTF-8:基于unicode,一个字节就可以存储数据,不要用两个字节存储,而且这个码表更加的标准化,在每一个字节头加入了编码信息(后期到api中查找)。

能识别中文的码表:GBK、UTF-8;正因为识别中文码表不唯一,涉及到了编码解码问题。

对于我们开发而言,常见的编码 GBK  UTF-8  ISO-8859-1

文字--->(数字) :编码。 “abc”.getBytes()  byte[]    //数字就是字节

(数字)--->文字  : 解码。 byte[] b={97,98,99}  new String(b)  用new String 传一个字节数组

三、字符输入流  Reader类

Reader类:读取字符流的超类。

方法:

1.read():读取单个字符并返回

2.read():将数据读取到数组中,并返回读取的个数

四、字符输入类 FileReader类

Reader类的子类,用来读取字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是适当的。

 构造方法:FileReader fr=new FileReader(文件路径/文件对象);

package com.oracle.demo01;
import java.io.FileReader;
import java.io.IOException;
//字符输入流
public class ReaderDemo {
//因为是一个字符一个字符读取的,所以读取中文不会出现乱码,专门用来处理文本文件
public static void main(String[] args) throws IOException {
// 1.获取数据源
FileReader fr=new FileReader("d:\\java\\writer.txt");
//2.读取数据
int len=0;
while((len=fr.read())!=-1){
System.out.println((char)len);
}
fr.close();
} }

五、字符输出流 Writer类

Writer是写入字符流的抽象类。其中描述了相应的写的动作。

 方法:

六、字符输出类 FileWriter类

Writer类的子类,用来写入字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是可接受的。

 构造方法:FileWriter fw=new FileWriter(文件路径/文件对象);

package com.oracle.demo01;

import java.io.FileWriter;
import java.io.IOException;
//字符输出流
public class WriteDemo {
//字符流处理的是文本文件
public static void main(String[] args) throws IOException {
// 文本文件:打开人能看懂的就是文本文件
//1.确定目的地
FileWriter fw=new FileWriter("d:\\java\\writer.txt",true);
//2.写入数据
//fw.write(100); // 如果不刷新,会保存在内存中
// char[] ch={'猴','赛','雷'}; //字符数组
// fw.write(ch,0,2); //可以输出字符数组,也可以控制输出的长度
fw.write("崔永元实话实说",0,3); //单引号是 字符,双引号是字符串
//3.刷新
fw.flush();
//4.释放资源
fw.close();
} }

 flush()方法与colse()方法的区别:

flush():将流中的缓冲区缓冲的数据刷新到目的地中,刷新后,流还可以继续使用,还可以继续输出。

close():关闭资源,但在关闭前会将缓冲区中的数据先刷新到目的地,否则丢失数据,然后再关闭流。关闭后流不可以使用。

注意:如果写入数据多,一定要一边写一边刷新,最后一次可以不刷新,由close完成刷新并关闭。

 练习题:用字符流复制文件

package com.oracle.demo01;

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
//用字符流复制文本文件,不要用来复制图片与视频等
public class Copy { public static void main(String[] args) throws IOException {
// 1.获取数据源
FileReader fr=new FileReader("e:\\java\\outint.PNG");
//2.获取目标
FileWriter fw=new FileWriter("D:\\java\\outin.png");
//3.读取并写入
int len =0;
char[] ch=new char[1024];
while((len=fr.read(ch))!=-1){
fw.write(ch,0,len);
}
fw.flush();
fr.close();
fw.close();
} }

 七、转换流

如果需要指定编码和缓冲区大小时,可以在字节流的基础上,构造一个InputStreamReader或者OutputStreamWriter。比如,如果文件内为UTF-8格式,但是电脑系统默认的格式为GBK格式,直接读取的话会出现读取内容与文件内容不符的问题,这个时候就需要转换流来转换。

7.1输出转换类OutputStreamWriter类

OutputStreamWriter 是字符流通向字节流的桥梁:可使用指定的字符编码表,将要写入流中的字符编码成字节。它的作用的就是,将字符串按照指定的编码表转成字节,再使用字节流将这些字节写出去。

package com.oracle.demo01;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
//转换流 输出
public class OutputStreamDemo {
//结尾为Streatm的为字节流 结尾为reader或writer的为字符流
public static void main(String[] args) throws IOException {
//1.确定目的地
//字节流输出对象
FileOutputStream fos=new FileOutputStream("e:\\java\\writer.txt",true);
//2.设置走哪个码表 码表是文本文件内容所使用的码表
OutputStreamWriter osw=new OutputStreamWriter(fos,"utf-8");
//3.写入数据
//写入时就转换为了指定码表的字符流
osw.write("野猪佩奇");
osw.flush();
osw.close();
} }

OutputStreamWriter流对象,它到底如何把字符转成字节输出的呢?

其实在OutputStreamWriter流中维护自己的缓冲区,当我们调用OutputStreamWriter对象的write方法时,会拿着字符到指定的码表中进行查询,把查到的字符编码值转成字节数存放到OutputStreamWriter缓冲区中。然后再调用刷新功能,或者关闭流,或者缓冲区存满后会把缓冲区中的字节数据使用字节流写到指定的文件中。

7.2转换输入流 InputStreamReader类

InputStreamReader 是字节流通向字符流的桥梁:它使用指定的字符编码表读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。

package com.oracle.demo01;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader; public class InputStreamDemo {
//转换流 先走码表,根据码表解析,然后再进行读写操作
public static void main(String[] args) throws IOException {
//1.获取数据源
FileInputStream fis=new FileInputStream("e:\\java\\writer.txt");
//2.设置走哪个码表
InputStreamReader isr=new InputStreamReader(fis,"utf-8");
//3.读取数据
int len=0;
while((len=isr.read())!=-1){
System.out.print((char)len);
}
isr.close(); } }

注意:在读取指定的编码的文件时,一定要指定编码格式,否则就会发生解码错误,而发生乱码现象。

7.3转换流和字符类区别

发现有如下继承关系:

父类:OutputStreamWriter:

子类:FileWriter:

父类:InputStreamReader:

     子类:FileReader;

OutputStreamWriter和InputStreamReader是字符和字节的桥梁:也可以称之为字符转换流。字符转换流原理:字节流+编码表。

FileWriter和FileReader:作为子类,仅作为操作字符文件的便捷类存在。当操作的字符文件,使用的是默认编码表时可以不用父类,而直接用子类就完成操作了,简化了代码。

InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"));//默认字符集。

InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"),"GBK");//指定GBK字符集。

FileReader fr = new FileReader("a.txt");

这三句代码的功能是一样的,其中第三句最为便捷。

注意:一旦要指定其他编码时,绝对不能用子类,必须使用字符转换流。什么时候用子类呢?

条件:

1、操作的是文件。2、使用默认编码。

总结:

字节--->字符 : 看不懂的--->看的懂的。  需要读。输入流。 InputStreamReader

字符--->字节 : 看的懂的--->看不懂的。  需要写。输出流。 OutputStreamWriter

练习题:

package com.oracle.demo01;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
//转换流复制文本文件
public class CopyTwo { public static void main(String[] args) throws IOException {
FileInputStream fis=new FileInputStream("e:\\java\\writer.txt");
InputStreamReader osr=new InputStreamReader(fis,"utf-8");
FileOutputStream fos=new FileOutputStream("d:\\java\\writer.txt");
OutputStreamWriter osw=new OutputStreamWriter(fos,"utf-8");
int len=0;
while((len=osr.read())!=-1){
osw.write(len);
}
osr.close();
osw.flush();
osw.close();
} }

Java第三阶段学习(三、字符流、转换流)的更多相关文章

  1. Java第三阶段学习(四、缓冲流)

    一.缓冲流: Java中提供了一套缓冲流,它的存在,可提高IO流的读写速度 缓冲流,根据流的分类分为:字节缓冲流与字符缓冲流. 二.字节缓冲流: 字节缓冲流根据流的方向,共有2个: 1.写入数据到流中 ...

  2. Java第三阶段学习(二、IO流--------递归,字节流Stream)

    一.递归 定义:指方法在方法内调用自己 适用于方法的运算主体不变,但运行的时候,参与运算的方法参数会变化注意:一定要给递归一个出口,否则内存溢出 练习题1:使用递归打印文件夹中所有的文件,包含子目录中 ...

  3. Java第三阶段学习(一、IO流------File类)

    一.IO概述: 把内存中的数据存入到硬盘(持久化设备)中叫做:输出(写)Output操作.JAVA软件往电脑硬盘上走叫输出. 把硬盘中的数据读取到到内存里叫做:输入(读)Input操作.电脑硬盘上往J ...

  4. Java精选笔记_IO流(转换流、常用流、流操作规律、字符编码)

    IO流 用来处理设备之间的数据传输,java对数据的操作是通过流的方式,java用于操作流的对象都在IO包中 按操作数据分为:字节流和字符流:按流向分为:输入流和输出流. 程序从输入流中读取数据,向输 ...

  5. Java第三阶段学习(五、流的操作规律、Properties流、序列化流与反序列化流、打印流、commons-IO jar包)

    一.流的操作规律 四个明确: 明确一:明确要操作的数据是数据源还是数据目的地 源:InputStream   Reader 目的地:OutputStream Writer 先根据需求明确是要读还是写 ...

  6. (java)selenium webdriver学习---三种等待时间方法:显式等待,隐式等待,强制等待

    selenium webdriver学习---三种等待时间方法:显式等待,隐式等待,强制等待 本例包括窗口最大化,刷新,切换到指定窗口,后退,前进,获取当前窗口url等操作: import java. ...

  7. Java学习笔记39(转换流)

    转换流:字符流和字节流之间的桥梁 用于处理程序的编码问题 OutputStreamWriter类:字符转字节流 写文本文件: package demo; import java.io.FileOutp ...

  8. Java IO流学习总结五:转换流-InputStreamReader、OutputStreamWriter

    类的继承关系 Reader |__ BufferedReader.StringReader.InputStreamReader |__ FileReader Writer |__ BufferedWr ...

  9. java IO之 编码 (码表 编码 解码 转换流)

    编码 什么是编码? 计算机中存储的都是二进制,但是要显示的时候,就是我们看到的却可以有中国 ,a  1 等字符 计算机中是没有存储字符的,但是我们却看到了.计算机在存储这些信息的时候,根据一个有规 则 ...

随机推荐

  1. Hadoop生态圈-注册并加载协处理器(coprocessor)的三种方式

    Hadoop生态圈-注册并加载协处理器(coprocessor)的三种方式 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 到目前为止,大家已经掌握了如何使用过滤器来减少服务器端通过 ...

  2. Java基础-字符串连接运算符String link operator

    Java基础-字符串连接运算符String link operator 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 字符串链接运算符是通过“+”进行拼接的. 一.使用“+”进行字 ...

  3. vue 混入的理解

  4. python---重点(设计模式)

    前戏:设计模式简介 设计模式是面向对象设计的解决方案,是复用性程序设计的经验总结.(与语言无关,任何语言都可以实现设计模式) 设计模式根据使用目的的不同而分为创建型模式(Creational Patt ...

  5. 安装解压版的mariadb

    今天尝试了安装解压版的mariadb,在官网上https://downloads.mariadb.org/下载了5.5版本的mariadb的zip压缩包, 经过实践发现mariadb解压版安装与mys ...

  6. Let Me Count The Ways(Kickstart Round H 2018)

    题目链接:https://code.google.com/codejam/contest/3324486/dashboard#s=p2 题目: 思路: 代码实现如下: #include <set ...

  7. 【译】第十篇 Replication:故障排除

    本篇文章是SQL Server Replication系列的第十篇,详细内容请参考原文. 复制故障排除是一项艰巨的任务.在任何复制设置中,都涉及到很多移动部件,而可用的工具并不总是很容易识别问题.Th ...

  8. 使用httpClient调用接口,参数用map封装或者使用JSON参数,并转换返回结果

    这里接口用表存起来,标记请求方式,然后接受参数,消息或者请求参数都可以, 然后先是遍历需要调用的接口,封装参数,再分别调用get与post即可,没有微服务还是得自己写 //消息转发-获取参数中对应参数 ...

  9. 洛谷 P3835: 【模板】可持久化平衡树

    题目传送门:洛谷P3835. 题意简述: 题面说的很清楚了. 题解: 考虑建立一棵每个节点都表示一个版本的树. 以初始版本 \(0\) 为根.对于第 \(i\) 个操作,从 \(v_i\) 向 \(i ...

  10. Java Dom对XML的解析和修改操作

    与Dom4J和JDom对XML的操作类似,JDK提供的JavaDom解析器用起来一样方便,在解析XML方面Java DOM甚至更甚前两者一筹!其不足之处在于对XML的增删改比较繁琐,特开篇介绍... ...