前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >第8次文章:其他流

第8次文章:其他流

作者头像
鹏-程-万-里
发布2019-09-27 12:22:51
4100
发布2019-09-27 12:22:51
举报

各位小伙伴儿,大家周末愉快哈

回到学校,开始科研,开始好好奋斗咯
一、节点流

1、字节数组 字节 节点流

在两台计算机上进行数据的相互的传输

输入流 :ByteArrayInputStream

使用方法:read(byte[] b,int off,int len) +close()

输出流 :ByteArrayOutputStream

使用方法:write(byte[] b,int off,int len) +toByteArray() + close() 不要使用多态

例如:

代码语言:javascript
复制
package com.peng.IO.others;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

public class ByteArrayDemo01 {

public static void main(String[] args) throws IOException {
read(write());
}
/**
 * 写出操作
 * 字节输出流与文件输出有些不同,因为字节输出流有新增方法,所以不可以使用多态
 * @throws IOException 
 */
public static byte[] write() throws IOException {
//目标位置
byte[] dest ;
//选择流  这里有不同点:没有将目标位置和输出流进行关联
ByteArrayOutputStream bos = new ByteArrayOutputStream();
//操作 写出
String msg = "字节输入流与文件输入流一致";
byte[] info = msg.getBytes();
bos.write(info, 0, info.length);
//获取数据
dest = bos.toByteArray();
//释放资源
bos.close();
return dest;
}

/**
 * 字节输入流(ByteArrayInputStream)与文件输入流一致(FileInputStream)
 * @throws IOException 
 */
public static void read(byte[] src) throws IOException {
//数据源  使用外部传入的方式来获取

//选择流。通过流,打开另一端计算机的数据,所以不能在数据源的地方进行打印输出
InputStream is = new BufferedInputStream(//缓冲流
new ByteArrayInputStream(src)//节点流
);

//操作
byte[] info =new byte[1024];
int len = 0;
while(-1 != (len=is.read(info))) {
System.out.println(new String(info,0,len));
}

//释放资源
is.close();//此处的close是一个空命令,两台计算机之间不需要释放资源
}

}

在写出操作的时候,与文件输出流不同的是:字节输出流没有和写出的目标位置相关联,而是直接将内容写进字节数组输出流中,然后使用字节数组输出流将内容转化为字节数组,并返回给目标位置。

二、处理流

1、基本类型 + String 保留数据+类型

输入流:DateInputStream readXxx

输出流:DateOutputStream writeXxx

在之前的IO流中,我们仅仅是将字符相关的信息保存在了相应的文件中,却没有注意各个保存的内容参数的类型,比如int,double,float,long,String等等,那么这样的保存,在我们后期的调用相关数据时,难以快速确定各个参数的类型,所以会降低效率。现在使用DateInputStream和DateOutputStream时,就可以有效的避免这样的问题。保存数据的时候,同时保存数据相对应的类型。

例如下面的实例:

代码语言:javascript
复制
package com.peng.IO.others;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * 数据类型(基本类型+String)处理流
 * 在保存时,同时保存数据以及其对应的数据类型
 */
public class DataDemo2 {

public static void main(String[] args) throws IOException {
byte[] data = write();
read(data);
System.out.println(data.length);
}

/**
 * 数据+类型   从字节数组中读取
 * @throws IOException 
 */
public static void read(byte[] src) throws IOException {

//选择流
//选择字节输入流
InputStream is = new ByteArrayInputStream(src);
DataInputStream dis = new DataInputStream(
new BufferedInputStream(
is
)
);

//操作 读取的顺序必须与写出的顺序一致 必须存在才能读取
double point = dis.readDouble();
long num = dis.readLong();
String str = dis.readUTF();
System.out.println(point+"--->"+num+"--->"+str);
//释放资源
dis.close();
}

/**
 * 数据+类型     输出到字节数组
 * @param destPath
 * @throws IOException 
 */
public static byte[] write() throws IOException {
double point = 2.5;
long num = 100L;
String str = "数据类型";

//创建目的地
byte[] dest = null;

//选择流
//选择字节数组输出流
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(//数据类型处理流
new BufferedOutputStream(//缓冲处理流
bos//建立联系
)
);
//写出的顺序很重要,因为后续在告诉用户的过程中,需要告诉用户第几个参数是什么含义
dos.writeDouble(point);
dos.writeLong(num);
dos.writeUTF(str);
dos.flush();

//获取数据
dest = bos.toByteArray();

//释放资源
dos.close();
return dest;
}

}

