Java—Reader,Writer,InputStream,OutputStream,缓冲IO流,转换流,数据IO流,序列化与反序列化,try...catch

这篇博客详细介绍了Java的IO流,包括输入输出流的分类、字节流与字符流的区别、节点流与处理流的概念。重点讲解了Reader、Writer、InputStream和OutputStream的基本操作,以及缓冲IO流的作用。此外,还讨论了转换流(InputStreamReader和OutputStreamReader)的功能,数据IO流的使用,以及对象的序列化与反序列化过程。最后提到了JDK1.7的try...catch语句块在资源管理上的应用。
摘要由CSDN通过智能技术生成

IO

  1. 概述
    (1)如果对于File对象来说,输入输出流只能针对文件,不能针对目录
    (2)IO操作不仅仅是针对文件,还可以从网络中输入输出
    (3)输入输出的参照物是当前程序

  2. IO的分类
    (1)按方向
    输入流(InputStream):将数据从某个源流向程序中
    输出流(OutputStream):将数据从程序往外发送到某个目的地
    (2)按操作数据的单位
    字节流:适用于任何类型的文件,但如果是纯文本文件用字符流更快
    字符流:只能用于读/写纯文本数据(内容全部是字符),纯文本文件:.txt,.html,.xml,.properties等是纯文本文件
    (3)按功能角色
    节点流:和某个文件关联,如文件流…
    处理流:在节点流的基础上加其它的处理功能的,例如:缓冲流,序列化,反序列化…

  3. IO流有四大抽象的父类/基类/超类
    (1)InputStream:字节输入流
    (2)OutputStream:字节输出流
    (3)Reader:字符输入流
    (4)Writer:字符输出流
    Reader系列:
    (1)int read():读取一个字符,返回该字符的Unicode编码
    (2)int read(char[] c):读取多个字符,读取的字符放到c数组中,从c的[0]开始存储,最多读取c.length个,返回实际本次读取的字符个数
    (3)int read(char[] c,int off,int len):读取多个字符,读取的字符放到c数组中,从c的[off]开始存储,最多读取len个 ,返回实际本次读取的字符个数
    如果流中没数据可读,以上方法返回-1
    Writer系列:
    (1)void write (char c):写单个字符
    (2)void write(char[] c):把单个字符数组的内容写出去
    (3)void write(char[] c,int off,int len):从c[off]开始,把len个字符写出去
    (4)void write(String str):把str的内容写出去
    (5)void write(String str,int off,int len):把str从[off]开始将len个字符写出去
    (6)void close():关闭
    (7)void flush():刷新
    InputStream系列
    (1)int read():一次读取一个字节,返回本次读取的字节的值
    (2)int read(byte[] b):一次读取多个字节,返回本次实际读取字节数,读取的字节存到b数组中,从[0]开始存储,一次最多存储b.length个字节
    (3)int read(byte[] b,int off,int len):一次读取多个字节,返回本次实际读取字节数,读取的字节存到b数组中,从[off]开始存储,一次最多存储len个字节
    如果流中没数据可读,以上方法返回-1
    OutputStream系列
    (1)void write(int b):写一个字节
    (2)void write(byte[] b):写一个字节数组的所有
    (3)void write(byte[] b,int off,int len):从b[off]开始,把len个字符写出去
    (4)void close()
    (5)void flush():刷新

  4. 缓冲IO流
    是处理流,负责在其他IO流基础上增加缓冲功能,默认的缓冲区大小8192字节/字符
    BufferedReader只能给Reader增加缓冲功能
    BufferedWriter只能给Writer…
    BufferedInputStream-----InputStream
    BufferedOutputStream------OutputStream
    BufferedReader在Reader基础上增加了:String readLine()读取一行,达到流的结尾,返回null
    BufferedWriter在Writer的基础上增加了:void newLine()写换行符

    //部分代码
    FileReader fr = new FileReader("1.txt");
    BufferedReader br=new BufferedReader(fr);
    FileWriter fw=new FileWriter("2.txt");
    BufferedWriter bw=new BufferedWriter(fw);
    String str;
    while((str=br.readLine())!=null){
    	bw.write(str); 
    }
    bw.close();
    fw.close();
    br.close();
    fr.close();
    
  5. 转换流
    解码:将字节流转换为字符流
    InputStreamReader

    //解码 字节--字符
    FileInputStream fis=new FileInputStream("1.txt");
    InputStreamReader isr=new InputStreamReader(fis,"GBK");
    char[] arr=new char[10];
    int len=isr.read(arr);
    System.out.println(new String(arr,0,len));
    isr.close();
    fis.close();
    

编码:将字符流转化为字节流
OutputStreamReader

	//编码 字符---字节
	String str="亮";
	FileOutputStream fos=new FileOutputStream("1.txt");
	OutputStreamWriter osw=new OutputStreamWriter(fos,"GBK");
	osw.write(str);
	osw.close();
	fos.close();
  1. 数据IO流
    DataOutputStream在OutputStream的基础上,增加的方法:
    writeXxx(…):
    DataInputStream在InputStream的基础上,增加的方法:
    readXxx():

