day-2-1-3

节点流

请添加图片描述

文件节点流

FileInputStream和FileOutputStream是文件字节流,是一种节点流

文件字节输入流的构造方法:

  • FileInputStream(“文件名称”),如果文件不存在则FileNotFoundException
  • FileInputStream(File)

文件字节输出流的构造方法:

  • FileOutputStream(“文件名称”) 如果文件不存在则新建文件,如果文件存在则覆盖文件内容
  • FileOutputStream(String name文件名称, boolean append是否采用追加方式)

FileReader和FileWriter类似

FileInputStream和FileOutputStream两个类属于节点流,第一个类的源端和第二个类的目的端都是磁盘文件,它们的构造方法允许通过文件的路径名来构造相应的流。

如:

FileInputStream infile = new FileInputStream(“myfile.dat”);

FileOutputStream outfile = new FileOutputStream(“results.dat”);

要注意的是,构造FileInputStream, 对应的文件必须存在并且是可读的,而构造FileOutputStream时,如输出文件已存在,则必须是可覆盖的。

练习

要求:将d盘上的TestFile.java拷贝到e盘,并命名为dd.txt

try (InputStream is = new FileInputStream("d:/TestFile.java");
		OutputStream os=new FileOutputStream("e:\\dd.txt");
	) {
		byte[] buffer=new byte[8192];
		int len=is.read(buffer);
		while(len>0){
			os.write(buffer,0,len);
			len=is.read(buffer);
		}
	}catch(IOException e){
		e.printStackTrace();
	}
构造输出文件流时可以使用两种不同的方式
OutputStream os=new FileOutputStream("e:\\dd.txt"); 如果文件不存在则自动创建;如果文件存在则进行覆盖
OutputStream os=new FileOutputStream("e:\\dd.txt",true),这里的boolean类型参数表示是否采用追加的方式写入文件

需求2:设计程序将aa.java和bb.java两个文件合并成一个文件,命名为cc.txt。

try (InputStream in1 = new FileInputStream("E:\\java\\eclipse-workspace\\0803\\src\\demo\\work7.java");
			InputStream in2 = new FileInputStream("E:\\java\\eclipse-workspace\\0803\\src\\demo\\work8.java");
			OutputStream out = new FileOutputStream("E:\\java\\eclipse-workspace\\0803\\src\\demo\\cc.txt",true);) {
		while (true) {
			int k1 = in1.read();
			if (k1 == -1)
				break;
			out.write(k1);
		}
		while (true) {
			int k2 = in2.read();
			if (k2 == -1)
				break;
			out.write(k2);
		}
	}
内存数组节点

如果文本则使用char[],如果二进制则使用byte[]

构造器方法

  • CharArrayReader(char[] buf)其中char[]就是数据的来源,也就是说Reader就是从char[]中读取数据
  • CharArrayRead(char[] buf, int offset, int length)

CharArrayWriter用于实现向一个字符数组中写入数据,这个数组可以自动调整大小

ByteArrayInputStream、ByteArrayOutputStream和CharArrayReader以及CharArrayWriter类似,支持操作的内容不同而已,操作byte[]与char[]

内存字串流

StringReader用于从一个字串String中读取数据

String str="亚洲说:‘我爱小黑’";
StringReader sr=new StringReader(str);
int cc;
while((cc=sr.read())!=-1)
	System.out.print((char)cc);
sr.close();

StringWriter用于给一个StringBuffer中写入数据,实现一个可边长的字串

Scanner sc=new Scanner(System.in);
try(
	StringWriter sw=new StringWriter();
	Writer fw=new FileWriter("c:/console.txt")
){
	String temp=sc.nextLine();
	while(!temp.equals("quit")){
		if(temp!=null && temp.trim().length()>0)
			sw.write(temp+"\n");
		temp=sc.nextLine();
	}
	fw.write(sw.toString());
}
总结
  • 读写文件使用节点流FileInputStream/FileOutputStream和FileReader/FileWriter,如果操作文本 文件,建议使用FileReader/FileWriter,如果操作二进制文件建议使用\

  • FileInputStream/FileOutputStream 需要建立缓冲区(建立临时文件的方式效率低),可以考虑使用内存节点,例如 CharArrayReader/CharArrayWriter、StringReader/StringWriter和 ByteArrayInputStream/ByteArrayOutputStream

  • 如果需要一个二进制缓冲区可以使用ByteArrayInputStream/ByteArrayOutputStream,如果需要 一个字符缓存可以使用CharArrayReader/CharArrayWriter、StringReader/StringWriter

  • 如果数据量不是特别大使用CharArrayReader/CharArrayWriter更为方便,如果数据量大而且可能需要直接操作缓冲区则使用StringReader/StringWriter

  • StringWriter中提供了方法getBuffer():StringBuffer

