Java IO学习--输入输出流

一、Java IO的定义

I/O:输入输出系统,由输入输出控制系统和外围设备两部分组成。

Java中I/O操作主要是指使用Java进行输入,输出操作. Java所有的I/O机制都是基于数据流进行输入输出,这些数据流表示了字符或者字节数据的流动序列。java类库中的I/O类分为输入和输出两部分。

Java IO模型 :Java的IO模型设计是非常典型的装饰器模式---Decorator模式,按功能划分Stream,可以动态装配这些Stream,以便获得您需要的功能。例如,需要一个具有缓冲的文件输入流,则应当组合使用FileInputStream和BufferedInputStream。

二、流的分类

1.按流的方向分类

  按流的方向分为:输入和输出流,注意输入流和输出流是相对于程序而言的。输入流即从不同数据源输入进程序或者说内存。输出流则相反。

  输入流的数据源包括:字节数组、String对象、文件、管道、一个由其他种类的流组成的序列、其他数据源,如intenet连接等。

2.按传输单位分类

  按传输单位分为:字节流和字符流,例如:InputStream和OutStream、Reader和Writer。

输入/输出

字节流

字符流

输入流

Inputstream

Reader

输出流

OutputStream

Writer

3.按功能分类

  按功能分为:节点流和处理流,节点流:可以从或向一个特定的地方(节点)读写数据。如FileReader。处理流:是对一个已存在的流的连接和封装,通过所封装的流的功能调用实现数据读写。如BufferedReader。

三、Java IO 流的整体架构图

从网上找到一张关于java IO流的整体架构图,一目了然。

 四、输入输出字节流

 1 public class FileStreamDemo {
 2     
 3     public static void main(String[] args) {
 4         
 5         //字节输入/输出流,并且以文件为数据源,即文件字节输入输出流
 6         try {
 7             //1.确定数据源与流类型
 8             File targetFile = new File("E:\\a.txt");
 9             OutputStream os = new FileOutputStream(targetFile, true);//第二参数,表示写入的数据是否追加到文件后面
10             //2.借助流进行具体的IO操作
11             /**
12              * void write(int b):把一个字节写入到文件中
13              * void write(byte[] b):把数组b 中的所有字节写入到文件中
14              * void write(byte[] b,int off,int len):把数组b 中的从 off 索引开始的 len 个字节写入到文件中
15              */
16             os.write(45);
17             os.write("aaa".getBytes());
18             os.write("bbbbb".getBytes(), 1, 3);
19             //操作完毕,关闭流
20             os.close();
21             
22             //通过字节输入流将目标文件的数据读取进内存中
23             InputStream is = new FileInputStream(targetFile);
24             
25             //读取一个字节
26             int data1 = is.read();
27             System.out.println((char)data1);
28             
29             byte [] bytes = new byte[10];
30             is.read(bytes);
31             System.out.println(Arrays.toString(bytes));
32             
33             is.close();
34             
35             
36             
37         } catch (Exception e) {
38             e.printStackTrace();
39         }
40         
41         
42         
43     }
44 
45 }

结果输出:

-
[97, 97, 97, 98, 98, 98, 0, 0, 0, 0]

 

 五、输入输出字符流

Java中字符是采用Unicode标准,一个字符是16位,即一个字符使用两个字节来表示。为此,JAVA中引入了处理字符的流。一般可以用记事本打开的文件,我们可以看到内容不乱码的。就是文本文件,可以使用字符流。而操作二进制文件(比如图片、音频、视频)必须使用字节流。

 1 public class FileStreamDemo2 {
 2     
 3     public static void main(String[] args) {
 4         //1.定义数据源对象
 5         File targetFile = new File("E:\\test.txt");
 6         try {
 7             //2.定义输出字符流
 8             FileWriter fw = new FileWriter(targetFile,true);
 9             //3.借助字符流进行IO操作
10             fw.write(65);
11             fw.write("lplp");
12             fw.write(new char[]{'a','b','c'}, 1, 2);
13             fw.close();
14             
15             FileReader fr = new FileReader(targetFile);
16             char [] ch= new char[5]; 
17             System.out.println(fr.read());
18             int count = fr.read(ch);//读取流中字符填充到字符数组ch中
19             System.out.println(count+":"+Arrays.toString(ch));
20             fr.close();
21         } catch (Exception e) {
22             e.printStackTrace();
23         }
24     }
25 
26 }

