[19/04/01-星期一] IO技术_字节流分类总结(含字节数组(Array)流、字节数据(Data)流、字节对象(Object)流)

一、字节流分类概括

                                                                 -->1、ByteArrayInputStream /ByteArrayOutputStream(数组字节输入输出)

 

       InputStream/OutputStream            -->2、FileInputStream/FileOutputStream(文件字节输入输出流【参考19.03.30文章】)

 

(四大抽象类之二,与Reader/Writer平辈)   -->3、ObjectInputStream/ObjectOutputStream(对象字节输入输出流)

 

                                                                 -->4、FilterInputStream/FilterOutputStream(加装饰器的输入/输出流)-----》》

 

----------------》》4-1:BufferedInputStream/BufferedOutputStream(带缓冲区的字节流)  【参考19.3.30文章】


----------------》》4-2:DataInputStream/DataOutputStream(数据输入/输出流)


----------------》》4-3:【独有】PrintStream打印输出流、处理流

 

 1、ByteArrayInputStream /ByteArrayOutputStream(数组字节输入输出)

 1 /**学习 1、文件数组字节流 (InputStream/OutputStream的亲儿子)
 2 * ByteArrayInputStream /ByteArrayOutputStream(文件数组字节输入输出)与FileInputStream/FileOutputStream平辈
 3 * 以前源头:本地电脑硬盘文件<-----操作系统----->Java虚拟机  。以前的FileInputStream/FileOutputStream的用法
 4 *          所以每次都要通知操作系统释放内存
 5 * 现在源头:本地电脑的另外一块内存/网络上的一块内存/远程服务器的一块内存 ,看成一块字节数组,所以可以让Java虚拟机直接访问
 6 * 与操作系统无关,使用完后由垃圾回收机制管理,不用释放内存。风格统一,可以释放内存,是实际没作用。
 7 * 1、任何东西都可以转成字节数组 2、字节数组不要太大
 8 * 
 9 * 写数据:ByteArrayOutputStream
10 * 不需要指定文件目的地,这点与FileOutputStream(如需要自己指定个"dest.txt")不同,因为是内存写的,大小不好管理
11 * 可以不用释放操作
12  * 
13  */
14 package cn.sxt.test;
15 
16 import java.io.ByteArrayInputStream;
17 import java.io.ByteArrayOutputStream;
18 import java.io.IOException;
19 
20 public class Test_0401_ArrayStream {
21     public static void main(String[] args) throws IOException {
22         //1、创建源 字符串,编码成字节数组
23         byte[] src="I am angry,Are you OK!".getBytes();
24         //2、选择流
25         ByteArrayInputStream bStream=new ByteArrayInputStream(src);
26         //3、选择操作
27         int len=0;
28        /*3-1: 不借助数组,简单粗暴
29         while ((len=bStream.read())!=-1) { //等于说读一个字节输出一个字节
30             System.out.print((char)len);        
31         }*/
32         //4、可以释放内存,保持统一 ,但其方法是个空方法 ,没什么卵用
33         bStream.close();
34         //3-2 :借助数组,常用方法
35         byte butter[] =new byte[5];
36         /*
37         while ((len=bStream.read(butter))!=-1) {//往butter读取每5个字符,解码换行输出一回。 循环往复
38             String msg=new String(butter,0,butter.length);
39             System.out.println(msg);
40         }*/
41         
42         //-------------分隔符----写数据(往内存中写,这里内存实际就是输出流的缓冲区)---
43         
44         ByteArrayOutputStream bStream2=new ByteArrayOutputStream();//默认构建一个32字节的缓冲区,且内容会自动增加)
45         bStream2.write(src);//把经过编码后的字节src 写入到内存中,也就是输出流缓冲区
46         byte[] dest=bStream2.toByteArray();//向缓冲区取数据
47         System.out.println(dest.length+"-->>"+new String(dest,0,dest.length));//数据展示
48         
49     }
50 
51 }

【综合练习-复制图片】

 1 /** 复制一张图片 所有东西都能读到字节数组中
 2  * 前面4种流的综合 
 3  * ByteArrayInputStream /ByteArrayOutputStream  FileInputStream/FileOutputStream
 4  * 图片---FileInputStream------->(借助程序作中转,Java虚拟机)---ByteArrayOutputStream------>字节数组中(内存)
 5  * 字节数组(内存)----ByteArrayInputStream---->(借助程序作中转,Java虚拟机)---FileOutputStream-------->图片
 6  * 
 7  */
 8 package cn.sxt.test;
 9 
