java 第十章 输入与输出技术

第十章 输入与输出技术
序言:
1,输入input:程序从外部系统获得数据。读取。
2,输出output:程序将数据输出到外部系统。写入。

10.1 基本概念和I/O入门:

10.1.1数据源:
数据源data source:提供数据的原始媒介。
分为:
源设备:为程序提供数据,一般对应输入流。 
目标设备:程序数据的目的地,一般对应输出流。 

10.1.2流的概念
流stream  数据源source 数据information 程序 program 目的地dest 
1,Java中对文件的操作是以流的方式进行的,
	流是Java内存中的一组有序数据序列 
	数据从源读入到内存中,形成流,这些流可以写入到另外的目的地。
	称为流是因为,这个数据序列在不同时刻操作的源的不同部分。
	
	数据源:水箱 。流:水管中流动的水。程序:最终用户。

	输入/输出的划分相对于程序而言。 
	输入流: 
	通过  流  将  数据源  中的  数据  输送到  程序  中。  
	
	输出流:
	通过  流  将  程序  中的  数据 输送到  数据源  中。

10.1.3第一个简单的I/O流程序
	程序读取数据源的数据时,会通过一个I/O流对象开启一个通向数据源的流,
	通过这个I/O流对象的相关方法,可以顺序读取数据源中的数据。
	try{
	//创建输入流 
	FileInputStream fis = new FileInputStream("d:/文件名.文件格式");
	//一个字节一个字节的读取: 
	int s1 = fis.read();
	System.out.println(s1);
	//对象流使用完必须关闭:
	fis.close();
	}catch(Exception e){
		e.printStackTrace;
	} 
	
	实际开发中根本不知道文件内容,在读取的时候需要结合while循环语句使用。
	为了保证出现异常后流的正常关闭,通常需要将流的关闭语句放到finally语句块中,
	并且要判断流是不是null.
	
	I/O流的经典写法:
	public static void main(String[] args){
		FileInputStream fis = null;
		try{
			fis = new FileInputStream("d:/文件名.文件格式")
			StringBuilder sb = new StringBuilder();
			int temp = 0;
			//当temp=-1时代表已经到了文件结尾,停止读取
			while((temp = fis.read() !=-1){
				sb.append((char) temp);
			} 
			System.out.println(sb);
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			try{
				//这种写法保证了即使遇到异常状况,也会关闭流对象。 
				fis.close(); 
			}catch(IOException e){
				e.printStackTrace();
			}
		}
	} 

10.1.4 java中流的概念细分
	1,按流的方向分:
		输入流:数据源-->程序。以InputStream,Reader结尾的流。 
		输出流 :程序-->目的地。以OutputStream,Writer结尾的流。
	
	2,按处理的数据单元分类:
		字节流:以字节为单位获得数据。
		命名上以Stream结尾的流一般是字节流,FileInputStream,FileOutputStream. 
		
		字符流:以字符为单位获得数据 
		命名上以Reader/Writer结尾的流一般是字符流,FileReader,FileWriter.
	
	3,按处理对象不同分类:
		节点流:直接从数据源或目的地读写数据。 
		FileInputeStream,FileReader,DateInputeStream.
		 
		处理流/包装流:不直接连接到数据源或目的地,是处理流的流,
				通过对其他流处理提高程序的性能。 
		BufferedInputStream,BufferedReader.
	
	节点流处于I/O流的一线,所有操作必须通过他们进行,
	处理流可以对节点流进行包装,提高性能或提高灵活性。 
		
10.1.5 Java中I/O流类的体系
	1,I/O流体系总结
	InputStream&OutputStream:
	字节流的抽象类。
	
	Reader&Writer:
	字符流的抽象类。
	
	FileInputeStream&FileOutputStream:
	节点流,以字节为单位直接操作文件。
	
	ByteArrayInputStream&ByteArrayOutputStream:
	节点流,以字节为单位,直接操作字节数组对象。

	ObjectInputStream&ObjectOutputStream:
	处理流,以字节为单位直接操作对象。
	
	DateInputStream&DateOutputstream:
	处理流,以字节为单位直接操作基本数据类型和字符串数据类型
						
	FileReader&FileWriter:
	节点流,以字符串为单位,直接操作文本文件(只能读写文本文件)。
								
	BufferedReader&BufferedWriter:
	处理流,将Reader/Writer对象进行包装,增加缓存功能,提高读写效率。
								
	BufferedInputStream&BufferedOutputStream:
	处理流,将InputStream/Outputstream队形进行包装,增加缓存功能,提高读写效率。
			
	InputStreamReader&OutputStreamWriter:
	处理流,将字节流对象转换成字符流对象.
	
	PrintStream:
	处理流,将OutputStream进行包装,可以方便的输出字符,更加灵活。
	 
10.1.6 四大I/O抽象类
	InputStream&OutputStream和Reader&Writer是所有I/O流的抽象父类。
	1,InputStream
		该抽象类表示字节输入流的所有类的父类,抽象类不可以实例化,
		数据的读取由其子类来实现。
		继承自InputStream的流都是用于向程序中输入数据,且数据的单位为字节(8bit)。 
		
		常用方法:
		int read():读取一个字节数据,并将字节的值以int类型返回,未读出返回-1.
		void close():关闭输入流对象,释放相关系统资源。
		 
	2,OutputStream
		该抽象类表示字节输出流的所有类的父类,抽象类不可以实例化,
		输出流接收输出字节,并将这些字节发送到某个目的地。
		
		常用方法:
		void write(int n):向目的地中写入一个字节。
		void close(); 关闭输入流对象,释放相关系统资源。
		
	3,Reader
		读取字符流抽象类,数据单位为字符。
		int read():读取一个字符数据,并将字符的值作为int类型返回。未读出返回-1.
		void close(); 关闭输入流对象,释放相关系统资源。 
		
	4,Writer 
		写入字符流抽象类,数据单位为字符。
		void writer(int n):向输出流中写入一个字符。
		void close(); 关闭输入流对象,释放相关系统资源。

10.2 常见流详解
10.2.1 文件字节流: FileInputStream&FileOutputStream
FileInputStream通过字节方式读取文件,适合读取所有类型文件。
FileOutputStream通过字节方式写数据到文件中,适合所有类型文件。

	//字符串/字节数组内容写入到文件中 
	直接写入一个字节数组 
	void write(byte[] b) 
	指定从哪个位置开始写,写入长度是多少 
	void write(byte[] b,int off,int length) 
		
	//利用文件流实现文件复制
	//将a.text内容,复制到b.text 
	copyFile("d:/a.text","d:/b.text"); 
	
	使用文件字节流注意:
		1,为了减少对硬盘的读写次数,提高效率,通常设置缓存数组。
			读取使用的方法为:read(byte[] b);
			写入使用方法为:write(byte[] b,int off,int length) ;
		2,程序中如果遇到多个流,每个流都到单独关闭,防止其中一个流出现异常后,
			导致其他流无法关闭的情况。 
	
10.2.2 文件字符流:FileReader&FileWriter 
	1,字节流不能很好的处理Unicode字符,经常出现乱码现象。
	   处理文本文件时,一般可以使用文件字符流,他以字符为单位。
	    
10.2.3 缓冲字节流:BufferedIntputStream&BufferedOutputStream 
		BufferedIntputStream&BufferedOutputStream通过内部缓存数组提高操作流的效率。 
	1, java缓冲流本身不具备I/O流的读取与写入功能,他在节点流或处理流上加上
		缓冲功能以提高效率。缓冲流是一种处理流/包装流。
		缓冲流对数据源能够频繁高效读写。
		缓冲流先将数据缓存起来,当缓存区满或手动刷新时,一次性将数据读取到程序或写入目的地。
	
	2,使用注意:
		1,关闭流时应先关闭最外层包装流,"后开启的先关闭"。
		2,缓存区默认大小8192字节,也可以使用其他构造器来指定大小。
		 
10.2.4 缓冲字符流:BufferedReader&BUfferedWriter 
	1,	增加了缓存机制,提高了读写文本的效率,
		提供按行读取的方法 readLine().处理文本时可以使用缓冲字符流
	
	2,使用注意:
		readLine();方法是BufferedReader特有的方法。
		写入一行后要使用newLine()方法换行。 
		 
10.2.5 字节数组流:ByteArrayInputStream&ByteArrayOuptStream 
	1, 用在需要流和数组之间转换的情况。
		FileInputStream把文件当作数据源。
		ByteArrayInputStream把内存中的"某个字节数组对象"当作数据源。
		 
10.2.6 数据流:DateInputeStream&DateOutputStream 
	1, 数据流将"基本数据类型和字符串数据类型"作为数据源,
		从而允许程序以与机器无关的方式从底层输入/输出流中
		操作Java基本数据类型与字符串类型。
		他可以对其他节点流或处理流进行包装,增加更灵活,高效的功能。
	
	2,使用数据流时,读取顺序一定要与写入顺序一致,否则不能正常读取数据。 
	
10.2.7 对象流:ObjectInputStream&ObjectOutputstream
	1,对象流以"对象为数据源",但必须对传输的对象进行序列化或反序列化操作。
	
	2,对象流可以读写对象和基本数据类型。
		使用对象流读取对象时,该对象必须经过序列化与反序列化。
		系统提供的类(eg:date)已经实现了序列化接口,自定义类必须手动实现序列化接口。
		 
10.2.8 转换流:InputeStreamReader&OutputStreamReader
	1,实现将字节流转换成字符流.
	
	2,使用场景
		System.in是字节流对象,代表键盘的输入 ,如果按行接收用户的输入,
		就必须用到缓冲字符流BufferedReade特有的方法readLine()。经过观察可以发现,
		创建BufferedReader方法的构造器的参数必须是一个Reader对象,这时就可以用上
		转换流InpuStreamReader.
		 
		System.out是字节流对象,代表输出到显示器。按行读取用户的输入,
		并且 将读取的一行字符串直接显示再控制台时,需要使用字符流的write(String str)方法。
		所以要使用OutputStreamWriter将字节流转换为字符流。 
	
10.2.9 随意访问文件流:RandomAccessFile
	1,作用:
		实现一个文件的读和写。
		可以访问文件的任意位置。
	2,该流需要掌握的三个核心方法
		1,RandonAccessFile(String name,String mode);
			name用于确定文件。
			mode取r(读)或rw(可读写),通过mode可以确定流对文件的访问权限。
	
		2,seek(long a);用于定位流对象读写文件的位置。
			a确定读写位置距离文件开头的字节数。
		
		3,getFilePointer();用于获取流的当前读取位置。 

10.3 java对象的序列化与反序列化
对象的本质是用于组织和存储数据,对象本身也是数据。
对象存储到硬盘文件中,对象通过网络传输到另外一台电脑。
通过序列化和反序列化实现。
10.3.1 序列化话和反序列化是什么
1,两个进程进行远程通信时以二进制序列的形式在网络上传送。
通过HTTP协议发送字符串信息,也可以在网络上直接发送Java对象。
发送方 将Java对象转化为字节序列(对象的序列化) 才能在网络上传送。
接收方 将字节序列恢复为Java对象(反序列化) 才能正常读取。

	2,对象序列化的作用
		1,持久化:把对象的字节序列永久保存到硬盘上,通常存放在一个文件中。
			eg:休眠的实现,服务器seccion的持久化,hibernate持久化对象。
			 
		2,网络通信:在网络上传送对象的字节序列。
			eg:服务器之间数据通信,对象传递。 
	 
	
10.3.2 序列化涉及的类和接口
	1,ObjectOutputStream对象输出流,
		其writeObject(Object obj)方法可对参数指定的obj对象进行序列化,
		将得到的字节序列写到一个目标输出流中。 
	
	2,ObjectInputStream对象输入流 :
		其readObject()方法可以从一个源输入流中读取字节序列,
		再将其反序列化为一个对象并返回。 
	
	3,只有实现Serializable接口的类的对象才能被序列化,
		Serializable接口是一个空接口,只起标记作用。
		 
10.3.3 序列化与反序列化的步骤和实现
	static属性不参与序列化。
	对象中不想被序列化的属性应使用transient,不能使用static。
	为了防止读和写的序列化ID不一致,一般指定一个固定的序列化ID. 

10.4 装饰器模式构建I/O流体系

10.5 Apache IOUtils和FileUtils的使用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值