结果输出:

65
5:[l, p, l, p, b]

六、包装流的使用

包装流,又称处理流,主要用来对已存在的流进行修饰和封装,进一步丰富或拓展流的功能。常用的处理流主要有下面几种

1.缓冲流

  缓冲流:是一个包装流,目的是缓存作用,加快读取和写入数据的速度。

  字节缓冲流:BufferedInputStream、BufferedOutputStream

  字符缓冲流:BufferedReader、BufferedWriter

 1 public class BufferStreamDemo {
 2     
 3     public static void main(String[] args) {
 4         
 5         //1.定义数据源对象
 6         File targetFile = new File("E:\\test2.txt");
 7         
 8         try {
 9             //2.定义字节缓冲输出流
10             BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(targetFile));
11             /*
12              *通过缓冲流将字节数组写入到文件输出流,最终是写入到文件,与通过文件字节输出流的区别在于,具备一个缓冲的作用,并不会立即将字节数组或者字节
13              * 写入到文件中,而先将字节写入到缓冲字节数组中,最后一次性写入到输出流中,避免多次操流,减少IO操作,提高效率,写到内存中比写到硬盘上快的多
14              */
15             bos.write("aaa".getBytes());
16             bos.write(100);
17             bos.write("sdjlksdjkl".getBytes(), 1, 5);
18             
19             bos.flush();//将缓冲字节数组的字节写入文件
20             bos.close();
21             //3.定义字节缓冲输入流,本质上也是较少IO操作
22             BufferedInputStream bis = new BufferedInputStream(new FileInputStream(targetFile));
23             
24             System.out.println((char)bis.read());
25             byte [] bs = new byte[8]; 
26             bis.read(bs);
27             System.out.println(Arrays.toString(bs));
28             System.out.println(new String(bs));
29             
30             bis.close();
31         } catch (Exception e) {
32             e.printStackTrace();
33         }
34         
35     }
36     
37 }

结果输出:

a
[97, 97, 100, 100, 106, 108, 107, 115]
aaddjlks

字符缓冲流,BufferedReader和BufferedWriter的使用和上面异曲同工。

2.转换流

InputStreamReader:把字节输入流转换为字符输入流

OutputStreamWriter:把字节输出流转换为字符输出流

 1 public class BufferStreamDemo2 {
 2     
 3     public static void main(String[] args) {
 4         
 5         //1.定义数据源对象
 6         File targetFile = new File("E:\\test2.txt");
 7         
 8         try {
 9             //定义缓冲字符流,将字节输出流转换为字符流,再包装为字符输出缓冲流,并且字符在转字节的时候,采用的编码为UTF-8
10             BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(targetFile),"UTF-8"));
11             bw.write("aaabababcc");
12             bw.flush();
13             bw.close();
14             BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(targetFile)));
15             String line = br.readLine();//读取文件中的一行
16             System.out.println(line);
17             br.close();
18             
19         } catch (Exception e) {
20             e.printStackTrace();
21         }
22         
23     }
24     
25 }

结果输出:

aaabababcc

3.内存流

字节内存流:ByteArrayOutputStream 、ByteArrayInputStream

字符内存流:CharArrayReader、CharArrayWriter