10 import java.io.ByteArrayInputStream;
11 import java.io.ByteArrayOutputStream;
12 import java.io.FileInputStream;
13 import java.io.FileOutputStream;
14 import java.io.IOException;
15 import java.io.InputStream;
16 import java.io.OutputStream;
17 
18 public class Test_0401_CopyImage {
19     public static void main(String[] args) throws IOException {
20         byte[] srcFile= fileToByteArray("SongYi.jpg");
21         System.out.println(srcFile.length);//输出源文件图片的大小
22         ByteArrayToFile(srcFile, "SongYi_copy.jpg");
23         
24 
25     }
26     //1、图片到字节数组 传进去一个源文件路径。    图片-->程序--->字节数组
27     public static byte[]  fileToByteArray(String srcFilePath) throws IOException {
28         
29         InputStream iStream=new FileInputStream(srcFilePath);//图片-->程序
30         ByteArrayOutputStream oStream=new ByteArrayOutputStream();//程序-->字节数组
31         byte buffer[]=new byte[1024*10]; //缓冲数组
32         int len=0; //分段读取
33         while ((len=iStream.read(buffer))!=-1) {
34             oStream.write(buffer,0,len);
35             
36         }
37         iStream.close();
38         
39         return oStream.toByteArray();
40 
41     }
42     
43     
44     //2、字节数组到图片 字节数组--->程序--->要复制的图片
45     public static void  ByteArrayToFile(byte[] src,String destFilePath) throws IOException {
46         
47         ByteArrayInputStream iStream1=new ByteArrayInputStream(src);//字节数组-->程序
48         
49         OutputStream oStream1=new FileOutputStream(destFilePath);//程序--->要复制的图片
50         
51         byte buffer1[]=new byte[1024*10]; //缓冲数组
52         int len=0; //分段读取
53         while ((len=iStream1.read(buffer1))!=-1) {
54             oStream1.write(buffer1,0,len);    
55         }
56         oStream1.close();
57     }
58 
59 
60 }

 2、ObjectInputStream/ObjectOutputStream(对象字节输入输出流)

        当两个进程远程通信时,彼此可以发送各种类型的数据。 无论是何种类型的数据,都会以二进制序列的形式在网络上传送。

比如,我们可以通过http协议发送字符串信息;我们也可以在网络上直接发送Java对象。发送方需要把这个Java对象转换为字节序列,

才能在网络上传送;接收方则需要把字节序列再恢复为Java对象才能正常读取。把Java对象转换为字节序列的过程称为对象的序列化。

把字节序列恢复为Java对象的过程称为对象的反序列化。

