Reader 简单介绍前面说了什么是字节流,今天来看什么是字符流。
字节流与字符流操作的本质区别只有一个:字节流是原生的操作,而字符流是经过处理后的操作。在进行网络数据传输、磁盘数据保存所保存所支持的数据类型只有:字节。
但是无论是字节流还是字符流,所有的基本操作都是一样的,都是基本的步骤,所有学习的方式也是一样的。
1.根据字节流或字符流的子类实例化父类对象 ;
2.进行数据的读取或写入操作
3.关闭流(close())
这里正式来学习
字符流的父类
InputStreamReader:字符输入流
InputStreamReader(inputStream in)
创建一个使用默认字符集的InputStreamReader
InputStreamReader(InputStream in, String charsetName)
创建了一个使用命名字符集的InputStreamReader。
InputStreamReader
构造方法
概念
1)使用默认的字符集构造InputStreamReader 流:本质是初始化其实例域的一个变量,并未看到 任何关于字符集的设置。
public InputStreamReader(InputStream in) {
super(in);
try {
sd = StreamDecoder.forInputStreamReader(in, this, (String)null);
} catch (UnsupportedEncodingException e) {
throw new Error(e);
}
}
2)使用指定的字符集名称构造InputStreamReader流:本质是初始化其实例 域的一个变量,可以发现字符集是初始化方法的第 三个参数
public InputStreamReader(InputStream in, String charsetName)
throws UnsupportedEncodingException
{
super(in);
if (charsetName == null)
throw new NullPointerException("charsetName");
sd = StreamDecoder.forInputStreamReader(in, this, charsetName);
}
小练习
public class InputStreamReaderDemo1 {
public static void main(String[] args) throws IOException {
//创建字符输入流
// InputStreamReader isr = new InputStreamReader(new FileInputStream("b4.txt"));
InputStreamReader isr = new InputStreamReader(new FileInputStream("b4.txt"),"UTF-8");
//读取数据
//int read()
//读一个字符
// System.out.println((char) isr.read());
int b =0;
while ((b=isr.read())!=-1){
System.out.print((char)b);
}
//释放资源
isr.close();
}
}
方法
这里只看两种方法
InputStreamReader读取数据的方法:
public int read():一次读取一个字符
public int read(char[] cbuf):一次读取一个字符数组
public class InputStreamReaderDemo2{
public static void main(String[] args){
//创建字符输入流的对象
InputStreamReader isr = new InputStreamReader(new FileInputStream("b4.txt"),"UTF-8")
}
int c = 0;
while((c = isr.read())!=-1){
System.out.println((char)c);
}
//public int read(char[] cbuf):一次读取一个字符数组
char[] chars = new char[1024];
int length = 0;
while ((length = isr.read())!=-1){
System.out.println(length);
System.out.println(new String(chars, 0, length));
}
//释放资源
isr.close();
}
writer
Writer:(java提供操作字符流的父类)
OutputStreamWriter 字符输出流(字符转换流)
OutputStreamWriter(OutputStream out)
创建一个使用默认字符编码的OutputStreamWriter。
OutputStreamWriter(OutputStream out, String charsetName)
创建一个使用命名字符集的OutputStreamWriter。
OutputStreamWriter
OutputStreamWriter流构造函数
概念
1)利用输出流构建默认字符编码的OutputStreamWriter流:本质是初始化StreamEncoder对象
private final StreamEncoder se;
public OutputStreamWriter(OutputStream out) {
super(out);
try {
se = StreamEncoder.forOutputStreamWriter(out, this, (String)null);
} catch (UnsupportedEncodingException e) {
throw new Error(e);
}
}
2)通过指定的字符编码构建OutputStreamWriter流:本质是初始化StreamEncoder对象但是指定了字符编码
public OutputStreamWriter(OutputStream out, String charsetName)
throws UnsupportedEncodingException
{
super(out);
if (charsetName == null)
throw new NullPointerException("charsetName");
se = StreamEncoder.forOutputStreamWriter(out, this, charsetName);
}
小练习
public class OutputStreamWriterDemo {
public static void main(String[] args) throws IOException {
//创建字符流输出对象
//如果目标文件不存在,会自动创建
// OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("b2.txt"));
//OutputStreamWriter(OutputStream out, String charsetName)
//创建一个使用命名字符集的OutputStreamWriter。
OutputStreamWriter osw2 = new OutputStreamWriter(new FileOutputStream("b3.txt"), "GBK");
//往文件中写入数据
// osw.write("我爱中国");
osw2.write("我爱家乡");
//释放资源
// osw.close();
osw2.close();
}
}
方法
OutputStreamWriter写数据的5个方法:
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)
public class OutputStreamWriterDemo2 {
public static void main(String[] args) throws IOException {
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("b4.txt"));
//写数据
//public void write(int c)
osw.write(99);
osw.flush();
//public void write(char[] cbuf)
//一次写一个字符数组
char[] chars = {'a','b','c','d','e'};
osw.write(chars);
osw.flush();
//public void write(char[] cbuf,int index,int length)
//一次写入字符数组的一部分
osw.write(chars, 1, 3);
osw.flush();
//public void write(String str)
//一次写入一个字符串
osw.write("刘生发真帅!");
osw.flush();
//public void write(String str,int off,int len)
//一次写入字符串的一部分
osw.write("刘生发真帅!",0,3);
osw.flush();
//释放资源
osw.close();
}
}
案例
把当前项目目录下的a.txt内容复制到当前项目目录下的b.txt中
数据源:
a.txt -- 读取数据 -- 字符输入流(字符转换流) -- InputStreamReader
目的地:
b.txt -- 写出数据 -- 字符输出流(字符转换流) -- OutputStreamWriter
public class FileCopyDemo3 {
public static void main(String[] args) throws IOException {
//创建字符输入流对象
InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"));
//创建字符输出流对象
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("b.txt"));
//读写数据
// //一次读写一个字符
// int c = 0;
// while ((c = isr.read()) != -1) {
// osw.write(c);
// osw.flush();
// }
//一次读写一个字符数组
char[] chars = new char[1024];
int length = 0;
while ((length = isr.read(chars)) != -1) {
osw.write(chars, 0, length);
osw.flush();
}
//释放资源
osw.close();
isr.close();
}
}
转换流
字符流(转换流) = 字节流 + 编码表
加密:把能看懂转成看不懂的(编码)
String -- byte[]
解密:把看不懂的转成能看懂的(解码)
byte[] -- String
编码的格式于解码的格式要一致,否则解码出来的内容你可能看不懂
import java.nio.charset.Charset;
import java.util.Arrays;
public class ZhuanHuanliuDemo {
public static void main(String[] args) throws Exception {
//查看当前的编码格式
System.out.println(Charset.defaultCharset());
//加密:把能看懂转成看不懂的(编码)
// String -- byte[]
String s = "kayleigh真帅!";
//byte[] getBytes(Charset charset)
//使用给定的charset将该String编码为字节序列,将结果存储到新的字节数组中。
// byte[] b1 = s.getBytes("UTF-8");
// System.out.println(Arrays.toString(b1));
byte[] b1 = s.getBytes("Unicode");
System.out.println(Arrays.toString(b1));
//解密:把看不懂的转成能看懂的(解码)
//byte[] -- String
//String(byte[] bytes, Charset charset)
//构造一个新的String由指定用指定的字节的数组解码charset 。
// String s1 = new String(b1,"UTF-8");
String s1 = new String(b1,"Unicode");
//Unicode两个字节组成一个中文字符
System.out.println(s1);
}
}
缓冲区类(高效类)
字符缓冲输出流
字节缓冲输出流:
BufferedOutputStream
字节缓冲输入流:
BufferedInputStream
问题:
我们在使用字节流读取中文的时候,一个一个字节的读取,发现强转之后,出现了我们看不懂的字符
public class BufferedOutputStreamDemo1 {
public static void main(String[] args) throws IOException {
//BufferedOutputStream(OutputStream out)
//创建一个新的缓冲输出流,以将数据写入指定的底层输出流。
// FileOutputStream fos = new FileOutputStream("b1.txt");
// BufferedOutputStream bos = new BufferedOutputStream(fos);
//开发中推荐该方式创建
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("b1.txt"));
//往文件中写入数据
//void write(byte[] b)
bos.write("大数据,yyds;朱佳乐真帅!".getBytes());
bos.flush();
//释放资源
//关闭的时候,关闭之前也对缓冲区进行了一次刷新
//关闭之后bos不能用了
bos.close();
// bos.write("数加科技".getBytes());
// //IOException: Stream Closed
// bos.flush();
}
}
字符缓冲输入流
BufferedReader:字符缓冲输入流
BufferedReader(Reader in)
创建使用默认大小的输入缓冲区的缓冲字符输入流。
public class BufferedReaderDemo1 {
public static void main(String[] args) throws IOException {
//创建字符缓冲输入流对象
// BufferedReader br = new BufferedReader(
// new InputStreamReader(
// new FileInputStream("a.txt")));
//简化写法
BufferedReader br = new BufferedReader(new FileReader("a.txt"));
//第一种:一次只读一个字符
// int c = 0;
// while ((c = br.read()) != -1) {
// System.out.print((char) c);
// }
//第二种:一次读取一个字符数组
char[] chars = new char[1024];
int length = 0;
while ((length=br.read(chars))!=-1){
System.out.println(new String(chars,0,length));
}
//释放资源
br.close();
}
}
字符流为了高效读写,也提供了相对应的字符缓冲流 BufferedWriter:字符缓冲输出流 BufferedReader:字符缓冲输入流 BufferedWriter:字符缓冲输出流、 将文本写入字符输出流,缓冲字符,以提供单个字符,数组和字符串的高效写入。 可以指定缓冲区大小,或者可以接受默认大小。 默认值足够大,可用于大多数用途
public class BufferedWriterDemo1 {
public static void main(String[] args) throws IOException {
//创建字符缓冲输出流
//BufferedWriter(Writer out)
//创建使用默认大小的输出缓冲区的缓冲字符输出流。
// BufferedWriter bw = new BufferedWriter(
// new OutputStreamWriter(
// new FileOutputStream("b5.txt")));
//简化写法
BufferedWriter bw = new BufferedWriter(new FileWriter("b5.txt"));
//写数据
bw.write("hello");
bw.write("rn");
bw.write("world");
bw.write("rn");
bw.write("java");
bw.write("rn");
bw.write("hadoop");
bw.flush();
//释放资源
bw.close();
}
}
字符缓冲流的特殊方法:
BufferedWriter:
public void newline()
throws IOException写一行行分隔符。
行分隔符字符串由系统属性line.separator定义,
并不一定是单个换行符(' n')字符。
BufferedReader:
public String readLine()
throws IOException读一行文字。
一行被视为由换行符(' n'),回车符(' r')中的任何一个或随后的换行符终止。
public class BufferedWriterDemo2 {
public static void main(String[] args) {
// write();
read();
}
public static void read(){
//创建字符缓冲输入流
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader("b6.txt"));
// String s = br.readLine();
// System.out.println(s);
//
// String s1 = br.readLine();
// System.out.println(s1);
//
// String s2 = br.readLine();
// System.out.println(s2);
//用循环改进读取数据,因为我们不知道一个文件到底有多少行,我们用while循环
//如果已达到流的末尾,则为null
String line = null;
while ((line=br.readLine())!=null){
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void write() {
//创建字符缓冲输出流
BufferedWriter bw = null;
try {
bw = new BufferedWriter(new FileWriter("b6.txt"));
//往文件中写入数据
for (int i = 0; i < 10; i++) {
bw.write("大数据" + i);
// bw.write("rn");
bw.newline();
bw.flush();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
简化写法
由于我们正常做字符流的处理的时候,一般都不会去刻意传入编码,用的都是默认的编码
基本数不会去指定。
而通过学习完转换流之后,发现,名字有点长,所以Java就提供了子类给我们使用
字符流 = 字节流 + 编码表
OutputStreamWriter = FileOutputStream + 编码表(Unicode)
InputStreamReader = FileInputStream + 编码表(Unicode)
字符转换流的简化写法:
字符输出流:
FileWriter
字符输入流:
FileReader
复制文件
public class FileCopyDemo5 {
public static void main(String[] args) throws IOException {
//创建字符输入流对象
// InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"));
//创建简化后的字符输入流对象
FileReader fr = new FileReader("a.txt");
//创建简化后的字符输出流对象
FileWriter fw = new FileWriter("c1.txt");
//第一种方式:一次读写一个字符
// int c = 0;
// while ((c=fr.read())!=-1){
// fw.write(c);
// fw.flush();
// }
//第二种方式:一次读写一个字符数组
char[] chars = new char[1024];
int length = 0;
while ((length=fr.read(chars))!=-1){
fw.write(chars, 0, length);
fw.flush();
}
//释放资源
fw.close();
fr.close();
}
}
案例
使用高效字符流复制文件
public class FileCopyDemo7 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("b.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("ceshi2.txt"));
long start = System.currentTimeMillis();
//一次读取一个字符数组
char[] chars = new char[1024];
int length = 0;
while ((length = br.read(chars)) != -1) {
bw.write(chars, 0, length);
bw.flush();
}
long end = System.currentTimeMillis();
System.out.println("总耗费时间:" + (end - start));
//释放资源
bw.close();
br.close();
}
}
字符缓冲流特殊功能复制文件:
数据源:
a.txt -- 读取数据 -- 字符输入流 -- InputStreamReader -- FileReader -- BufferedReader
目的地:
b7.txt -- 写出数据 -- 字符输出流 -- OutputStreamWriter -- FileWriter -- BufferedWriter
public class FileCopyDemo8 {
public static void main(String[] args) throws IOException {
//创建字符缓冲输入流对象
BufferedReader br = new BufferedReader(new FileReader("a.txt"));
//创建字符缓冲输出流对象
BufferedWriter bw = new BufferedWriter(new FileWriter("b7.txt"));
String line = null;
while ((line=br.readLine())!=null){
bw.write(line);
bw.newline();
bw.flush();
}
//释放资源
bw.close();
br.close();
}
}



