详解 字符转换流
(请观看本人博文——《详解 字符流》)
@
字符转换流
字符转换流 和本人之前在博文《详解 字节输出流 与 字节输入流》所讲解的知识点类似,总共分为两个部分 —— OutputStreamWriter(字符转换输出流) 和 InputStreamReader(字符转换输入流)
那么,现在,本人就来讲解下这两个类:
OutputStreamWriter:
(输出流)
本人先来介绍下InputStreamReader类:
定义:
OutputStreamWriter 是字符流通向字节流的桥梁:
可使用指定的 charset, 将要写入流中的字符编码成字节。
它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符集
构造方法:
- OutputStreamWriter(OutputStream out):
根据默认编码(GBK)把字节流的数据转换为字符流- OutputStreamWriter(OutputStream out,String charsetName):
根据指定编码把字节流数据转换为字符流- OutputStreamWriter(OutputStream out, Charset cs)
创建使用给定字符集的 OutputStreamWriter- OutputStreamWriter(OutputStream out, CharsetEncoder enc)
创建使用给定字符集编码器的 OutputStreamWriter
需要强调的一点是:
- 这个类只能用于操作文本文件
- 当我们所表示的文件不存在时,会自动帮我们创建一个相应的文件
- 这个类相当于包装了字节流的OutputStream类,所以若是我们想实现文本文件内容的追加,就要传递以参数append为true所构建出来的OutputStream对象
这个类的 常用API 也是write():
- public void write(int c)
写一个字符- public void write(char[] cbuf)
写一个字符数组- public void write(char[] cbuf,int off,int len)
写一个字符数组的 一部分- public void write(String str)
写一个字符串- public void write(String str,int off,int len)
写一个字符串的一部分
本人现在来讲解下这个类的write()方法的底层实现过程:
每次调用 write() 方法都会导致在给定字符(或字符集)上调用编码转换器。
在写入底层输出流之前,得到的这些字节将在缓冲区中累积。
可以指定此缓冲区的大小, 不过,默认的缓冲区对多数用途来说已足够大。
(注意:传递给 write() 方法的 字符 没有缓冲)
那么,本人来展示下这些API的使用:
package edu.youzg.about_io.about_file.core;
import java.io.*;
public class Test {
public static void main(String[] args) throws IOException {
OutputStreamWriter out = out=new OutputStreamWriter(new FileOutputStream("test.txt",true),"utf-8");
out.write('?'); //一次写一个字符
out.write("\r\n");
out.write("当我打出?");//一次写入一个字符串
out.write("\r\n");
out.write("不是我有问题啦啦啦啦阿联",0,5);//一次写入字符串的一部分
out.write("\r\n");
out.write(new char[]{'而','是'});//一次写入一个字符数组
out.write("\r\n");
out.write(new char[]{'c', '你', '有', '问', '题', '?', '!', 'a'},1,4);//一次写入一个字符数组的一部分
//释放资源
out.close();
}
}
本人现来展示下运行前的目录:
现在,本人展示下运行后的目录 以及 创建出来的文件的内容:
那么,现在,本人来讲下InputStreamReader类:
InputStreamReader:
(输入流)
本人先来介绍下InputStreamReader类:
定义:
InputStreamReader 是字节流通向字符流的桥梁:
它使用指定的 charset ,读取字节并将其解码为字符。
它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集
现在,本人来展示下这个类的构造方法:
构造方法:
- InputStreamReader(InputStream in)
创建一个使用默认字符集的 InputStreamReader- InputStreamReader(InputStream in, Charset cs)
创建使用给定字符集的 InputStreamReader- InputStreamReader(InputStream in, CharsetDecoder dec)
创建使用给定字符集解码器的 InputStreamReader- InputStreamReader(InputStream in, String charsetName)
创建使用指定字符集的 InputStreamReader
本人要强调的一点是:
构造InputStreamReader对象时,所关联的文件 如果不存在,就会报错
这个类的 常用API 也是read():
- public int read()
一次读取一个字符
返回值为该字符 的ASCII码值
如果没有读到 ,则返回-1- public int read(char[] cbuf)
一次读取一个字符数组
如果没有读到 ,则返回-1- public int read(char[] cbuf, int offset, int length)
将字符读入数组中的某一部分
如果没有读到 ,则返回-1
现在本人来讲解下此类read()方法的底层实现:
每次调用 InputStreamReader 中的一个 read() 方法都会导致从底层输入流读取一个或多个字节
(例:在UTF-8编码下,一个汉字占3个字节,当读取汉字字符时,就要读取3个字节)
那么,本人来展示下这些API的使用:
package edu.youzg.about_io.about_file.core;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class Test {
public static void main(String[] args) throws IOException {
FileReader in = new FileReader("test.txt");
int ch = in.read(); //一次读取一个字符
System.out.println(ch); //那个字符的ASCII码值
char[] chars = new char[3];//字符数组,充当缓冲区
int len = in.read(chars); //返回值,是实际读取到的字符个数
System.out.println(len);
String s = String.valueOf(chars);
System.out.println(s);
chars = new char[6];//字符数组,充当缓冲区
len = in.read(chars, 0, 3); //一次读取3个字符,装入缓冲区中
System.out.println(len);
s = String.valueOf(chars, 0, len);
System.out.println(s);
//释放资源
in.close();
}
}
那么,本人来展示下运行结果:
(换行符在utf-8编码下也算2个字符,即:"/r/n")
那么,现在,本人来利用这两个类,实现下文件的复制操作:
我们当然可以一个字节一个字符地读取并写入,但是在前面的知识点讲解中,我们发现,还是每次读入一个数组(充当 缓冲区),那样去完成复制操作,效率会更高,所以,本人就不展示如何一个字符一个字符地复制了
package edu.youzg.about_io.about_file.core;
import java.io.*;
public class Test {
public static void main(String[] args) throws IOException {
InputStreamReader in = new InputStreamReader(new FileInputStream("test.txt"));
OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream("copyView1.txt"));
char[] chars = new char[1000];
int len = 0;//读取到有效字符个数
while ((len=in.read(chars)) != -1){
out.write(chars,0,len);
out.flush();//字符流记得刷新一下
}
//释放资源
in.close();
out.close();
}
}
那么,现在本人来展示下 生成的文件的内容:
可以看出,本人的代码完成了文件的复制操作!
(本人《详解 字节流 与 字符流》博文链接:https:////www.cnblogs.com/codderYouzg/p/12418532.html)
(本人 I/O流总集篇 博文链接:https:////www.cnblogs.com/codderYouzg/p/12418404.html)