Java核心库——IO(二)

文件的字节流:
FileInputStream
FileOutputStream
当我们学习完了文件的字节流,就可能会考虑,既然有了字节流了,为什么还要文件字符流呢?
我们来看这样一个操作,对如下的一个文件进行拷贝操作,每5个字节进行一次读取到buffer中.并且在程序中输出拷贝结果
这样一个文本文件:
进行读取5个字节,然后拷贝一次.
public class FileInputStreamDemo{
 public static void main(String[] args) throws IOException {
	File f = new File("file/Stream.txt");
	
	FileInputStream in = new FileInputStream(f);
	byte[] buffer = new byte[5];
	System.out.println(Arrays.toString(buffer));
	int len = -1;
	while( (len = in.read(buffer))!=-1){
		String str= new String(buffer,0,len);
		System.out.println(str);
	}
	in.close();

 }


但是这里就出现问题了,因为一个汉字占两个字节,拷贝不完整的时候输出如下
使用字节流操作汉字或者特殊的符号语言的时候,容易乱码,建议使用字符流
先有字节流,后有字符流,字符流是对字节流的补充
使用记事本打开某个文件,可以看到文件的内容的就是文本文件,否则可以理解二进制
一般的,操作二进制文件 (图片,音频,视频等)必须使用字节流
操作文文件使用字符流
如果不清楚是哪一类文件, 使用字节流
-----------------------------------------------
文件的字符流:
FileReader
FileWriter

流的分类,从不同角度,有不同的分类:
从流向上分,有输入流和输出流
从单位上分,有字节流和字符流
从功能上分,有节点流和包装流

处理流/包装流相对于节点流更高级:
1.隐藏了底层节点流的差异,并对外提供了方便的输入/输出功能,让我们只 关心高级流的操作
2.使用处理流包装了节点流程序直接操作处理流,让节点流与底层的设备io交流
3.只需要关闭处理流即可
包装流如何区分:
创建对象的时候需要传递另一个流对象
new 包装流(其他流对象)
------------------------------------------------
缓冲流:
是一个包装流,起缓冲作用
BufferedInputStream
BufferedOutputStream
BufferedReader
BufferedWriter
提供的默认缓冲区大小是 1024*8=8192个字节/字符,一般不用修改这个大小
缓冲流的作用:
操作流的时候,习惯定义一个char/byte数组
int read()每次都从磁盘文件中读取一个字节,直接操作磁盘文件性能极低。
没有经过Buffered处理的IO, 意味着每一次读和写的请求都会由OS底层直接处理,这会导致非常低效的问题。
解决方法:定义一个数组作为缓冲区
byte[] a = new byte[ 1024 ];该数组其实就是一个缓冲区
一次性从磁盘文件中读取1024个字节,如此一来,磁盘文件的操作次数少了————性能得以提升
经过Buffered处理过的输入流将会从一个buffer内存区域读取数据,本地API只会在buffer空了之后才会被调用(可能一次调用会填充很多数据进buffer)。
经过Buffered处理过的输出流将会把数据写入到buffer中,本地API只会在buffer满了之后才会被调用。

//比较节点流和缓冲流的方式的效率比较
public class BufferedStreamvsNodeStreamDemo {
	public static void main(String[] args) throws IOException {
		File srcfile = new File("file/伯乐油画体.ttf");
		File desfile = new File("target/ziti.ttf");
		// test1(srcfile, desfile);使用节点流从磁盘文件一个一个字节读取
		// test2(srcfile, desfile);
		//test3(srcfile, desfile);
		test4(srcfile, desfile);
	}
	//使用缓冲流,一次从磁盘文件读取1024个字节
	private static void test4(File srcfile, File desfile) throws IOException {
		long begin = System.currentTimeMillis();
		BufferedInputStream in = new BufferedInputStream(new FileInputStream(srcfile));
		BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(desfile));
		byte[] bu = new byte[1024];
		int len = -1;
		while ((len = in.read(bu)) != -1) {
			out.write(len);
		}
		in.close();
		out.close();
		System.out.print("使用缓冲流的方式,一次读取1024byte:\n");
		System.out.println(System.currentTimeMillis() - begin);
		
	}