对象序列化的作用有如下两种:

      1. 持久化: 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中,比如:休眠的实现。以后服务器session管理,hibernate将对象持久化实现。

      2. 网络通信:在网络上传送对象的字节序列。比如:服务器之间的数据通信、对象传递。

 【代码示例】

  1 /**2、对象流 ObjectStream
  2  * 输出流:序列化
  3  * 输入流:反序列化
  4  *ObjectOutputStream 对象输出流,它的writeObject(Object obj)方法可对参数指定的obj对象进行序列化,
  5  *把得到的字节序列写到一个目标输出流中。这个目标输入流可能是文件,数据库,内存中。
  6  *
  7   ObjectInputStream  对象输入流,它的readObject()方法从一个源输入流中读取字节序列
  8   ,再把它们反序列化为一个对象,并将其返回。
  9 
 10       只有实现了Serializable接口的类的对象才能被序列化。 Serializable接口是一个空接口,只起到标记作用。
 11  * 
 12  * 不是所有的对象都可序列化
 13  */
 14 package cn.sxt.test;
 15 
 16 import java.io.ByteArrayInputStream;
 17 import java.io.ByteArrayOutputStream;
 18 import java.io.IOException;
 19 import java.io.ObjectInputStream;
 20 import java.io.ObjectOutputStream;
 21 import java.security.PrivateKey;
 22 import java.util.Date;
 23 
 24 import javax.tools.JavaCompiler;
 25 
 26 
 27 
 28 public class Test_0401_ObjectStream {
 29     public static void main(String[] args) throws IOException, ClassNotFoundException {
 30 
 31         ByteArrayOutputStream baos=new ByteArrayOutputStream();
 32         ObjectOutputStream dos=new ObjectOutputStream(baos);
 33 
 34 
 35         dos.writeUTF("编码");
 36         dos.writeInt(345);
 37         //写入:序列化
 38         dos.writeObject("编码好痛苦");//字符串也是一个对象
 39         dos.writeObject(new Date());
 40         dos.writeObject(new Employee("李白",3458.4));
 41         
 42         dos.flush();
 43 
 44         //错误原因:byte[] datas=baos.toByteArray();放在了oos.writeInt(14);oos.flush();的前边,应该在后边
 45         byte[] datas=baos.toByteArray();
 46 
 47         //DataInputStream dis=new DataInputStream(new ByteArrayInputStream(datas));
 48 
 49         ByteArrayInputStream bis=new ByteArrayInputStream(datas);
 50         ObjectInputStream dis=new ObjectInputStream(bis);
 51 
 52         //读取 :反序列化
 53         String msg=dis.readUTF();
 54         System.out.println(msg);
 55         System.out.println(dis.readInt());
 56         System.out.println(dis.readObject());
 57         System.out.println(dis.readObject());
 58         //System.out.println(dis.readObject());
 59         //同理前边的字符串类也可以这样操作
 60         Object employee=dis.readObject();
 61         if (employee instanceof Employee) {//如果employee 是Employee类的实例化对象则输出
 62             Employee employeetemp=(Employee)employee;//而且可以强制转换一下
 63             System.out.println(employeetemp); 
 64             
 65             System.out.println("名字:"+employeetemp.getName());
 66             //可以看出薪水的属性加了transient透明修饰,这里的返回值为0.0
 67             System.out.println("薪水:"+employeetemp.getSalary());
 68             
 69         }
 70         
 71 
 72     }
 73 
 74 
 75 }
 76 
 77 //自己定义的一个类,称之为Javabean封装数据用的。这里还必须要序列化(Serializable),加个牌照,否则虚拟机后拦截的
 78 class Employee implements java.io.Serializable{
 79     private  String name;
 80                                   
 81     private transient double salary;//transient:短暂的,临时的  这里翻译为透明的、隐身的.敏感数据可以用。这里不需要序列化
 82     
 83     //按键alt+shift+s 出现上面菜单  无参构造 : 快捷键 下边 Generate Constructors from Supperclass..
 84     //.根据基类的构造函数生成构造函数,生成和基类参数相同的构造函数,并同时调用基类的构造函数。
 85     public Employee() {
 86         super();
 87     }
 88 
 89     //构造方法 Generate Constructor using Fields... 
 90     //      使用类属性生成构造函数,就是说会生成使用你定义好的属性作为参数的构造函数。
 91     public Employee(String name, double salary) {
 92         super();
 93         this.name = name;
 94         this.salary = salary;
 95     }
 96 
 97     
 98     public String getName() {
 99         return name;
100     }
101 
102     
103     public void setName(String name) {
104         this.name = name;
105     }
106 
107 
108     public double getSalary() {
109         return salary;
110     }
111 
112 
113     public void setSalary(double salary) {
114         this.salary = salary;
115     }
116 
117    //重写 toString 方法
118     public String toString() {
119         return "雇员 [name=" + name + ", salary=" + salary + "]";
120     }
121     
122     
123     
124     
125 
126 }

 

 4-2:DataInputStream/DataOutputStream(数据输入/输出流)

【代码示例】

 1 /**
 2  *4-2:DataInputStream/DataOutputStream(数据输入/输出流)
 3  *用途:方便处理8大基本数据类型
 4  *1) 先写出后读取
 5  *2) 读取顺序和写出保持一致
 6  * 
 7  */
 8 package cn.sxt.test;
 9 
