Java I/O流总结(二)
来源:互联网 发布:cad of mac中文破解版 编辑:程序博客网 时间:2024/03/29 09:48
/*@author StormWangxhu@date 2017/11/1*/
面对压力,我可以挑灯夜战,不眠不休。面对挑战,我愿意迎难而上,永不退缩!
昨天我们总结了字符的输入流,主要进行读写的功能。今天来看一下字节流InputStream和OutputStream.
字节流基本框架体系图
整体体系:
InputStream:
基本概念
和字符流一样,字节流也有两个抽象基类作为其他类的父类。一个是InputStream,一个是OutPutStream.其他的类都是这两个类的拓展类。
(1)特点:
字节流可以操作任何数据。
(2)注意:
字节流使用的是字节数组 byte[]
字符流使用得是字符数组 char[]
- inputStream
(1)、inputStream是所有字节输入流的父类,是一个抽象类。
(2)ByteArrayInputStream、StringBufferInputStream、FileInputStream 是三种基本的介质流,它们分别从Byte 数组、StringBuffer、和本地文件中读取数据。
(3)ObjectInputStream 和所有FilterInputStream 的子类都是装饰流(装饰器模式的主角)。 - outputStream
(1)、OutputStream 是所有的输出字节流的父类,它是一个抽象类。
(2)、B
yteArrayOutputStream、FileOutputStream 是两种基本的介质流,它们分别向Byte 数组、和本地文件中写入数据。PipedOutputStream 是向与其它线程共用的管道中写入数据。
(3)、ObjectOutputStream 和所有FilterOutputStream 的子类都是装饰流。 - 其他
(1)、LineNumberInputStream 主要完成从流中读取数据时,会得到相应的行号,至于什么时候分行、在哪里分行是由改类主动确定的,并不是在原始中有这样一个行号。在输出部分没有对应的部 分,我们完全可以自己建立一个LineNumberOutputStream,在最初写入时会有一个基准的行号,以后每次遇到换行时会在下一行添加一个行 号,看起来也是可以的。好像更不入流了。
(2)、PushbackInputStream 的功能是查看最后一个字节,不满意就放入缓冲区。主要用在编译器的语法、词法分析部分。输出部分的BufferedOutputStream 几乎实现相近的功能。
StringBufferInputStream 已经被Deprecated,本身就不应该出现在InputStream 部分,主要因为String 应该属于字符流的范围。已经被废弃了,当然输出部分也没有必要需要它了!还允许它存在只是为了保持版本的向下兼容而已。
(3)、SequenceInputStream 可以认为是一个工具类,将两个或者多个输入流当成一个输入流依次读取。完全可以从IO 包中去除,还完全不影响IO 包的结构,却让其更“纯洁”――纯洁的Decorator 模式。
(4)、PrintStream 也可以认为是一个辅助工具。主要可以向其他输出流,或者FileInputStream 写入数据,本身内部实现还是带缓冲的。本质上是对其它流的综合运用的一个工具而已。一样可以踢出IO 包!System.out 和System.out 就是PrintStream 的实例!
下面我们通过案例来分别讲解一下这些字节流的使用。首先讲解一下FileInputStream:
案例一:利用字节流读取或写入文本内容到控制台或者文本文件中
package com.StormWang.InputStream;import java.io.FileInputStream;import java.io.FileWriter;import java.io.IOException;/*** @author StormWangxhu* @version 创建时间:2017年11月1日 上午11:19:03**/ class FileInStream{ //读文件,一个一个的读,读一个存一个 public static void readFile_1(){ //先写一个文件 FileWriter fileWriter = null ; FileInputStream fileInputStream = null ; try { fileWriter = new FileWriter("input.txt"); fileWriter.write("FileInputStream,success."); fileWriter.flush(); fileInputStream = new FileInputStream("input.txt"); int ch = 0 ; while ((ch= fileInputStream.read())!=-1) { System.out.print((char)ch); } } catch (Exception e) { // TODO: handle exception e.printStackTrace(); }finally { if (fileInputStream != null) { try { fileInputStream.close(); } catch (Exception e2) { // TODO: handle exception e2.printStackTrace(); } } if (fileWriter != null) { try { fileWriter.close(); } catch (Exception e2) { // TODO: handle exception e2.printStackTrace(); } } } } /* //读方法二(读完之后,一起存起来。) public static void readFile_2() { FileInputStream fileInputStream = null ; try { fileInputStream = new FileInputStream("E:\\eclipse-workspace\\day1101\\input.txt"); byte[] buf = new byte[1024]; int len = 0 ; while ((len = fileInputStream.read()) != -1) { System.out.println("len是:"+len); //System.out.print(new String(buf,0,len)); System.out.println(buf); } System.out.println("buf数组内容:"+buf); } catch (IOException e) { e.printStackTrace(); }finally { if (fileInputStream != null) { try { fileInputStream.close(); } catch (Exception e2) { // TODO: handle exception System.out.println("close:"+e2.toString()); } } } }*/ }public class FileInputStreamDemo { public static void main(String[] args) { FileInStream fileInStream = new FileInStream() ; fileInStream.readFile_1(); }}
我们来看一下结果:
再来看一个实例:实现对一个图片文件的复制
案例二:
package com.StormWang.InputStream;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;/*** @author StormWangxhu* @version 创建时间:2017年11月1日 下午4:53:32**/public class CopyPicture { /* * 实现功能: 实现图片文件的复制 * 思路: * 1、字节输入流和图片文件相关联 * 2、再用字节输入流将图片文件数据写入到缓冲区中,即字节数组中 * 3、通过循环读写,完成数据的存储 * 4、关闭流资源。 * */ public static void main(String[] args) { // TODO Auto-generated method stub FileInputStream fileInputStream = null; FileOutputStream fileOutputStream =null ; try { fileInputStream = new FileInputStream("F:\\2016\\1.jpg"); //测试代码 System.out.println("已过!"); fileOutputStream = new FileOutputStream("F:\\2.JPG"); byte[] buff = new byte[1024]; int ch = 0 ; //此处的read()方法可能会抛出IOException异常,我们catch一下。 while ((ch= fileInputStream.read(buff)) !=-1) { /* *write方法说明: *write(byte[] b, int off, int len) * 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此文件输出流。 * * */ fileOutputStream.write(buff, 0, ch); } } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally { if (fileInputStream != null) { try { fileInputStream.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if (fileOutputStream != null) { try { fileOutputStream.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }}
问题:在输入流和图片文件关联时,系统找不到指定文件。
F盘文件如下所示,不知道为什么会找不到文件呢?待解决:。。。。。。。
自定义缓冲字节流
package com.StormWang.InputStream;/*** @author StormWangxhu* @version 创建时间:2017年11月1日 下午6:44:40**/import java.io.IOException;import java.io.InputStream;public class MyBuffereedInputStream { private InputStream iStream ; private byte[] buff = new byte[1024]; private int pos = 0,count = 0 ; public MyBuffereedInputStream(InputStream iStream) { // TODO Auto-generated constructor stub this.iStream = iStream ; } public int myRead() throws IOException{ //通过iStream读取硬盘中的数据,存储到buff //如果count=0,说明byte数组是空的,所以开始读取数据 if (count == 0) { count = iStream.read(buff); //标记位 pos = 0; //通过下标找到数组 byte bt = buff[pos]; //byte数组个数递减 count--; //移动标记位 pos++; return bt&255; } //如果字节数组中还有数据,则继续往出取 else if (count>0) { byte bt = buff[pos]; count--; pos++; return bt & 255 ; } return -1 ; } //关闭流方法 public void myClose() { try { iStream.close(); } catch (IOException e) { e.printStackTrace(); } }}
这样就完成了自定义字节流的定义。下面我们来应用一下:
package com.StormWang.InputStream;import java.io.BufferedOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.OutputStream;/*** @author StormWangxhu* @version 创建时间:2017年11月1日 下午7:08:36**/public class myBufferedInputStreamTest { public static void main(String[] args) { // TODO Auto-generated method stub FileInputStream fInStream = null; MyBuffereedInputStream myBuffereedInputStream = null ; BufferedOutputStream bufferedOutputStream = null; try { fInStream = new FileInputStream("E:\\eclipse-workspace\\day1101\\src\\com\\StormWang\\InputStream\\CopyPicture.java"); myBuffereedInputStream = new MyBuffereedInputStream(fInStream); bufferedOutputStream = new BufferedOutputStream(new FileOutputStream("myBuff.txt")); int ch = 0; while ((ch=myBuffereedInputStream.myRead())!= -1) { bufferedOutputStream.write(ch); } } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally { if (myBuffereedInputStream!= null) { myBuffereedInputStream.myClose(); } if (bufferedOutputStream != null) { try { bufferedOutputStream.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if (fInStream != null) { try { fInStream.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }}
我们来看一下结果:
读写成功!
(待回头再思考。。。。。。)**注意:**字节流的read()方法读取一个字节。为什么返回的不是byte类型的,而是int 类型的呢?因为read方法读到末尾时返回的是-1.而在所操作的数据中的很容易出现连续多个1的情况,而连续读到8个1,就是-1.导致读取会提前停止。所以将读到的一个字节给提升为一个int类型的数值,但是只保留原字节,并在剩余二进制位补0.具体操作是:byte&255 or byte&0xff 对于write方法,可以一次写入一个字节,但接收的是一个int类型数值。只写入该int类型的数值的最低一个字节(8位)。即对于write()方法实际上进行了强制转化的动作。简单说:read方法对读到的数据进行提升。write对操作的数据进行转换。**
转换流
- 特点:
1,是字节流和字符流之间的桥梁。
2,该流对象中可以对读取到的字节数据进行指定编码表的编码转换。 - 什么时候使用呢?
1,当字节和字符之间有转换动作时。
2,流操作的数据需要进行编码表的指定时。
具体的对象体现:这两个流对象是字符流体系中的成员。
1,InputStreamReader:字节到字符的桥梁。
2,OutputStreamWriter:字符到字节的桥梁。
这两个流对象是字符流体系中的成员。那么它们有转换作用,而本身又是字符流。所以在构造的时候,需要传入字节流对象进来。
构造函数:
InputStreamReader(InputStream):通过该构造函数初始化,使用的是本系统默认的编码表GBK。
InputStreamReader(InputStream,StringcharSet):通过该构造函数初始化,可以指定编码表。
OutputStreamWriter(OutputStream):通过该构造函数初始化,使用的是本系统默认的编码表GBK。
OutputStreamWriter(OutputStream,StringcharSet):通过该构造函数初始化,可以指定编码表。
我们来看看API是怎么解释的:
我们通过代码来演示一下:
小技巧:1. * 源:键盘录入 * 目的:控制台 * @author StormWangxhu * 2.改变需求:想把键盘录入的数据存储到一个文件中 * 源:键盘 * 目的:文件 * * 3.改变需求:想要将一个文件数据打印到控制台上 * 源:文件 * 目的:控制台 * * ######################流操作的基本规律:############## * 最痛苦的就是流对象有很多,不知道该用哪一个? * 通过三个明确来完成: * 1.明确源和目的 * 源:输入流. InputStream Reader * 目的:输出流. OutputStream Writer * 2.明确操作的数据是否是是纯文本 * 是纯文本:用字符流 * 不是纯文本:用字节流 * 3.当体系明确后,再明确要使用哪个具体的对象 * 通过设备来进行区分: * 源设备:内存、硬盘、键盘 * 目的设备:内存、硬盘(文件)、控制台 * ----------------------3个需求之一----------------------- * 1.将一个文本文件中的数据存储到另一个文件中 ,也就是复制文件 * 源:因为是源,所以使用读取流:InputStream Reader * a.是不是操作文本文件? * 是:这就可以选择Reader * 不是:可以选择InputStream * 这样下来,所属体系就明确了。 * * b.接下来就要明确要使用体系中的哪个对象? * 明确设备:硬盘上的一个文件 * Reader体系中可以操作文件的对象是FileReader * c.是否需要提高效率? * 需要:加入Reader体系的缓区:BufferedReader * * 接下来就是: * 1) FileReader fr =new FileReader("a.txt"); 2) BufferedReader br = new BufferedReader(fr); * 目的:文件 OutputStream Writer * a.目的是否是纯文本的? * 是:Writer * 不是:OutputStream * b.明确设备:硬盘上的一个文件 * Writer体系中可以操作一个文件的对象是FileWriter * * c.是否需要提高效率? * 需要:加入Writer体系的缓冲区:BufferedWriter * * 接下来就是: * 1) FileWriter fw = new FileWriter("b.txt"); 2) BufferedWriter bw = new BufferedWriter(fw); * * 练习: 将一个图片文件中的数据存储到另一个图片中 ,即为copy图片,要按照以上的格式去写 * 源(是图片):因为是源, 所以使用读取流:InputStream Reader * a.是不是操作的纯文本文件? * 不是:这就可以选择InputStream * 是:这就可以选择 Reader * b.接下来就要明确要使用体系中的哪个对象? * 明确设备:硬盘上的一个图片 * InputStream体系中可以操作图片的对象时FileInputStream * c.是否需要提高效率? * * 需要:加入InputStream体系的缓冲区:BufferedInputStream * * 接下来就是: * FileInputStream fis = new FileInputStream("1.jpg"); BufferedInputStream bis = new BufferedInputStream(fis); * 目的:文件 OutputStream Writer * a.是否是纯文本的文件? * 不是:OutputStream * 是:writer * b.明确设备:硬盘上的一个图片 * * OutputStream体系中可以操作一个文件的对FileOutputStream * c.是否需要提高效率? * * 需要:加入OutputStream体系的缓冲区:BufferedOutputStream * FileOutputStream fos = new FileOutputStream("2.jpg"); * * BufferedOutputStream bos = BufferedOutputStream(fos); *
我们来实现一个功能,把一个 文件的内容 输出到 控制台 上
package com.StormWang.InputStream;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.FileWriter;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;/*** @author StormWangxhu* @version 创建时间:2017年11月1日 下午8:04:29**//* * 实现将一个文件中的内容输出到控制台上 * */public class FileStreamDemo_2 { public static void main(String[] args) { // TODO Auto-generated method stub //创建读取和写入对象 BufferedReader bReader = null ; BufferedWriter bWriter = null ; try { /** * FileinputStream fs = new FileInutStream("E:\\eclipse-workspace\\day1101\\myBuff.txt"); * InputStreamReader isr = new InputStreamReader(fs); * BufferedReader br = new BufferedReader(isr); * 以上三句合并为一句如下: */ bReader = new BufferedReader( new InputStreamReader(//将字节流转换为字符流。 new FileInputStream("E:\\eclipse-workspace\\day1101\\myBuff.txt"))); bWriter = new BufferedWriter( //将字符流转化为字节流 //并输出到控制台上 new OutputStreamWriter(System.out)); //循环读取 String lines = null ; /** * readLine()方法的原理: * 其实缓冲区中的readLine()方法,用的还是与缓冲区关联的流对象的read()方法 。 * 只不过,每一次读到一个字符,先不进行具体的操作,先进行临时存储。 * 当读到回车标记时,将临时容器中存储的数据一次性的返回。 * * */ while ((lines = bReader.readLine())!= null) { //读一行,写一行,把每一行都写到输出流中 bWriter.write(lines); //写一行后换一行 //newLine()方法为跨平台换行。。 bWriter.newLine(); //写一行刷新一行 bWriter.flush(); } } catch (FileNotFoundException e) { System.out.println("找不到文件了!"); e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally { if (bReader!= null) { try { bReader.close(); }catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } if (bWriter!= null) { try { bWriter.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } }}
看一下结果:
输出成功!
好了,就先总结到这儿吧。如有错误,还望指正!
- Java I/O流总结(二)
- Java I/O总结(二)
- java i/o 学习总结(二)
- Java I/O 学习总结(二)
- Java进击(二) I/O流
- Java基础I/O流(二)
- java输入输出流(I/O)总结
- java输入输出流(I/O)总结
- Java I/O流总结(一)
- Java I/O流(二)
- JAVA I/O 流(二)
- Java I/O 流 总结
- java总结I/O流
- java i/o流总结
- Java I/O流总结
- java I/O流总结
- Java I/O流总结
- Java I/O流总结
- vue2.0+vue-cli+webpack+vue-router中路由设定
- <iframe>和<frame>区别
- 编译 CTK
- Ubuntu14.04安装与配置ROS Indigo 详细教程
- JavaScript编码规范
- Java I/O流总结(二)
- block,inline和inlinke-block区别
- 用TortoiseSVN的SubWCRev.exe管理同步项目版本号
- 正则匹配地点 标点符号
- 实用Java代码
- spring mvc 上传文件默认大小错误
- 无服务器探索之路(初级):AWS Lambda服务应用场景实践之一(六)
- AsyncTask的基础使用
- RecyclerView加载多类型item 实现淘宝首页布局