	//使用节点流,一次从磁盘文件读取1024个字节
	static void test3(File srcfile, File desfile) throws IOException {

		long begin = System.currentTimeMillis();
		FileInputStream in = new FileInputStream(srcfile);
		FileOutputStream out = new FileOutputStream(desfile);
		byte[] bu = new byte[1024];
		int len = -1;
		while ((len = in.read(bu)) != -1) {
			out.write(len);
		}
		in.close();
		out.close();
		System.out.print("使用节点流,一次从磁盘文件读取1024个字节:\n");
		System.out.println(System.currentTimeMillis() - begin);

	}

	// 使用缓冲流从文件一个一个字节读取
	static void test2(File srcfile, File desfile) throws IOException {
		long begin = System.currentTimeMillis();
		BufferedInputStream in = new BufferedInputStream(new FileInputStream(srcfile));
		BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(desfile));

		int len = -1;
		while ((len = in.read()) != -1) {
			out.write(len);
		}
		in.close();
		out.close();
		System.out.print("使用缓冲流的方式:");
		System.out.println(System.currentTimeMillis() - begin);
	}

	// 使用节点流从磁盘文件一个一个字节读取
	static void test1(File srcfile, File desfile) throws IOException {
		long begin = System.currentTimeMillis();
		FileInputStream in = new FileInputStream(srcfile);
		FileOutputStream out = new FileOutputStream(desfile);
		int len = -1;
		while ((len = in.read()) != -1) {
			out.write(len);
		}
		in.close();
		out.close();
		System.out.print("使用节点流的方式:");
		System.out.println(System.currentTimeMillis() - begin);
	}
}


节点流的方式:
使用缓冲流的方式:
使用节点流,一次从磁盘文件读取1024个字节:
使用缓冲流的方式,一次读取1024byte:
-----------------------------------------------

转换流:把字节流转换为字符流
InputStreamReader:把字节输入流转换为字符输入流
OutputStreamReader:把字节输出流转换为字符输出流

为什么只有字节流转为字符流,没有字符流转为字节流:
字节流可以操作一切文件,包括纯文本文件和二进制文件;字符是用来操作中文文本使用的,本身是对字节流的一个增强。
public class TransferDemo {
	public static void main(String[] args) throws IOException {
		File src = new File("file/Stream.txt");
		File des = new File("file/Stream_copy.txt");		
		InputStreamReader ir = new InputStreamReader(new FileInputStream(src),"GBK");
		OutputStreamWriter ow = new OutputStreamWriter(new FileOutputStream(des),"GBK");
		int len = -1;
		
		//操作字符流
		char[] buffer= new char[1024];
		while((len = ir.read(buffer))!=-1){
			ow.write(buffer,0,len);
		}
		ir.close();
		ow.close();
		
	}
}

内存流(数组流):
把数据先临时存在数组中,待会儿再从数组中取出来:
(1):字节内存流 ByteArrayInputStream/ByteArrayOutputStream
(2):字符内存流
(3):字符串流

字节内存流
public class ByteArrayDemo {
	public static void main(String[] args) throws IOException {
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		bos.write("ABCDE".getBytes());
		//要使用存储的临时数据
		byte[] buffer = bos.toByteArray();
		
		//字节数组输入流:内存->程序
		ByteArrayInputStream bis = new ByteArrayInputStream(buffer);
		
		byte[] bys= new byte[5];
		int len = -1;
		while((len =bis.read(bys)) !=-1){
			System.out.println(new String(buffer,0,len));			
		}
		bis.close();
	}
}



字符串
public class StringWriterReaderDemo {
	public static void main(String[] args) throws IOException {
		//字符串的输出流
		StringWriter sw = new StringWriter();
		sw.write("hello");
		System.out.println(sw.toString());
		
		//字符串输入流:内存->程序
		StringReader sr = new StringReader(sw.toString());
		char[] buffer =new char[1024];
		int len = -1;
		while((len =sr.read(buffer))!=-1){
			System.out.println(new String(buffer,0,len));			
		}
		sr.close();
	}
}


另外还有一个合并流的概念:
合并流(sequenceInputStream):
就是把多个输入流合并成一个流对象
public class SequenceInputDemo {
	public static void main(String[] args) throws IOException {
		//创建顺序流对象
		SequenceInputStream sis = new SequenceInputStream(new FileInputStream("file/Stream.txt"), new FileInputStream("file/Stream_copy.txt"));
		
		byte[] buffer = new byte[1024];
		int len = -1;
		while( (len = sis.read(buffer)) != -1){
			System.out.println(new String(buffer,0,len));
		}
		sis.close();
	}
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值