流类型—上

今日总结:
今天学习了过滤流类型等流类型

过滤流类型

过滤流就是在节点流的基础上附加功能

在这里插入图片描述

过滤流

FilterInputStream/FilterOutputStream和FilterReader/FilterWriter

public class FilterInputStream extends InputStream { //典型的装饰模式
protected volatile InputStream in; //被装饰目标
protected FilterInputStream(InputStream in) { //通过构造器组装被装饰对象
this.in = in;
}
public int read() throws IOException {//调用Filter中的read方法时实际操作是由被装饰对象实现return in.read();
}
}

所谓的过滤流实际上就是类似上面的加密处理,在输入之后(后置处理,被装饰对象先执行)或者输出之前(前置处理,先处理然后被装饰对象执行)进行一下额外的处理,最终实际操作是调用被装饰对象的方法完成工作,依靠这种装饰模式实现在节点流的基础上附加额外功能.当然也允许多个过滤流嵌套从而达到功能累加的目的
FilterInputStream实际上就是一个装饰抽象角色
自定义流实现循环13加密:
读取数据不变:FileReader—BueredReader
写出数据自定义过滤流SecurityWriter(FilterWriter)

public class SecurityWriter extends FilterWriter {
protected SecurityWriter(Writer out) {
super(out);
}
public void write(int c) throws IOException {
if (c >= 'a' && c <= 'z') {
c = (c - 'a' + 13) % 26 + 'a';
} else if (c >= 'A' && c <= 'Z') {
c = (c - 'A' + 13) % 26 + 'A';
}
super.write(c);
}
}
public class SecurityReader extends FilterReader {
protected SecurityReader(Reader in) {
super(in);
}
public int read() throws IOException {
int c = super.read();
if (c >= 'a' && c <= 'z') {
c = (c - 'a' + 13) % 26 + 'a';
} else if (c >= 'A' && c <= 'Z') {
c = (c - 'A' + 13) % 26 + 'A';
}
return c;
}
}

桥接转换流

InputStreamReader和OutputStreamWriter提供了字节流和字符流之间的桥接转换功能,用于与字节数据到字符数据之间的转换,无需编程实现将字节拼接为字符

转换流可以在构造时指定其编码字符集

InputStreamReader用于将一个InputStream类型的输入流自动转换为Reader字符流

OutputStreamWriter用于将一个Writer字符输出流转换为OutputStream字节输出流

InputStreamReader构造器

InputStreamReader(InputStream)
InputStreamReader(InputStream, String)
InputStreamReader(InputStream, Charset)
InputStreamReader(InputStream, CharsetDecorder)

Reader r=new InputStreamReader(System.in);
int kk=r.read(); //例如输入的是“中国”,这里实际读取的是"中"
//因为这里读取的是一个字节,所以输入"中国",实际读取的是"中"的一个字节,输出显示为?
kk=System.in.read();
System.out.println("输入的是:"+(char)kk);

InputSteram is=new InputStreamReader(System.in,”iso8859-1”);

Reader r=new InputStreamReader(System.in, "gbk");
int kk=r.read(); //例如输入的是"中国",实际读取的是"中"
System.out.println("输入的是:"+(char)kk);

注意:一般不建议自行设置编码字符集,除非是必须的
在这里插入图片描述

缓冲流

缓冲流是套接在响应的节点流之上,对续写的数据提供缓冲的功能,提高读写的效率,同时增加了一些新方法

以介质是硬盘为例,字节流和字符流的弊端:在每一次读写的时候,都会访问硬盘。 如果读写的频率比较高的时候,其性能表现不佳。为了解决以上弊端,采用缓存流。

缓存流在读取的时候,会一次性读较多的数据到缓存中,以后每一次的读取,都是在缓存中访问,直到缓存中的数据读取完毕,再到硬盘中读取。

构造方法

BueredReader(Reader)不定义缓存大小,默认8192
BueredReader(Reader in, int size)size为自定义缓冲区的大小
BueredWriter(Writer)
BueredWriter(Writer out, int size)size为自定义缓冲区的大小

BueredInputStream(InputStream)
BueredInputStream(InputStream in, int size)size为自定义缓冲区的大小
BueredOutputStream(OutputStream)
BueredOutputStream(OuputStream out, int size)size为自定义缓冲区的大小

缓冲输入流的方法

BuedReader提供了一个方法readLine():String,但是BueredInputStream中并没有这个

BueredReader提供了readLine方法用于读取一行字符串,以\r或\n分割(换行符)

  • 如果读取内容为null,则表示读取到了流的末尾
  • readLine方法会自动剔除本行内容末尾的换行符

BueredWriter提供了newLine方法用于写入一个行分隔符
对于输出的缓冲流,写入的数据会先在内存中缓存,使用ush方法会使内存中的数据立即写出

键盘录入

System.in:InputStream用于指代系统默认的输入设备—键盘
方法read():int 可以实现代码执行到这里则会阻塞等待,只要输入数据为止

BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
System.out.println("输入数据");
String temp="";
while((temp=br.readLine()).trim().length()>0){
if("quit".equals(temp)) break;
System.out.println(temp);
}
br.close();
BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(System.out));
bw.write("只有缓冲区满才自动进行输出显示");
bw.flush(); //刷新缓冲区,否则看不到输出内容
System.in.read();
bw.close(); //关闭输出时会首先自动进行刷新缓冲区

数据流

DataInputStram和DataOutputStream分别继承自InputStream和OuputStream,属于过滤流,需要分别套接在InputStream和OutputStream类型的节点流上

  • 只有字节流,没有对应的字符流

DataInputStream和DataOutputStream提供了可以存取与机器无关的Java原始类型数据的方法
DataInputSteram和DataOutputStream构造方法为

  • DataInputStream(InputStream)
  • DataOutputStream(OutputStream)

读取、写出一个double数据到文件中

//使用数据流就可以直接操作简单类型数据
double dd=123.4567;
FileOutputStream fos=new FileOutputStream("d:\\a.data");
fos.write((dd+"").getBytes());
fos.close();
//如果不使用数据流,则需要额外编码进行数据类型转换
FileInputStream fis=new FileInputStream("d:/a.data");
byte[] buffer=new byte[8192];
int len=fis.read(buffer);
fis.close();
String str=new String(buffer,0,len);
double dd=Double.parseDouble(str);
System.out.println(dd);

加入需要写一个double,然后一个String,然后再一个int

需要将输入内容转换为String,并且为了区分数据需要引入特殊符号,例如@@,输入数据为123.456@@shi yazhou@@12。从功能角度上说没问题,但是编码太复杂了,所以引入Data类型的输入输出流

//这里不使用OutputStream定义变量的原因是:需要使用DataOutputStream中定义的特殊方法,而不是父类中
定义的通用方法
DataOutputStream dos=new DataOutputStream(new FileOutputStream("d:\\a.data"));
dos.writeDouble(123.456);
dos.writeChars("赵天爱小猴!");
dos.writeInt(12);
dos.close();

由于读取出现问题,针对中间的String数据引入一个额外的数据,其中存储String的char个数写出数据

double salary=123.456;
String ss="赵天爱小猴,小猿爱小主,小胡招小天";
int age=12;
DataOutputStream dos=new DataOutputStream(new BufferedOutputStream(new
FileOutputStream("d:\\aa.data")));
dos.writeDouble(salary);
dos.writeInt(ss.length());
dos.writeChars(ss);
dos.writeInt(age);
dos.close();

读取数据

double salary=0;
String str="";
int age=0;
//读取数据的前提是必须知道数据的结构
DataInputStream dis=new DataInputStream(new BufferedInputStream(new
FileInputStream("d:\\aa.data")));
salary=dis.readDouble();
StringBuilder sb=new StringBuilder();
int len=dis.readInt();
for(int i=0;i<len;i++) sb.append(dis.readChar());
str=sb.toString();
age=dis.readInt();
System.out.println(salary+"---"+str+"---"+age);

注意:读取数据判断文件结束EOFException,这里没有-1
在具体应用中建议针对字串使用readUTF和writeUTF

DataOutputStream dos=new DataOutputStream(new FileOutputStream("data2.txt"));
dos.writeDouble(1234.56);
String str="猴子愛小終,小終愛信心";
dos.writeUTF(str);
dos.writeInt(99);
dos.close();
DataInputStream dis = new DataInputStream(new FileInputStream("data2.txt"));
double d1 = dis.readDouble();
String ss=dis.readUTF();
int kk = dis.readInt();
System.out.println(d1 + "\t" + ss + "\t" + kk);
dis.close();

练习:编写一个程序实现以下功能:
(1)产生5000个1~9999之间的随机整数,将其存入二进制数据文件a.data中。
(2)从文件中读取所有整数(文件中都是整数,但是个数未知),并计算其最大值、最小值和平均值并输出结果。

import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.Random;

public class B1 {
	public static void main(String[] args) throws Exception {
		DataOutputStream dos=new DataOutputStream(
				new BufferedOutputStream(new FileOutputStream("a.data")));
		Random r=new Random();
		for (int i = 0; i < 5000; i++) {
			int kk=1+r.nextInt(100)+1;
			dos.writeInt(kk);
		}
		dos.close();
	}
}

public class B2 {
	public static void main(String[] args) throws Exception {
		DataInputStream dis=new DataInputStream(
				new BufferedInputStream(new FileInputStream("a.data")));
		int max=Integer.MIN_VALUE;
		int min=Integer.MAX_VALUE;
		int counter=0;//统计整数的个数
		int sum=0;
		while (true) {
			try {
				int kk=dis.readInt();
				sum+=kk;
				if (kk>max) {
					max=kk;
				}
				if (kk<min) {
					min=kk;
				}
				counter++;
				System.out.println(kk);
			} catch (Exception ex) {
				break;
			}
		}
		dis.close();
		System.out.println("最大值为:"+max+",最小值为:"+min
				+",平均值为:"+(sum/counter));
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值