[19/03/30-星期六] IO技术_四大抽象类_ 字节流( 字节输入流 InputStream 、字符输出流 OutputStream )_(含字节文件缓冲流)...

1、概念及分类html

       InputStream(输入流)/OutputStream(输出流)是全部字节输入输出流的父类java

【注】输入流和输出流的是按程序运行所在的内存的角度划分的数组

          字节流操做的数据单元是8的字节,字符流操做的数据单元是16位的字符缓存

【流的概念】eclipse

——————————post

ooooooooooooooooo学习

—————————— (输入流模型,文件从头(左边)到尾(右边),)测试

↑,(记录指针)编码

 

每一个‘’o“”看出一个"水滴",不论是字节流仍是字符流,每一个水滴是最小的输入/输出单位,对于字节流而言,每一个水滴是1个字节(8位)spa

对于字符流而言,每一个水滴是1个字符(16位)。输入流使用隐含的记录指针来表示当前正准备从哪一个水滴开始读取,每当程序从InputStream或

Reader里取出一个或多个水滴后,指针自动向后(指针从左往右)移动。此外,还能够控制记录指针的移动,好比说设置偏移量off。

对于输出流相对于把水滴放入输入流水管中,也有记录指针自动控制移动,每当程序向OutputStream或Writer输出一个或多个水滴后,记录指针自

动向后移动。

 

一、InputStream(重要的是 文件操做字节流FileInputStream子类和带8KB缓冲数组的ButteredInputStream)

      此抽象类是表示字节输入流的全部类的父类。InputSteam是一个抽象类,它不能够实例化。 数据的读取须要由它的子类来实现。根据节点的不一样,

它派生了不一样的节点流子类 。 继承自InputSteam的流都是用于向程序中输入数据,且数据的单位为字节(8 bit)。

      int read():从(所写程序的源文件中)一个一个字节读取数据,并将字节的值做为int类型返回(0-255之间的一个值)。

                         若是未读出字节则返回-1(返回值为-1表示读取结束)。

      int (byte b[]) :一段一段的读取数据

      void close(): (通知操做系统)关闭输入流对象,释放相关系统资源。