用DataOutputStream写的数据/文件,用DataInputStream读取,并且要求读的顺序与写的顺序一致

	@Test
	public void test5() throws IOException{
	 int num=1;
	 char c='好';
	 double d=3.4;
	 String info="哈哈哈";
	 boolean b=true;
	 FileOutputStream fos=new FileOutputStream("3.dat");
	 DataOutputStream dos=new DataOutputStream(fos);
	 dos.writeInt(num);
	 dos.writeChar(c);
	 dos.writeDouble(d);
	 dos.writeUTF(info);
	 dos.writeBoolean(b);
	 dos.close();
	 fos.close();
	}
	@Test
	public void test6() throws IOException{
	FileInputStream fis=new FileInputStream("3.dat");
	DataInputStream dis=new DataInputStream(fis);
	int num=dis.readInt();
	char c=dis.readChar();
	double d=dis.readDouble();
	String info=dis.readUTF();
	boolean b=dis.readBoolean();
	System.out.println(num);
	System.out.println(c);
	System.out.println(d);
	System.out.println(info);
	System.out.println(b);
	dis.close();
	fis.close();
	}
  1. 序列化与反序列化
    (1)java.io.Serializable接口
    ObjectOutputStream:用于输出对象,即把对象转成字节数据输出,对象的输出过程称为序列化;ObjectOutputStream比OutputStream多的方法之一:writeObject(obj)

如果创建对象的类没有实现Serializable接口,在序列化时,会报错NotSerializableException,不能序列化,因此,类必须实现java.io.Serializable接口

(2)ObjectInputStream:用于输入对象,把字节序列转为对象读取,对象的读取过程称为反序列化;ObjectInputStream比InputStream多的方法之一:Object readObject()

当对象已经输出到文件后修改了类,再次读取这个文件时,报错InvalidClassException,报错的原因:流中关于类的serialVersionUID与本地类的serialVersionUID对不上,就会报错InvalidClassException;
如何解决?修改本地的serializableUID为流中的serialVersionUID;或者在实现Serializable接口时固定一个serialVersionUID

(3)序列化一个对象时,要求它的属性是基本数据类型,如果是引用数据类型,那么这个引用数据类型也必须实现Serializable接口
序列化一个数组,要求元素类型实现Serializable接口

	@Test
	public void test7() throws IOException{
		User u=new User("lx","123456");
		FileOutputStream fos=new FileOutputStream("3.dat");
		ObjectOutputStream oos=new ObjectOutputStream(fos);
		oos.writeObject(u);
		oos.close();
		fos.close();
	}
	@Test
	public void test8() throws IOException,ClassNotFoundException{
		FileInputStream fis=new FileInputStream("3.dat");
		ObjectInputStream ois=new ObjectInputStream(fis);
		Object obj=ois.readObject();
		System.out.println(obj);
		ois.close();
		fis.close();
	}
	//实现Serializable接口
	class User implements Serializable{
		private static final long serivalVersionUID=1L;
		private String name;
		private String id;
		public User(String name, String id) {
			super();
			this.name = name;
			this.id = id;
		}
		//实现Externalizable
		class User implements Externalizable{
		private static final long serivalVersionUID=1L;
		private String name;
		private String id;
		public User(String name, String id) {
			super();
			this.name = name;
			this.id = id;
		}
		@Override
		public void writeExternal(ObjectOutput out) throws TOException{
			out.writeUTF(name);
			out.writeUTF(id):
		}
		@Override
		public void readExternal(ObjectInput in)throws IOException,ClassNotFoundException{
			name = in.readUTF();
			id = in.readUTF();
		}
	}

(4)不序列化的字段:
不是对象的所有属性都需要序列化
如果某个属性不需要序列化,可以在属性的前面加一个关键字:transient
如果某个属性是static,也不会序列化,因为静态变量不属于某个对象,而是整个类,所以不需要随着对象的序列化而序列化
(5)java.io.Externalizable接口
若要完全控制某一个对象的流格式和内容,则它要实现Externalizable接口的writeExternal和readExternal方法,程序员在writeExternal方法中,自己定制哪些属性要序列化及其顺序;在readExternal方法中,自己定制哪些属性要反序列化及其顺序

JDK1.7新增try…catch
try(
需要关闭的资源对象
){
可能发生异常的逻辑代码
}catch(异常对象 e){
异常处理代码
}catch(异常对象 e){
异常处理代码
}
凡是在try()中声明的资源对象,无论是否发生异常都会自动关闭

	 @Test
	 public void test2(){
	 try(
			FileInputStream fis=new FileInputStream("1.txt");
			InputStreamReader isr=new InputStreamReader(fis,"GBK");
			BufferedReader br=new BufferedReader(isr);
			FileOutputStream fos=new FileOutputStream("1.txt");
			OutputStreamWriter osw=new OutputStreamWriter(fos,"UTF-8");
			BufferedWriter bw=new BufferedWriter(osw);
	 ){
		 String str;
		 while((str=br.readLine())!=null){
			 bw.write(str);
			 bw.newLine();
		 }
	 } catch (IOException e) {
		e.printStackTrace();
		}
	 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值