字符串流:StringReader,StringWriter(把数据临时存储到字符串中)

 1 public class ArrayStreamDemo {
 2     
 3     public static void main(String[] args) {
 4         //1.字节内存流,数据源为字节数组
 5         ByteArrayInputStream bais = new ByteArrayInputStream("aaa".getBytes());
 6         //2通过字节流从字节数组从读取字节
 7         int len =-1;
 8         while((len=bais.read())!=-1){
 9             System.out.println((char)len);
10         }
11         //3.定义字节数组输出流
12         ByteArrayOutputStream baos = new ByteArrayOutputStream(5);//10表示指定字节数组的大小
13         try {
14             baos.write("abcdef".getBytes());
15             
16             System.out.println(Arrays.toString(baos.toByteArray()));
17             System.out.println("--------------");
18             //4.定义字符数组输出流
19             CharArrayWriter caw = new CharArrayWriter();
20             caw.write("ppll");
21             System.out.println(new String(caw.toCharArray()));
22             //5.定义字符数组输入流
23             CharArrayReader car = new CharArrayReader(caw.toCharArray());//从字符数组中读取字符
24             int len2 =-1;
25             while((len2=car.read())!=-1){
26                 System.out.print((char)len2);
27             }
28             System.out.println();
29             System.out.println("--------------");
30             //7.字符串输入流
31             StringReader sr = new StringReader("aaaa");
32             //8.字符串输出流
33             StringWriter sw = new StringWriter();
34             int len3=-1;
35             while((len3=sr.read())!=-1){
36                 sw.write(len3);
37             }
38             System.out.println(sw.getBuffer().toString());
39             
40         } catch (Exception e) {
41             e.printStackTrace();
42         }
43         
44         
45     }
46 
47 }

输出结果:

a
a
a
[97, 98, 99, 100, 101, 102]
--------------
ppll
ppll
--------------
aaaa

转载于:https://www.cnblogs.com/liupiao/p/9291762.html