【代码示例】字节文件操做流_不带缓冲数组 (FileInputStream)

  1 /*输入流(从数据源输入到程序中) :数据源-->>程序,是从数据源(源文件、类比书本上知识)读取(read)数据到程序(目标程序、大脑)
  2  * 输入流对应read()方法 ,从书本上流入(输入、Input)到大脑中,而大脑须要读取(read)书本上的知识  
  3 * 步骤:选择源数据-->>选择流(选哪一个搬家公司)-->>操做(一个一个读/写or一段一段读/写,即怎么搬家)-->>释放系统资源(让搬家公司走)
  4  *  
  5   1、 read():从输入流中读取一个8位的字节的数据,(程序自动)把它转成0-255之间的整数,并返回这个整数。 采用逐个读取字节
  6 1.从读取流读取的是一个一个字节 
  7 2.返回的是字节的(0-255)内的字节值 ASCII码
  8 3.读一个下次就自动到下一个,若是碰到-1说明没有值了.
  9 
 10  2、 read(byte[] bytes): 从输入流中最多读取bytes.length(定量)个字节的数据(最后一次可能不满,前面确定是满的),并将
 11  它们存在byte数组中,返回实际读取的字节数
 12 1.从读取流读取必定数量的字节,若是好比文件总共是102个字节
 13 2.咱们定义的数组长度是10,那么默认前面10次都是读取10个长度
 14 3.最后一次不够十个,那么读取的是2个
 15 4.这十一次,每次都是放入10个长度的数组.
 16 
 17  3、read(byte[] bytes,int off ,int len):从输入流中最多读取len个字节(字节能够设定,但不超过数组最大容量)将其存在bytes
 18 数组中,但放入数组的时候并非从起点开始的是从能够本身设定的off位置开始的(固然能够设为0,表示从起点开始)返回实际读取的字节数
 19 1.从读取流读取必定数量的字节,若是好比文件总共是102个字节
 20 2.咱们定义的数组长度是10,可是这里咱们写read(bytes,0,9)那么每次往里面添加的(将只会是9个长度),就要读12次,最后一次放入3个.
 21 3.因此通常读取流都不用这个而是用上一个方法:read(byte[]);
 22 
 23   void close()关闭输入流并释放与该流相关的全部系统资源
 24  */
 25 package cn.sxt.test;
 26 
 27 import java.io.File;
 28 import java.io.FileInputStream;
 29 import java.io.IOException;
 30 import java.io.InputStream;
 31 
 32 
 33 public class Test_0329_InputStream {
 34     public static void main(String[] args) throws IOException { //与外界(操做系统读写)有联系,可能有异常,因此抛出异常
 35         //一、选择源文件 内容为:hello China I love you
 36         File file=new File("编码_GBK_纯英文.txt");    //GBK编码 英文占一个字节
 37         //二、选择流 FileInputStream 顺序的读取文件,只要不关闭每次调用read()方法就顺序的读取源数据中【剩余】的内容
 38         InputStream iStream=new FileInputStream(file);
 39         
 40         //这种写法也对,综合了第一步和第二步,更加简单
 41         FileInputStream iStream2=new FileInputStream("编码_GBK_纯英文.txt");
 42         
 43         //3-1-一、有点绕的写法   测试read()方法选择操做 (读/写) 循环读取 一个一个字节去读
 44         /*int temp;
 45         while ((temp=iStream.read())!=-1) {
 46             System.out.print((char)temp);
 47             
 48         }*/
 49          //3-1-二、最可让人理解的一种写法
 50         /*int b=0;//b的做用记住每次读取的一个字节的整形返回值(英文、数字及常见符号其实就是ASCII码的值)
 51         while (true) {
 52             b=iStream.read();
 53             if (b==-1) {//若是读出字节为-1 跳出整个循环表示已经到文件末尾
 54                 break;
 55             }
 56             System.out.print((char)b);
 57         }*/
 58         
 59         
 60         /*//3-2 测试read(byte[] b)方法 将数据读取到准备好的字节数组(byte[],这里名字叫datas)中,同时返回读取字节数组的实际长度
 61         // 若是到结尾,返回-1
 62         byte datas[]=new byte[4]; //新建一个大小为4的字节(byte)数组,名字叫datas.
 63         int length=iStream.read(datas);//length=4 就是每次读取时字符的实际长度,由于读到最后是可能剩余的字符不足4 可能为3
 64                                  //当最后读取完后,再去读取时发现没有了,则返回-1 表示读取结束
 65          //String msg2=new String(datas, 0, datas.length, "GBK"); 标准解码语句
 66         String msg2=new String(datas, 0, length); //字节数组解码成字符 
 67         System.out.println(msg2); //输出 "hell" 由于没用循环只表示一次读取的状况,一次只读取了4个字节的字符
 68         //能够加循环或者加大datas数组的大小,让其一次读完 
 69         */
 70          
 71         
 72         
 73         //3-3 测试read(byte[] b,int off,int len)方法 。读取任意一段字节。off(偏移量):表示把源文件中从头(即下标)开始读取到的字节数存在
 74         //datas数组下标为off开始的位置,读取源文件的长度为len,也就是在datas数组中下标为off开始位置存储长度为len字节的源数据 
 75         byte datas[]=new byte[7];
 76         
 77         //虽然定义的数组datas大小为7个字节,但每次只添加4个字节的字符,表示使用datas数组的实际使用空间为4个字节。
 78         //2的含义:表示把读取到数据存在datas数组下标为2的位置 即datas[2]='h'意味着datas[0]=datas[1]=0,即null空字符
 79         //4的含义:在datas数组中从下标为2的位置开始存储一段长度为4的源数据字节(从源文件开头读的) 即
 80         //datas[2]=104,'h';datas[3]=101,'e';datas[4]=108,'l';datas[5]=108,'l' datas[6]=0 ,null
 81         int length=iStream.read(datas, 2, 4);//read()方法返回length=4 4:表明实际存储一段长度为4的字节,其它下标位置存储为空
 82         System.out.println(length);
 83         for (int i=0;i<datas.length ;i++) {
 84             System.out.printf("datas[%d]=%d;",i,datas[i]);
 85             
 86         }
 87         
 88         
 89         //ASCII码 (范围 0-127)null 0;a 97;b 98;c 99;d 100;e 101;f 102; g 103 ;h 104;i 105; g 106;k 107;l 108  
 90         //字节数组解码成字符  从数组datas下标为1的地方开始解码(只测试纯英文的状况,含中文数字可能报异常)。
 91         //解码长度length=4,表明解码一段长度为4的字节码文件 输出" hel";也能够length-1 解码一段长度为3的datas数组文件
 92         //输出结果为" he"  
 93         String msg2=new String(datas, 1, length); //String 构造方法,字节-->>字符 
 94         System.out.println("\n"+msg2); 
 95         
 96         
 97         /*
 98         int data1=iStream.read();//读取第一个字符 "h" 输出的是"h"的ASCLL码104 
 99         int data2=iStream.read();//读取第二个字符 "e"
100         int data3=iStream.read();//读取第三个字符 "l"
101         System.out.println(data1);//返回的数据的ASCII码须要强制转型 。文件的末尾若是没有数据返回-1
102         System.out.println((char)data2);
103         System.out.println((char)data3);*/
104         
105         //四、释放资源
106         iStream.close();
107         
108     }
109 
110 }

 

