功能:
转换吗?转换流。InputStreamReader OutputStreamWriter
高效吗?缓冲区对象。BufferedXXX
unicode:国际标准码表:无论是什么文字,都用两个字节存储。
l Java中的char类型用的就是这个码表。char c = 'a';占两个字节。
l Java中的字符串是按照系统默认码表来解析的。简体中文版 字符串默认的码表是GBK。
UTF-8:基于unicode,一个字节就可以存储数据,不要用两个字节存储,而且这个码表更加的标准化,在每一个字节头加入了编码信息(后期到api中查找)。
能识别中文的码表:GBK、UTF-8;正因为识别中文码表不唯一,涉及到了编码解码问题。
对于我们开发而言;常见的编码 GBK UTF-8 ISO-8859-1
文字--->(数字) :编码。“abc”.getBytes() byte[]
(数字)--->文字 : 解码。 byte[] b={97,98,99} new String(b,0,len)
转化流
OutputStreamWriter 是字符流通向字节流的桥梁:可使用指定的字符编码表,将要写入流中的字符编码成字节,将字符串按照指定的编码表转成字节,在使用字节流将这些字节写出去
其实在OutputStreamWriter流中维护自己的缓冲区,当我们调用OutputStreamWriter对象的write方法时,会拿着字符到指定的码表中进行查询,把查到的字符编码值转成字节数存放到OutputStreamWriter缓冲区中。然后再调用刷新功能,或者关闭流,或者缓冲区存满后会把缓冲区中的字节数据使用字节流写到指定的文件中。
转换流_字节转字符流过程
InputStreamReader
InputStreamReader 是字节流通向字符流的桥梁
java.io.InputStreamReader 继承 Reader
字符输入流,明确读取文本文件
字节流向字符,将字节流转字符流
读取的方法:read() 读取1个字符,读取字符数组
技巧 :
(1)OuputStreamWriter书写文件
(2)InputStreamReader读取文件
OutputStreamWriter(OutputStream out)所有字节输出流
InputStreamReader(InputStream in) 接收所有的字节输入流
可以传递的字节输入流: FileInputStream
InputStreamReader(InputStream in,String charsetName) 传递编码表的名字
代码展示
字符流通向字节流
package com.oracle.demo01; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.UnsupportedEncodingException; public class demo01 { public static void main(String[] args) throws IOException{ //首先明确目的地 FileOutputStream fos=new FileOutputStream("D:\\demo0611\\gbk.txt",true);//加true开启续写功能 //然后进行转换----目的地,添加转换流指定码表 OutputStreamWriter osw= new OutputStreamWriter(fos,"gbk");//(目的地,码表) //写入字符串---谁调谁写 osw.write("你好"); //释放资源-- 谁开启关谁--或者黄色的警告的 osw.close(); } }
字节流通向字符流
package com.oracle.demo01; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; public class demo02 { public static void main(String[] args) throws IOException { // 明确数据源 FileInputStream fis= new FileInputStream("D:\\demo0611\\gbk.txt"); //添加转换流指定码表 InputStreamReader isr= new InputStreamReader(fis,"gbk"); //一个字符数组读 char[] ch=new char[1024]; int len=0; while((len=isr.read(ch))!=-1){ System.out.println(new String (ch,0,len)); } isr.close(); } }
1.1 转换流和子类区别
发现有如下继承关系:
OutputStreamWriter: utf-8 gbk
|--FileWriter: gbk
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
缓冲流
缓冲流概述
- 可提高IO流的读写速度
- 分为字节缓冲流与字符缓冲流
字节缓冲流
字节缓冲流根据流的方向,共有2个
l 写入数据到流中,字节缓冲输出流 BufferedOutputStream
l 读取流中的数据,字节缓冲输入流 BufferedInputStream
它们的内部都包含了一个缓冲区,通过缓冲区读写,就可以提高了IO流的读写速度
l 构造方法
public BufferedOutputStream(OutputStream out)创建一个新的缓冲输出流,以将数据写入指定的底层输出流。
字节缓冲方式
//创建基本的字节输出流
FileOutputStream fileOut = new FileOutputStream("abc.txt");
//使用高效的流,把基本的流进行封装,实现速度的提升
BufferedOutputStream out = new BufferedOutputStream(fileOut);
//1,创建缓冲流对象
FileInputStream fileIn = new FileInputStream("abc.txt");
//把基本的流包装成高效的流
BufferedInputStream in = new BufferedInputStream(fileIn);
字节与字符方式一杨演示字符:
字符四种缓冲方式
* 1,指定数据源, 是数据源中读数据,采用输入流
* 2,指定目的地,是把数据写入目的地,采用输出流
* 3,读数据
* 4,写数据
* 5,关闭流
package com.oracle.demo02; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; public class work { public static void main(String[] args) throws IOException { // get1(); // get2(); get3(); } // 单个个字符复制 时间: 5284 public static void get1() throws IOException { // 明确写入的目的地 FileWriter fw = new FileWriter("D:\\demo0611\\a\\dmc.txt"); // 明确数据源 FileReader fr = new FileReader("D:\\demo0611\\dm.txt"); int len = 0; long time = System.currentTimeMillis(); // 复制 while ((len = fr.read()) != -1) { fw.write(len); } long time2 = System.currentTimeMillis(); System.out.println(time2 - time); // 释放资源 fw.close(); fr.close(); } // 缓冲流单个字符复制 时间:4344 public static void get2() throws IOException { // 明确写入的目的地 FileWriter fw = new FileWriter("D:\\demo0611\\b\\dmc.txt"); // 明确数据源 FileReader fr = new FileReader("D:\\demo0611\\dm.txt"); // 加入缓冲流 BufferedWriter bw = new BufferedWriter(fw); BufferedReader br = new BufferedReader(fr); String lin = null; long yi = System.currentTimeMillis(); // 复制 while ((lin = br.readLine()) != null) { bw.write(lin); bw.flush(); } long ye = System.currentTimeMillis(); System.out.println(ye - yi); // 释放资源 br.close(); bw.close(); } // 字符数组复制 时间:1026 public static void get3() throws IOException { // 明确写入的目的地 FileWriter fw = new FileWriter("D:\\demo0611\\c\\dmc.txt"); // 明确数据源 FileReader fr = new FileReader("D:\\demo0611\\dm.txt"); // 数组 char[] ch = new char[1024]; // 复制 int le = 0; long t = System.currentTimeMillis(); while ((le = fr.read(ch)) != -1) { fw.write(ch, 0, le); } long t2 = System.currentTimeMillis(); System.out.println(t2 - t); // 释放资源 fw.close(); fr.close(); } // 缓冲流 字符数组 时间: 1056 public static void get4() throws IOException { // 明确写入的目的地 FileWriter fw = new FileWriter("D:\\demo0611\\d\\dmc.txt"); // 明确数据源 FileReader fr = new FileReader("D:\\demo0611\\dm.txt"); //缓冲 BufferedReader br=new BufferedReader(fr); BufferedWriter bw= new BufferedWriter(fw); //数组 long tt=System.currentTimeMillis(); char[] ch=new char[1024]; int ss=0; while((ss=br.read())!=-1){ bw.write(ch,0,ss); bw.flush(); } long tt2=System.currentTimeMillis(); System.out.println(tt2-tt); //释放资源 bw.close(); br.close(); } }
字符输出流缓冲流BufferedWriter特有方法newLine
a、方法介绍:void newLine() 写换行
- newLine()文本中换行, \r\n也是文本换行
特点
- 获取内容的方法一般都有返回值
- int 没有返回的都是负数
- 引用类型 找不到返回null
- boolean 找不到返回false
package com.oracle.demo02; import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; public class demo02 { public static void main(String[] args) throws IOException { //明确目的地 FileWriter fw= new FileWriter("D:\\demo0611\\e.txt"); //添加缓冲流 BufferedWriter bw= new BufferedWriter(fw); //写入字符串 bw.write("你好,窝窝头"); bw.flush(); //换行 bw.newLine(); bw.write("一块钱四个"); bw.flush(); //换行 bw.newLine(); //释放资源 bw.close(); } }
public static void main(String[] args) throws IOException { //明确数据源 FileReader fr= new FileReader("D:\\demo0611\\e.txt"); //添加缓冲流 BufferedReader br = new BufferedReader(fr); //开始复制 String line=null; while((line=br.readLine())!=null){ System.out.println(line); } // 释放资源 br.close(); }
流的操作规律
IO流中对象很多,解决问题(处理设备上的数据时)到底该用哪个对象呢?
把IO流进行了规律的总结(四个明确):
l 明确一:要操作的数据是数据源还是数据目的。
源:InputStream Reader
目的:OutputStream Writer
先根据需求明确要读,还是要写。
l 明确二:要操作的数据是字节还是文本呢?
源:
字节:InputStream
文本:Reader
目的:
字节:OutputStream
文本:Writer
已经明确到了具体的体系上。
l 明确三:明确数据所在的具体设备。
源设备:
硬盘:文件 File开头。
内存:数组,字符串。
键盘:System.in;
网络:Socket
目的设备:
硬盘:文件 File开头。
内存:数组,字符串。
屏幕:System.out
网络:Socket
完全可以明确具体要使用哪个流对象。
l 明确四:是否需要额外功能呢?
额外功能:
转换吗?转换流。InputStreamReader OutputStreamWriter
高效吗?缓冲区对象。BufferedXXX
InputStream
FileInputStream
BufferedInputStream
OuputStream
FileOutputStream
BufferedOuputStream
Writer
OutputStreamWriter
FileWriter
BufferedWriter
Reader
InputStreamReader
FileReader
BufferedReader