在读取最后的写出结果时,可以直接识别出写出的结果是什么类型的,这样就可以大大的提高运行效率。

2、引用类型(对象) 保留数据+类型

反序列化:输入流:ObjectInputStream readObject()

序列化:输出流:ObjectOutputStream writeObject()

注意:

1)先序列化后反序列化;但序列化的顺序必须和序列化的顺序相同

2)不是所有的对象都可以序列化,需要对象实现接口java.io.Serializable

不是对象的所有属性都需要序列化,可以在不需要序列化的属性前面加上修饰符transient

例如:

1)创建Employee类,实现接口java.io.Serializable,同时利用transient修饰属性name,使得name不进行序列化。

代码语言:javascript
复制
package com.peng.IO.others;
/**
 * 空接口只是一个标识
 *
 */
public class Employee implements java.io.Serializable{//此处是一个空接口
//transient表示该属性不需要序列化
private transient String name;
private double salary;

public Employee(String name, double salary) {
super();
this.name = name;
this.salary = salary;
}
public Employee() {

}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}

}

2)对Employee对象进行序列化写出以及反序列化读取

代码语言:javascript
复制
package com.peng.IO.others;

import java.io.BufferedInputStream;
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.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Arrays;

/**
 * 数据类型(不仅限于基本数据类型,可以为引用数据类型,对象)处理流
 * 1、序列化------>写出  ObjectOutputStream
 * 2、反序列化----->读取 ObjectInputStream
 * 
 * 不是所有的对象都可以序列化 java.io.NotSerializableException
 * 不是所有的属性都需要序列化 transient
 *
 */
public class ObjectDemo01 {

public static void main(String[] args) throws IOException, ClassNotFoundException {
seri("E:\\java学习\\test\\seri.txt");
read("E:\\java学习\\test\\seri.txt");
}
//反序列化  读取
public static void read(String srcPath) throws FileNotFoundException, IOException, ClassNotFoundException {
//创建源
File src = new File(srcPath);
//选择流 ObjectInputStream
ObjectInputStream ois = new ObjectInputStream(
new BufferedInputStream(
new FileInputStream(src)
)
);

//操作
Object obj = ois.readObject();
if (obj instanceof Employee) {
Employee temp = (Employee) obj;
System.out.println(temp.getName());
System.out.println(temp.getSalary());
}

Object obj1 = ois.readObject();
int[] arr = (int[]) obj1;
System.out.println(Arrays.toString(arr));

//释放资源
ois.close();
}


//序列化  写出
public static void seri(String destPath) throws FileNotFoundException, IOException {
Employee temp = new Employee("鹏程万里",1000);
int[] arr = {1,2,3,4,5};
//创建源
File dest = new File(destPath);

//选择流ObjectOutputStream
ObjectOutputStream dos = new ObjectOutputStream(
new BufferedOutputStream(//缓冲流
new FileOutputStream(dest)//节点流
)
);

dos.writeObject(temp);
dos.writeObject(arr);
dos.flush();
dos.close();

}

}

3)查看结果

代码语言:javascript
复制
null
1000.0
[1, 2, 3, 4, 5]

由于我们使用了transient对Employee对象的name属性进行了修饰,所以在反序列化(读取)的时候,并没有输出Employee对象的name属性。

注意:

1)数组也属于一个对象,所以在序列化的时候,可以将数组也作为一个对象进行序列化和反序列化。

2)在反序列化(读取)时,读取的顺序必须与序列化(写出)的顺序相同,所以在写出的时候,需要注意写出的对象的顺序,避免后期读取的时候报错。

3)写出的文件内容是给计算机查看的内容,保留有各个属性的类型,所以我们查看路径“E:\java学习\test\seri.txt”的内容时,所看到的是一堆乱码。如下图所示:

三、打印流

1、在java编程中,我们经常使用System.out.println()命令,将我们想要看到的变量打印在控制台上,便于我们看到变量的具体内容。而System.out.println()命令也属于IO流中的一种,也属于处理流中的一种。打印流的使用方法,也和其他的处理流的使用方法相同:

代码语言:javascript
复制
package com.peng.IO.others;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;

/**
 * PrintStream  打印流---->处理流
 */