二、 OutputStream  (重要的是 文件操做字节流FileOutputStream子类和带8KB缓冲数组的ButteredOutputStream子类))

      此抽象类是表示字节输出流的全部类的父类。输出流接收输出字节并将这些字节发送到某个目的地。

      void write(int n):向目的地(即所写程序)中写入一个字节。

      void write(byte b[]):一段一段去写数据

      void  (byte b[],int off,int len) :从指定的字节数组写入len字节,从偏移量off开始输出到此输出流

      void flush() :刷新此输出流,并强制任何缓冲的输出字节流被写出。

      void close(): (通知操做系统)关闭输出流对象,释放相关系统资源。

【代码示例】

 1 /*
 2 *输出(Output)流(Stream)。
 3 *经过写字( write()方法 ),把大脑中的知识(类比程序)输出(写出)到(Output)外界的做业本上(类比源文件,如a.txt文件),去更改做业本上原有的内容
 4 步骤:建立源-->>选择流-->>操做(写出内容)-->>释放资源
 5 void write(int n):     向目的地(即所写程序)中写入一个字节。逐个写入字节
 6   n应是读取到的源数据编码值。如把"love"写入目标文件, 一个一个字节读,读到'l' 此时这里的n应该是'l'的ASCII码值108,依次往下读
 7    while(( len=in.read() )!=-1){
 8          out.write(len);
 9    } 这段程序完成文件的复制,表示读到的十进制编码值(0-255之间,英文就是ASCII码),而后把这个值送到write()方法中,让其执行写入操做
10     可是效率很低,它是读一个字节取到编码值后,而后再根据编码值去写入,循环往复。一个字节一个字节读和写.比如不少货物但每次只送一个,
11     循环往复,尽管车箱很大,只装一个,浪费油。电脑中就是浪费内存,不停进行磁盘读写,速度很慢。       
12     
13 void write(byte b[]):一段一段去写数据。把参数b指定的字节数组的【全部字节】写入到目标文件中去。批量写入
14    为了提升送货速度则能够每次把车箱装满,减小送货次数 车箱就是byte[]数组 批量送货,减小磁盘读写
15 void  (byte b[],int off,int len) :将指定的byte数组【从偏移量off开始的len个字节】写入到目标文件。 批量写入
16 
17 void flush() :刷新此输出流,并强制写出全部缓冲中的字节
18 void close() : 关闭输出流并释放系统资源
19 
20  * 
21  */
22 package cn.sxt.test;
23 
24 import java.io.File;
25 import java.io.FileOutputStream;
26 import java.io.IOException;
27 import java.io.OutputStream;
28 
29 public class Test_0329_OutputStream {
30     public static void main(String[] args) throws IOException {
31         //一、给出输出流目的地(给出做业本)(与read()不一样那个源文件必须存在,才能够被正确读出,这里可不存在,帮你建立源文件)
32         File file=new File("编码_GBK_输出流.txt");
33         //二、建立指向目的地的输出流。参数:true:(前提是文件已存在)表示赞成在文件末尾追加新字节数组, false:表示不一样意,即覆盖目的地文件的内容
34         OutputStream oStream=new FileOutputStream(file,true);
35         //三、让输出流把字节数组写入目的地
36         String msg="I love you";
37         byte datas[]=msg.getBytes();
38         //ASCII码 :范围是十进制的 0-127
39         //byte:整形变量(8位,范围十进制的-128-127) 字符串-->>字节存在名叫datas的数组 :编码
40         //再次理解getBytes()方法: 此方法所作的工做就是英文字符(按GBK的方式,本电脑eclipse默认是GBK)进行编码,而后把它们的
41         //十进制编码存在datas数组中,GBK中文占3个字节,英文占1个字节.GBK兼容ACSII码,因此英文字符的编码就是它们的ACSII码
42         //并且一个datas数组下标对应一个字节,对于英文1个下标存储1个字符如:datas[0]=73对应英文字符'I' datas[1]=32 对应' '(空格)
43         //假设有中文字符则是datas[n-1][n][n+1]这3个连续的空间共同存储一个中文字符(占3个字节)。这3个空间返回的分别是这个        
44         //中文字符的编码的(23-16位,15-8位,7-0位)的十进制数。
45         
46         for (int i=0;i<datas.length ;i++) {
47             System.out.printf("datas[%d]=%d;",i,datas[i]);
48             //3-1:利用循环向txt文件中一个一个字节写入
49             //oStream.write(datas[i]);
50             
51         }
52         //3-2 一段一段字节去写入
53         //oStream.write(datas);//把datas数组中的所有字符写入目的文件
54         
55         //3-3 写入部分字节  往目的地的txt文件中写了datas数组的部分字节(从下标2(字符'l')开始,长度为8的一段字节)
56         oStream.write(datas, 2, datas.length-2);
57         
58         //四、关闭输出流
59         oStream.close();;
60     }
61 
62 }

 