10 import java.io.ByteArrayInputStream;
11 import java.io.ByteArrayOutputStream;
12 import java.io.DataInputStream;
13 import java.io.DataOutputStream;
14 import java.io.FileInputStream;
15 import java.io.FileOutputStream;
16 import java.io.IOException;
17 
18 
19 public class Test_0401_DataStream {
20     public static void main(String[] args) throws IOException {
21         //先搞个节点流ByteArrayInputStream /ByteArrayOutputStream或FileInputStream/FileOutputStream
22         //然后让装饰流去操作他们,否则装饰流就是无源之水,无本之木。//默认构建一个32字节的缓冲区,且内容会自动增
23         //ByteArrayOutputStream bos=new ByteArrayOutputStream();//这个流不用关闭
24         
25         //写出,使用数组作为节点流时
26         FileOutputStream out = new FileOutputStream("D:/a1.txt");
27         DataOutputStream dos=new DataOutputStream(out);
28 
29         //byte[] datas=bos.toByteArray();//转成字节放在字节数组中
30 
31         dos.writeChar('a');
32         dos.writeInt(10);
33         dos.writeDouble(Math.random());
34         dos.writeBoolean(true);
35         dos.writeUTF("Are you OK");
36         dos.flush();
37 
38         //读取顺序与写入保持一致
39         //ByteArrayInputStream bis=new ByteArrayInputStream(datas);//从字节数组中读取
40         FileInputStream in = new FileInputStream("D:/a1.txt");
41         DataInputStream dis=new DataInputStream(in);
42 
43         System.out.println("char: " + dis.readChar());
44         System.out.println("int: " + dis.readInt());
45         System.out.println("double: " + dis.readDouble());
46         System.out.println("boolean: " + dis.readBoolean());
47         System.out.println("String: " + dis.readUTF());
48 
49         dos.close();
50         dis.close();
51         
52         //数组作为字节流
53     /*    ByteArrayOutputStream baos=new ByteArrayOutputStream();
54         DataOutputStream dos=new DataOutputStream(baos);
55         
56         dos.writeUTF("编码");
57         dos.writeInt(345);
58         dos.flush();
59         
60         byte[] datas=baos.toByteArray();
61         
62         //DataInputStream dis=new DataInputStream(new ByteArrayInputStream(datas));
63         
64         ByteArrayInputStream bis=new ByteArrayInputStream(datas);
65         DataInputStream dis=new DataInputStream(bis);*/
66 
67     }
68 
69 }

 

 4-3:【独有】PrintStream打印输出流、处理流

 【代码示例】

 1 /**
 2  * 学习4-3:打印流、处理流PrintStream
 3  * 
 4  */
 5 package cn.sxt.test;
 6 
 7 import java.io.FileDescriptor;
 8 import java.io.FileNotFoundException;
 9 import java.io.FileOutputStream;
10 import java.io.PrintStream;
11 import java.io.PrintWriter;
12 
13 public class Test_0401_PrintStream {
14     public static void main(String[] args) throws FileNotFoundException {
15         PrintStream pStream=System.out;
16         pStream.println("人生如逆旅"); //输出内容到控制台
17         pStream.println(true);
18         //2个打印流的效果一样
19         PrintWriter pWriter=new PrintWriter(new FileOutputStream("print3.txt"),true);
20         pWriter.print("学习Java");
21         pWriter.close();
22         
23         FileOutputStream file=new FileOutputStream("print.txt");
24         PrintStream pStream2=new PrintStream(file,true);//在里面放个字节流 true:使用自动刷新的功能
25         pStream2.println(false); //输出内容到文件
26         pStream2.println("人生苦短,学习要趁早!");
27         pStream2.println("java is best");
28         
29         //重定向输出端 把原本输出到控制台的输出到文件中去
30         System.setOut(pStream2);
31         pStream2.println("改变自己");
32         //重定向回去控制台 FileDescriptor.out 标准的输入输出端
33         FileOutputStream file2=new FileOutputStream(FileDescriptor.out);
34         PrintStream pStream3=new PrintStream(file2,true);
35         System.setOut(pStream3);
36         pStream3.println("back");
37         
38         /*//效果一样
39         System.setOut(pStream);
40         pStream.print("回来了");*/
41         
42         pStream.close();
43         pStream2.close();
44         pStream3.close();
45     }
46 
47 }

 

posted @ 2019-04-01 19:22  ID长安忆  阅读(294)  评论(0)    收藏  举报