IO流——字节流
基本操作与字符流类相同。
但它仅可以操作字符,还可以操作其他媒体文件
字符流的缓冲区是字符数组,字节流的缓冲区是字节数组
例程:
利用字节流输入输出文件。
public void writeObj() { //1.创建字节流对象,用于操作文件 FileOutputStream fos=new FileOutputStream("bytedeom.txt"); //写数据,不需要缓冲,直接写入目的地。 fos.flush(); //无意义 缓冲区对象中是有意义的。 fos.close(); //关闭资源对象。有意义 } public void readObj() { //1.创建一个读取流对象,和指定文件关联 FileInputStream fis=new FileInputStream("bytedeom.txt"); //一次读入一个字节 int ch=0; while((ch=fis.read())!=-1) { System.out.println((char)ch); } }
FileInputStream对象的available()方法可以获取取输入文件的字节数大小。
public static void main(String [] args) throws IOException { copy_1(); copy_2(); copy_3(); } public void copy_1() throws IOException { FileInputStream fis=new FileInputStream("c:\\0.mp3"); FileOutputStream fos=new FileOutputStream("C:\\1.mp3"); byte[] buf=new byte[1024]; int len=0; while ((len=fis.read(buf))!=-1) { fos.write(buf,0,len); } fos.close(); fis.close(); } public void copy_2() throws IOException { FileInputStream fis=new FileInputStream("c:\\0.mp3"); BufferedInputStream bufis=new BufferedInputStream(fis); FileOutputStream fos=new FileOutputStream("C:\\1.mp3"); BufferedOutputStream bufos=new BufferedOutputStream(fos); int ch=0; while ((ch=bufis.read()!=-1) { bufos.write(ch); bufos.flush(); } bufos.close(); bufis.close(); } public void copy_3() throws IOException //缓冲数组可能太大 { FileInputStream fis=new FileInputStream("c:\\0.mp3"); FileOutputStream fos=new FileOutputStream("C:\\1.mp3"); byte[] buf=new byte[fis.available()]; int len=0; while ((len=fis.read(buf))!=-1) { fos.write(buf,0,len); } fos.close(); fis.close(); } public void copy_4() throws IOException //非常慢 { FileInputStream fis=new FileInputStream("c:\\0.mp3"); FileOutputStream fos=new FileOutputStream("C:\\1.mp3"); int ch=0; while ((ch=fis.read())!=-1) { fos.write(ch); } fos.close(); fis.close(); }
用字符流读图片文件,行吗?不行,因为字符流是按字符数据读图片文件,然后查编码表,读图片文件有可能查不到编码表内容。
读入一个键盘录入的数据,并打印在控制台上。
键盘本身就是一个标准的输入设备,对于java而言,对于这种输入设备都有对应的对象。
public static void readKey() throws IOExcepton { InputStream in=System.in;//键盘输入是字节流 int ch=0; while((ch=in.read())!=-1) { System.out.println(ch); } //in流不能关,一关键盘就无法输入,系统流是不需要关的。 }
public static void readKey2() throws IOException { /* *获取键盘录入的数据 *并将数据变成大写,显示在控制台上 *如果用户输入的是over,结束键盘录入 */ StringBuilder sb=new StringBuilder(); InputStream in=System.in; int ch=0; while((ch=in.read())!=-1) { if (ch==13) continue; if (ch==10) { String tmp=sb.toString(); if (tmp.equals("over")) break; System.out.println(tmp.toUpperCase()); sb.delete(0.sb.length()); } else { sb.add((char)ch); } } }
字节流转字符流实例
public static void exam() { //字节流 InputStream in=system.in; //InputStreamReader是字节流通向字符流的桥梁,它用指定的编码表为字节解码 InputStreamReader isr=new InputStreamReader(in); //字符流 BufferedReader bufr=new BufferedReader(isr); String line=null; while((line=bufr.readLine())!=null) { if ("over".equals(line)) break; System.out.println(line.toUpperCase()); } }
字符流通向字节流的桥梁是OutputStreamWriter,FileWriter是操作文本文件的类,它的父类就是OutperStreamWriter类的子类。
public static void exam() { //字节流 InputStream in=system.in; //InputStreamReader是字节流通向字符流的桥梁,它用指定的编码表为字节解码 InputStreamReader isr=new InputStreamReader(in); //字符流 BufferedReader bufr=new BufferedReader(isr);
//以上三句可简化为: BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in)); //字节流 OutputStream out=System.out; OutputStreamWriter osw=new OutputStreamWriter(out); BufferedWriter bufw=new BufferedWriter(osw);
//以上三句可简化为:BufferedWriter bufw=new BufferedWriter(new OutputStreamWriter(System.out)); String line=null; while((line=bufr.readLine())!=null) { if ("over".equals(line)) break; // bufw.write(line.toUpperCase()+"\r\n"); //字符转字节,并输出。 //osw.flush(); bufw.write(line.toUpperCase()); bufw.newLine(); bufw.flush(); } }
分析如下:
转换流:
InputStreamReader:字节到字符的桥梁,解码
OutputStreamWriter:字符到字节的桥梁,编码
流的操作规律:
想要知道开发时用到哪些对象,只要通过四个明确即可:
1.明确源和目的:汇
源:InputStream、Reader
目的:OutputStream 、Writer
2.明确数据是否是纯文本数据
源:是,Reader;否,InputStream
目的:是,Writer;否,OutputStream
3.明确具体的设备
源设备:
硬盘:File
键盘:System.in
内存:数组
网络:Socket流
目的设备:
硬盘:File
控制台:System.out
内存:数组
网络:Socket流
4.是否需要其他额外功能
(1)是否需要高效(缓冲区)
是,就加上Buffer。
BufferedReader bufr=new BufferedReader(new FileReader("a.txt"));
BufferedWriter bufw=new BufferedWriter(new FileWriter("b.txt"));
将一个中文字符串按照指定的编码表写入到一个文本文件中。
public static void writeText_1() { //FileWriter只能用默认码表,不能指定 //FileWriter其实就是转换流指定了本机默认码表的体现。 FileWriter w=new FileWriter("gbk_1.txt"); //字符串默认的是本地默认码表,中文平台一般为GBK //java默认码表为Unicode码表,一个字符2个字符 //后扩展为utf-8,字符可能1个字节,2个字符,3个字节 fw.write("你好");//默认GBK fw.close(); } public static void writeText_2() { //OutputStreamWriter是FileWriter的父类,它可以指定码表 OutputStreamWriter osw=new OutputStreamWriter(new FileOuptStream("gbk_2.txt"),"GBK");//码表名称不分大小写 osw.write("你好"); osw.close(); }
同理,读取文本文件时也要指定相应的码表。
可以看出,能指定编码表,也是转换流的一个重要的功能。
什么时候使用转换流呢?
1. 源或目的对应的设备是字节流,但是操作的却是文本数据,可以使用转换流作为桥梁。
2.一旦操作文本涉及到具体的指定编码表时,必须使用转换流。