Java IO流学习总结 Java流操作有关的类或接口: Java流类图结构: 流的概念和作用 流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作。 IO流的分类 根据处理数据类型的不同分为:字符流和字节流 根据数据流向不同分为:输入流和输出流 字符流和字节流 字符流的由来: 因为数据编码的不同,而有了对字符进行高效操作的流对象。本质其实就是基于字节流读取时,去查了指定的码表。 字节流和字符流的区别: 读写单位不同:字节流以字节(8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。 处理对象不同:字节流能处理所有类型的数据(如图片、avi等),而字符流只能处理字符类型的数据。 结论:只要是处理纯文本数据,就优先考虑使用字符流。 除此之外都使用字节流。 输入流和输出流 对输入流只能进行读操作,对输出流只能进行写操作,程序需要根据待传输数据的不同特性而使用不同的流。 Java IO流对象 1.输入字节流InputStreamIO 输入字节流的继承图可见上图,可以看出: InputStream 是所有的输入字节流的父类,它是一个抽象类。 ByteArrayInputStream、StringBufferInputStream、FileInputStream 是三种基本的介质流,它们分别从Byte 数组、StringBuffer、和本地文件读取数据。PipedInputStream 是从与其它线程共用的管道读取数据,与Piped 相关的知识后续单独介绍。 ObjectInputStream 和所有FilterInputStream 的子类都是装饰流(装饰器模式的主角)。 2.输出字节流OutputStream IO 输出字节流的继承图可见上图,可以看出: OutputStream 是所有的输出字节流的父类,它是一个抽象类。 ByteArrayOutputStream、FileOutputStream 是种基本的介质流,它们分别向Byte 数组、和本地文件写入数据。PipedOutputStream 是向与其它线程共用的管道写入数据, ObjectOutputStream 和所有FilterOutputStream 的子类都是装饰流。 3.字节流的输入与输出的对应 图蓝色的为主要的对应部分,红色的部分就是不对应部分。紫色的虚线部分代表这些流一般要搭配使用。从上面的图可以看出Java IO 的字节流是极其对称的。“存在及合理”我们看看这些字节流不太对称的几个类吧! LineNumberInputStream 主要完成从流读取数据时,会得到相应的行号,至于什么时候分行、在哪里分行是由改类主动确定的,并不是在原始有这样一个行号。在输出部分没有对应的部分,我们完全可以自己建立一个LineNumberOutputStream,在最初写入时会有一个基准的行号,以后每次遇到换行时会在下一行添加一个行号,看起来也是可以的。好像更不入流了。 PushbackInputStream 的功能是查看最后一个字节,不满意就放入缓冲区。主要用在编译器的语法、词法分析部分。输出部分的BufferedOutputStream 几乎实现相近的功能。 StringBufferInputStream 已经被Deprecated,本身就不应该出现在InputStream 部分,主要因为String 应该属于字符流的范围。已经被废弃了,当然输出部分也没有必要需要它了!还允许它存在只是为了保持版本的向下兼容而已。 SequenceInputStream 可以认为是一个工具类,将个或者多个输入流当成一个输入流依次读取。完全可以从IO去除,还完全不影响IO 包的结构,却让其更“纯洁”――纯洁的Decorator 模式。 PrintStream 也可以认为是一个辅助工具。主要可以向其他输出流,或者FileInputStream 写入数据,本身内部实现还是带缓冲的。本质上是对其它流的综合运用的一个工具而已。一样可以踢出IO 包!System.out 和System.out 就是PrintStream 的实例! 4.字符输入流Reader 在上面的继承关系图可以看出: Reader 是所有的输入字符流的父类,它是一个抽象类。 CharReader、StringReader 是种基本的介质流,它们分别将Char 数组、String读取数据。PipedReader 是从与其它线程共用的管道读取数据。 BufferedReader 很明显就是一个装饰器,它和其子类负责装饰其它Reader 对象。 FilterReader 是所有自定义具体装饰流的父类,其子类PushbackReader 对Reader 对象进行装饰,会增加一个行号。 InputStreamReader 是一个连接字节流和字符流的桥梁,它将字节流转变为字符流。FileReader 可以说是一个达到此功能、常用的工具类,在其源代码明显使用了将FileInputStream 转变为Reader 的方法。我们可以从这个类得到一定的技巧。Reader 各个类的用途和使用方法基本和InputStream 的类使用一致。后面会有Reader 与InputStream 的对应关系。 5.字符输出流Writer 在上面的关系图可以看出: Writer 是所有的输出字符流的父类,它是一个抽象类。 CharArrayWriter、StringWriter 是种基本的介质流,它们分别向Char 数组、String 写入数据。PipedWriter 是向与其它线程共用的管道写入数据, BufferedWriter 是一个装饰器为Writer 提供缓冲功能。 PrintWriter 和PrintStream 极其类似,功能和使用也非常相似。 OutputStreamWriter 是OutputStream 到Writer 转换的桥梁,它的子类FileWriter 其实就是一个实现此功能的具体类(具体可以研究一SourceCode)。功能和使用和OutputStream 极其类似,后面会有它们的对应图。 6.字符流的输入与输出的对应 7.字符流与字节流转换 转换流的特点: 其是字符流和字节流之间的桥梁 可对读取到的字节数据经过指定编码转换成字符 可对读取到的字符数据经过指定编码转换成字节 何时使用转换流? 当字节和字符之间有转换动作时; 流操作的数据需要编码或解码时。 具体的对象体现: InputStreamReader:字节到字符的桥梁 OutputStreamWriter:字符到字节的桥梁 这个流对象是字符体系的成员,它们有转换作用,本身又是字符流,所以在构造的时候需要传入字节流对象进来。 8.File类 File类是对文件系统文件以及文件夹进行封装的对象,可以通过对象的思想来操作文件和文件夹。 File类保存文件或目录的各种元数据信息,包括文件名、文件长度、最后修改时间、是否可读、获取当前文件的路径名,判断指定文件是否存在、获得当前目录的文件列表,创建、删除文件和目录等方法。 9.RandomAccessFile类 该对象并不是流体系的一员,其封装了字节流,同时还封装了一个缓冲区(字符数组),通过内部的指针来操作字符数组的数据。 该对象特点: 该对象只能操作文件,所以构造函数接收种类型的参数:a.字符串文件路径;b.File对象。 该对象既可以对文件进行读操作,也能进行写操作,在进行对象实例化时可指定操作模式(r,rw) 注意:该对象在实例化时,如果要操作的文件不存在,会自动创建;如果文件存在,写数据未指定位置,会从头开始写,即覆盖原有的内容。 可以用于多线程下载或多个线程同时写数据到文件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值