字符流
一、字符流产生的原因
- 在某些情况下,用字节流来操作中不太方便,因为有些字符,需要多个字节数据来表示,而字节流数据的单位是单字节。
- 在字节流中,就可能出现不完整的字符表示,其根本原因是 —— 数据逻辑单位不一致。
二、字符的表示
-
字符在计算机中,是以二进制数据的形式存储,即字符在旧手机中对应的是一个二进制的整数
-
字符集(编码表),由字符及其对应的数值组成的一张表,即字符所对应的二进制数值,是由字符集(编码表)规定的
-
常见字符集:ASCII码、ISO8859-1、GB2312、GBK、GB18030、BIG-5码、Unicode等等
-
编解码:
- 编码:将字符转化为对应的二进制整数值(基于指定的字符集)
- 解码:将整数值转化为对应的字符(基于指定字符集)
- 编解码使用的是同一个字符集,否则可能出现乱码问题
对应Java的编解码操作:
- 编码:字符串对象.getBytes(“指定字符集或编解码表的名称”),当没有指定字符集的时候,在IDEA中默认使用UTF-8,如果没有使用IDEA,则原生的默认字符集是GBK
- 解码:String(byte[], String charsetName)、String(byte[], int offset, int len, String charsetName),当没有指定所用编解码或字符集的时候在IDEA中默认使用UTF-8,如果没有使用IDEA,则原生的默认字符集是GBK
-
乱码问题产生的根本原因是:编解码使用的字符集不一致
三、字符流的实质
- 字符流 = 字节流 + 编解码(根据指定编码表,编解码的过程)
- 字符的存储和传输天然于二进制数据密切相关
- 字符流需要在二进制的基础上,添加基于特定编码表的字符编解码
- 字符输入流:解码 + 字节流
- 字符输出流:编码 + 字节流
四、字符流体系
-
字符流的基类:Writer、Reader(都是抽象类)
-
输入流(Writer)
具体子类:
- OutputStreamWriter
public OutputStreamWriter (OutputStream out),创建使用默认字符编码的OutputStreamWriter。
public OutputStreamWriter(OutputStream out, String charsetName),创建使用给定字符集的OutputStreamWriter。
- FileWriter
用来写入字符文件的便捷类
public FileWriter(String fileName),创建使用默认字符集的字符输出流,专门向文件中写入字符数据
public FileWriter(File file)
public FIleWriter(String fileName, boolean append),改构造方法用来实现简化流的文件的追加写入
- BufferedWriter
BufferedWriter(Writer out),创建一个使用默认大小输出缓冲区的缓冲字符输出流。
BufferedWriter(Writer out, int sz),创建一个使用给定大小输出缓冲区的新缓冲字符输出流
特有的方法:void newLine() 向流中写入换行符
write()方法:
> void write(char[] cbuf) 写入字符数组。
void write(char[] cbuf, int off, int len) 写入字符数组的某一部分。
void write(int c) 写入单个字符。 要写入的字符包含在给定整数值的 16 个低位中,16 高位被忽略
void write(String str) 写入字符串。
void write(String str, int off, int len)写入字符串的某一部分。
-
输入流(Reader)
具体子类:
- InputStreamReader
public InputStreamReader(InputStream in),创建一个使用 默认字符集 的 InputStreamReader。
public InputStreamReader(InputStream in,String charsetName),创建使用指定字符集的 InputStreamReader。
- FileReader
用来读取字符文件的便捷类
public FileReader(String fileName)
创建使用默认字符集的字符输入流,从指定文件中读取字符数据public FileReader(File file)
- BufferedReader
BufferedReader(Reader in) 创建一个使用默认大小输入缓冲区的缓冲字符输入流。
BufferedReader(Reader in, int sz) 创建一个使用指定大小输入缓冲区的缓冲字符输入流。
特有方法: String readLine() 读取一行文本数据(不包括该行的换行符)
read()方法
int read() ----- 读取单个字符。如果已到达流的末尾,则返回 -1
int read(char[] cbuf) -------- 将字符读入数组。读取的字符数,如果已到达流的末尾,则返回 -1
int read(char[] cbuf, int off, int len) -------- 将字符读入数组的某一部分。
-
字符流是不可以用来传输图片、视频数据
a. 图片和视频 图片文件数据和视频文件数据,都有自己的编码方式,而这种编码方式和
字符编码,没有任何关系b. 所以,在图片和视频的编码数据中,就会存在一些,字符集中不存在的编码值
此时在读入,视频和图片数据的时候,就会遇到一些在字符集中,找不到编码值
c. 于是在转化的时候,如果遇到不认识的编码值,要么直接丢弃,
要么就用一个固定的???来表示未知编码值所对应的字符,这也就意味着, 视频和图片数据,已经被改变了
字节流:Click me!