public class PrintStreamDemo01 {
public static void main(String[] args) throws FileNotFoundException {
System.out.println("test");
PrintStream ps = System.out;
ps.println(false);
//输出到文件
File src = new File("E:\\java学习\\test\\print.txt");
ps = new PrintStream(//处理流
new BufferedOutputStream(//缓冲流
new FileOutputStream(src)//节点流--- 字节流
)
);
ps.println("peng is very good");
ps.flush();
ps.close();
}

}

通过上面的代码可以看出来,打印流(PrintStream)使用的是其自己的方法println方法,将字符串写出到目标文件中。

2、在打印流中,有几个基本的知识点这里提一下:

1)三个常量:

  • System.in 输入流-----键盘输入
  • System.out 输出流-----控制台输出
  • System.err 输出流-----控制台输出 其中,System.out和System.err的功能完全相同,都是将相应的提示信息输出到控制台上,唯一的差别就是在控制台上输出的信息的字体颜色不同,System.out输出到控制台上的字体颜色默认为黑色,而System.err输出到控制台上的字体颜色默认为红色。

2)重定向

由于在上述的三个常量,默认的输入与输出都是在控制台上进行,假如用户需要将信息输出到相应的文本文件中,而不是显示在控制台上,那么就需要使用重定向,将其输入与输出的位置进行重新关联。

例如:

代码语言:javascript
复制
package com.peng.IO.others;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.PrintStream;
import java.util.Scanner;

public class SystemDemo01 {

public static void main(String[] args) throws FileNotFoundException {
test();
}

public static void test() throws FileNotFoundException {
//重定向
System.setOut(new PrintStream(//本质上还是一个输出流 ---- 处理流
new BufferedOutputStream(
new FileOutputStream(
new File("E:/java学习/test/print.txt")
)
),true
)
);
//此时的输出已经不在控制台中了,将所需要输出的字符输出到指定的文件中
System.out.println("test");//控制台----->文件
System.out.println("one produce two, two produce three,three produce all things.");

//重新回到控制台
System.setOut(new PrintStream(
new BufferedOutputStream(
new FileOutputStream(
FileDescriptor.out
)
),true
)
);
System.out.println("back.........");
}

}

重定向主要使用三条命令进行实现:SetIn();SetOut();SetErr(),三条命令分别设定输入,输出,以及输出错误信息的位置。

控制台的目标位置同样使用三条命令进行实现:FileDescriptor.in;FileDescriptor.out;FileDescriptor.err,三条命令分别代表输入,输出和错误信息在返回到控制台上的位置。

四、装饰设计模式

1、类与类之间的关系

1)依赖:形参||局部变量

2)关联:属性

聚合:属性 整体与部分 不一致的生命周期 人与手

组合:属性 整体与部分 一致的生命周期 人与大脑

3)继承:父子类关系

4)实现:接口与实现类的关系

2、IO流中使用的属于装饰设计模式

也就是利用不同的处理流,对节点流进行包装处理。比如在老师讲课的时候,使用扩音器,就属于将老师的讲课声音进行了扩大,对原声进行了装饰。

例如:

1)我们先建立一个声音类

代码语言:javascript
复制
package com.peng.IO.pattern;

public class Voice {
private int voice = 10;
public Voice() {

}
public Voice(int voice) {
super();
this.voice = voice;
}
public int getVoice() {
return voice;
}
public void setVoice(int voice) {
this.voice = voice;
}
public void say() {
System.out.println(voice);
}
}

2)然后建立一个扩音器

代码语言:javascript
复制
package com.peng.IO.pattern;

public class Amplifier {
private Voice voice;
public Amplifier() {

}
public Amplifier(Voice voice) {
super();
this.voice = voice;
}
public Voice getVoice() {
return voice;
}
public void setVoice(Voice voice) {
this.voice = voice;
}
public void say() {
System.out.println(voice.getVoice()*1000);
}
}

3)最后应用一下

代码语言:javascript
复制
package com.peng.IO.pattern;

public class App {

public static void main(String[] args) {
Voice v =new Voice(20);
v.say();
Amplifier am = new Amplifier(v);
am.say();
}
}

最终的结果当然就是我们将声音的数值扩大了1000倍,这就是简单的使用了装饰模式。类比在IO流的使用上,我们依旧是首先利用处理流,使用处理流对缓冲流进行包装,然后再利用缓冲流对节点流或者字符流进行包装,最后实现我们需要的功能。

以上就是本周分享的内容咯!Java小白成长之路!Java小白在这里陪你一起学Java,一起向上奋斗!
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-03-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java小白成长之路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
文件存储
文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档