【示例】利用输入流和输出流进行文件复制_不带缓冲数组 (FileInputStream)

 1 /*
 2  *利用输入流和输出流完成文件的复制
 3  * 输入流(InputStream)  书本的知识输入到大脑中,大脑要读取(read)知识
 4  * 输出流(OutputStream) 大脑中的知识要写出(write)到做业本上
 5  * 一、为了减小对硬盘的读写次数,提升效率,一般设置缓存数组。相应地,读取时使用的方法为:read(byte[] b)
 6  *                                    写入时的方法为:write(byte[ ] b, int off, int length)。
 7  */
 8 package cn.sxt.test;
 9 
10 import java.io.File;
11 import java.io.FileInputStream;
12 import java.io.FileOutputStream;
13 import java.io.IOException;
14 import java.io.InputStream;
15 import java.io.OutputStream;
16 
17 public class Test_0330_CopyFile {
18     public static void main(String[] args) throws Exception {
19 
20         //copy("SongYi.jpg", "Song2.jpg"); 图片也可复制,可是要注意设置缓冲数组的大小
21         copy("src.txt", "src_copy3.txt");
22     }
23 
24 
25     static void copy(String src,String dest) throws IOException{
26         //一、获取源数据
27         File file =new File(src);//源文件 从这里读取字节
28         File file2=new File(dest);//目标文件 往这里写入字节
29 
30         //二、选择流
31         InputStream iStream=new FileInputStream(file);//输入流 。从源文件(书本)输入到程序中(大脑中)
32         OutputStream oStream=new FileOutputStream(file2);//输出流。 从程序中(大脑中)输出到目标文件(做业本)上.采用的是覆盖,而不是追加
33 
34         //三、选择操做
35         /*把读到数据存在butter数组从下标0开始的位置,每次存储长度为数组的长度(也即一次就读完)。若butter.length 改成4表示
36          *每次只读取源文件的(从头开始的)前4个字节,存在butter[0]--butter[3]中,至于源文件剩下的须要再次运行程序读取或加个循环
37          *对于较大的文件(如图片)能够加大缓冲数组的容量
38          */        
39         byte butter[]=new byte[1024];//缓冲数组,数组的大小为1024 。中转站 大脑
40         
41         /*  //3-1:总体读取写入,每次都固定读取1024个字节
42         iStream.read(butter);
43         oStream.write(butter);*/
44         
45         // 3-2 :能够选择总体读取或者部分读入(即把butter.length的数值改低).这里起到效果是总体读取与3-1是一个道理 
46         iStream.read(butter,0,butter.length);
47         oStream.write(butter, 0, butter.length); 
48         
49         
50         /*//能够具体看看读取到的内容 详细步骤
51         iStream.read(butter,0,butter.length);
52         String msg=new String(butter,0,butter.length);//字节-->>字符串:解码
53         System.out.println(msg);
54         byte datas[]=msg.getBytes();//对读取到的msg字符串进行编码:字符串-->>字节
55         oStream.write(datas, 0, datas.length);  */
56          
57 
58         //四、关闭流
59         oStream.close();
60         iStream.close();
61 
62     }
63 }

 【代码示例】字节文件操做流_带缓冲数组 (ButteredInputStream)大小为8192B(大小就是8KB,2^13次方,1KB=1024B,)