过滤流类型

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

请添加图片描述

过滤流

就是decorate模式中的抽象装饰角色

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—BufferedReader

​ 写出数据自定义过滤流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是java.io包中用于处理字符流的最基本的类,用来在字节流和字符流之间作为中介:从字节输入流读入字节,并按编码规范转换为字符;往字节输出流写字符时先将字符按编码规范转换为字节。使用这两者进行字符处理时,在构造方法中应指定一定的平台规范,以便把以字节方式表示的流转换为特定平台上的字符表示。

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

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);

注意:一般不建议自行设置编码字符集,除非是必须的

缓冲流

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

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

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

InputStream is = new FileInputStream("d:\\FileTest.java");
long start=System.currentTimeMillis();//获取从1970-1-1 0:0:0到当前的毫米值
int con = is.read();
while (con != -1) {
	System.out.write(con);
	con = is.read();
}
long end=System.currentTimeMillis();
is.close();
System.out.println("统计时间为:"+(end-start)+"ms");

60ms
构造方法
  • BufferedReader(Reader)不定义缓存大小,默认8192

  • BufferedReader(Reader in, int size)size为自定义缓冲区的大小

  • BufferedWriter(Writer) BufferedWriter(Writer out, int size)size为自定义缓冲区的大小

  • BufferedInputStream(InputStream)

  • BufferedInputStream(InputStream in, int size)size为自定义缓冲区的大小

  • BufferedOutputStream(OutputStream) BufferedOutputStream(OuputStream out, int size)size为自定义缓冲区的大小

InputStream is = new BufferedInputStream(new
FileInputStream("d:\\FileTest.java"));
long start=System.currentTimeMillis();
int con = is.read();//这里并不是直接从文件中进行读取,而是从缓存中进行读
while (con != -1) {
	System.out.write(con);
	con = is.read();
}
long end=System.currentTimeMillis();
is.close();
System.out.println("统计时间为:"+(end-start)+"ms");
is.close();
10ms
缓冲输入流的方法

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

  • BufferedReader提供了readLine方法用于读取一行字符串,以\r或\n分割(换行符)
  • 如果读取内容为null,则表示读取到了流的末尾
  • readLine方法会自动剔除本行内容末尾的换行符
  • BufferedWriter提供了newLine方法用于写入一个行分隔符

对于输出的缓冲流,写入的数据会先在内存中缓存,使用flush方法会使内存中的数据立即写出

键盘录入

System.in:InputStream用于指代系统默认的输入设备—键盘

方法read():int 可以实现代码执行到这里则会阻塞等待,只要输入数据为止

练习题

使用java的输入/输出流技术将一个文本文件的内容按行读出,每读出一行就顺序添加行号,并写入 到另一个文件中。

try (BufferedReader br = new BufferedReader(
			new FileReader("E:\\java\\eclipse-workspace\\0803\\src\\demo\\work2.java"));
			BufferedWriter bw = new BufferedWriter(
					new FileWriter("E:\\java\\eclipse-workspace\\0803\\src\\demo\\buffer.txt"))) {
		int c = 0;
		while (true) {
			String k = br.readLine();
			if (k == null)
				break;
			bw.write(++c + " ");
			bw.write(k);
			bw.newLine();
		}
	}

new BufferedReader(new FileReader(…))或new BufferedWriter(new FileWriter())实际上使用的还是Reader/Writer那些方法,这里从编码的角度上说,没有任何区别,但是从执行性能上说,比 FileReader/Writer效率高,可以减少磁盘的读写次数

数据流

DataInputStream和DataOutputStream两个类创建的对象分别被称为数据输入流和数据输出流。这是很有用的两个流,它们允许程序按与机器无关的风格读写Java数据。所以比较适合于网络上的数据传输。这两个流也是过滤器流,常以其它流如InputStream或OutputStream作为它们的输入或输出

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值