·

 1 /** 
 2  * 学习 BufferedInputStream/BufferedOutputStream 缓冲字节流类
 3  *复制文件  测试Java自带的在缓冲数组的输入输出流
 4  */ 
 5 
 6 package cn.sxt.test;
 7 
 8 import java.io.BufferedInputStream;
 9 import java.io.BufferedOutputStream;
10 import java.io.FileInputStream;
11 import java.io.FileOutputStream;
12 import java.io.IOException;
13 
14 
15 public class Test_0330_Buffered {
16     public static void main(String[] args) throws IOException {
17         /*File file=new File("poem.txt");
18         InputStream iStream=new FileInputStream(file);*/
19         //带缓冲的输入流 缓冲区为8KB 8192B (8192个字节)
20         FileInputStream file=new FileInputStream("poem.txt");
21         BufferedInputStream iStream=new BufferedInputStream(file);
22 
23         FileOutputStream file2=new FileOutputStream("poem2.txt");
24         BufferedOutputStream oStream=new BufferedOutputStream(file2);
25         long  b=System.currentTimeMillis();//获取系统当前时间
26         int len;
27         while ( (len=iStream.read()) !=-1) {
28             oStream.write(len);    //当调用read()或write()方法时 首先将读写的数据存入类内部定义好8KB的数组中,而后一次性
29             //读写到文件中,相似于前边本身自定义的大小为1KB的数组,极大提升读写效率
30         }
31         long  c=System.currentTimeMillis();
32         System.out.println("共花费:"+(c-b)+"毫秒");
33         iStream.close();
34         oStream.close();
35         
36         
37         //不带缓存缓冲的
38         FileInputStream file3=new FileInputStream("poem.txt");
39         FileOutputStream file4=new FileOutputStream("poem3.txt");
40         
41         long  d=System.currentTimeMillis();//获取系统当前时间
42         int length;//不带缓冲区的,老办法,读取一个字节,往文件中写一个字节。循环往复直到结束。速度很慢
43         while ( (length=file3.read()) !=-1) {
44             file4.write(length);    
45         }
46         long  e=System.currentTimeMillis();
47         System.out.println("共花费:"+(e-b)+"毫秒"); //很明显比带缓冲区的花费时间多
48         file3.close();
49         file4.close();
50         
51 
52     }
53 
54 }

 

转载于:https://www.cnblogs.com/ID-qingxin/p/10623587.html