IO流

IO流

在这里插入图片描述

流的概念:

流是一个很形象的概念,当程序需要读取数据的时候,就会开启一个通向数据源设备的流,这个数据源设备可以是文件、内存或网络连接。流是含有流质具有方向的抽象管道。
流的特点:
流有两个最基本的特性:一是它含有流质,而是它有方向
对流的读或写就是针对设备进行信息的输入或输出。我们可以将流理解为传送数据的管道。管道的一段是固定的,就是系统的内存;管道的另一端连的是不同的设备。
流的作用:
用于应用程序和内外部进行数据通讯。

**

流的分类:

      方向:
  1. 输入流inputStream 继承自抽象类InputStream或Reader

  2. 输出流outputStream继承自抽象类OutputStream或Writer

    流的数据单位:
    

    1.字节流 1个字节 8位二进制数继承自抽象类InputStream或OutputStream。
    2.字符流 char字符(2个字节)继承自抽象类Reader或者Writer

     流的功能:
    

低级流(节点流)节点流是可以直接从/向一个特定的数据源(例如磁盘文件、内存、网络)读/写数据的流。
高级流(处理流不直接连接到设备,而是连接在已存在的流(节点流或处理流))

文件类

File既代表文件又代表目录

File.exist()
File.isFile();

低级字符流:
低级字符流实现文件的复制:

String fromPath="E:"+File.separator+"helloWorld.java";
File file=new File(fromPath);
String toPath="D:"+File.separator+"test"+File.separator+"helloWorld.java";
File file02=new File(toPath);
	
	if(file.exists()) {
		FileReader r=null;
		FileWriter w=null;
		try {

			r=new FileReader(file);
			w=new FileWriter(file02);
			
			char[] data=new char[1024];
			int length=0;
			while((length=r.read(data))!=0) {
				w.write(data, 0, length);
			}
			
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}finally {
			try {
				r.close();
				w.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}
	}

低级字节流

无论是什么类型的文件都可以使用字节流。InputStream和OutputStream。
音频、视频图片等文件使用字节流。
文本型文件一般使用字符流。
低级字符流
文本文件,适合使用字符流来读取、写入
以下是通过低级字节流,把一个文件内容复制到另一个文件:

	String fromPath = "C:" + File.separatorChar +"1" + File.separatorChar + "MainEnter.java";
	**//路径根据本地地址更改**
	//File.separatorChar代表路径中的”/“
	File file = new File(fromPath);//新创一个文件通过被复制文件路径
	String toPath = "C:" + File.separatorChar +"2" + File.separatorChar + "MainEnter.java";
	//复制到的路径
	File file02 = new File(toPath);//新创一个文件,代表复制到的文件
	//判断文件是否存在
	if(file.exists()) {
		//无论文件是什么类型的文件,都可以采用字节流
		//推荐:对于字节码文件,或者图片,或音频,视频等等文件,我们读取时,一般采用字节流
		//而文本文件,采用字符流
		FileInputStream in = null;
		FileOutputStream out = null;
		
		byte[] data = new byte[1024];//定义一个数据缓冲区
		try {
			in = new FileInputStream(file);//针对该文件,创建一个对应字节输入流
			//false代表文件采用覆盖的方式,来写入内容,true代表文件采用尾部追加的方式,来写入内容
			out = new FileOutputStream(file02,false);//针对该文件,创建一个对应的字节输出流

			int lenth = 0;//代表单次读取内容的长度
			while((lenth = in.read(data)) != -1) {
				out.write(data,0,lenth);
			}
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {//关流
			try {
				in.close();
				out.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

高级字节流

缓冲流:BufferedInputStream和BufferedOutputStream利用缓冲区来提高读写数据的效率。
BufferedReader和BufferedWriter类,与BufferedInputStream和BuffedOutputStream类似,可以利用缓冲区来提高读写数据的效率,用来装饰其它的字符流。比BufferedInputStream和BuffedOutputStream更强大的是,这两个类可以整行读写字符。

以下是通过高级字节流,复制一个文件的内容到另一个文件:

String fromPath = "C:" + File.separatorChar + "1" + File.separatorChar + "1.txt";
		File file = new File(fromPath);

		String toPath = "D:" + File.separatorChar + "test" + File.separatorChar + "2.txt";
		File file02 = new File(toPath);

		// 判断文件是否存在
		if (file.exists()) {
			// 定义低级流
			FileInputStream in = null;
			FileOutputStream out = null;
			// 定义高级流
			BufferedInputStream bis = null;
			BufferedOutputStream bos = null;

			try {
				// 实例化低级流
				in = new FileInputStream(file);
				out = new FileOutputStream(file02);
				// 实例化高级流
				bis = new BufferedInputStream(in);
				bos = new BufferedOutputStream(out);

				// 读写文件
				byte[] data = new byte[1024];
				int lenth = 0;
				while ((lenth = bis.read(data)) != -1) {
					bos.write(data, 0, lenth);
				}
			} catch (Exception e) {
				// TODO: handle exception
				e.printStackTrace();
			} finally {
				try {
					bos.flush();// 向文件中,写入数据
					in.close();
					out.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

			}
		}

数据流:DataInputStream和DataOutputStream。与计算机无关,非文件。

字节打印输出流
PrintStream
可以让我们写入以默认字符编码集显示

String[] names = { "张帅", "徐帅", "袁帅", "胡帅", "帅胡" };// 名字
	int[] age = { 20, 18, 29, 19, 91 };// 年龄
	boolean[] marry = { true, false, true, true, false };// 结没结婚
	// 将上面的这些数据,写入到文件中
	String toPath = "C:" + File.separatorChar + "2" + File.separatorChar + "Person02.txt";
	File file = new File(toPath);

//定义低级字节流
FileOutputStream os = null;
//定义字节,字符转换流
OutputStreamWriter osw = null;
//定义高级字符流
PrintWriter out = null;

try {
	//实例化各种流
	os = new FileOutputStream(file);
	osw = new OutputStreamWriter(os, "utf-8");//指定文本文件,采用什么编码方式,转换字符
	out = new PrintWriter(osw);
	
	//通过高级字符流向文件中输出“特定编码方式”内容
	int lenth = names.length;
	for(int i = 0; i < lenth; i ++) {
		
		out.print(names[i] + " ");
		out.print(age[i] + " ");
		out.print(marry[i] + " ");
		out.println();//换行
	}
	
	out.flush();//刷新缓冲区
} catch (Exception e) {
	// TODO: handle exception
	e.printStackTrace();
}finally {
	try {
		os.close();//关流
	} catch (IOException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
}

字符流:处理文本文件、音频、视频
Reader类可以将数据源中采用其他编码的字符转换为Unicode编码;writter会将Unicode字符转换为其他编码的字符。
字符流中常用的高级流包括:
缓冲流:包括BufferedReader和BufferedWriter类,利用缓冲区来提高读写数据的效率。

String fromPath = "C:" + File.separatorChar + "1" + File.separatorChar + "MainEnter.java";
		File file = new File(fromPath);
		
		String toPath = "C:" + File.separatorChar + "2" + File.separatorChar + "MainEnter.java";
		File file02 = new File(toPath);
		
		
		//判断文件是否存在
		if(file.exists()) {
			//声明字符输入流,字符输出流
			FileReader r = null;
			FileWriter w = null;
			BufferedReader reader = null;
			BufferedWriter writer = null;
			try {
				//实例化字符流入流,和字符输出流
				r = new FileReader(file);
				w = new FileWriter(file02);
				reader = new BufferedReader(r);
				writer = new BufferedWriter(w);
				
				//使用BufferedReader类可以缓冲数据,在读取的可以1个字符1个字符的读,也可以1行行的读
				String data = "";
				while((data = reader.readLine()) != null) {
					System.out.println(data);
					writer.write(data + "\n");
//					writer.newLine();//换行
				}
				writer.flush();//将缓冲区中的数据推送到文件中去,重新清空缓冲区
				
//				char[] data = new char[1024];
//				int lenth = 0;
//				while((lenth = br.read(data)) != -1) {
//					System.out.println(Arrays.toString(data));
//				}
				
			} catch (IOException e) {
				// TODO: handle exception
				e.printStackTrace();
			}finally {
				try {
					r.close();
					w.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			
		}
		
		
		
		
		

	}

转换流:用于字节数据到字符数据之间的转换,包括InputStreamReader和OutputStreamWriter。

String fromPath = "C:" + File.separatorChar + "1" + File.separatorChar + "MainEnter.java";
		File file = new File(fromPath);
		String toPath = "C:" + File.separatorChar + "2" + File.separatorChar + "MainEnter.java";
		File file02 = new File(toPath);
		
		
		if(file.exists()) {
			// 定义低级输入流
			FileInputStream in = null;
			FileOutputStream out = null;
			//定义 转换流 
			InputStreamReader isr = null;
			OutputStreamWriter osw = null;
			
			//定义字符缓冲流
			BufferedReader reader = null;
			
			
			try {
				//实例化输入流
				in = new FileInputStream(file);
				out = new FileOutputStream(file02);
				isr = new InputStreamReader(in);//作用:将字节流数据转换为字符流数据
				osw = new OutputStreamWriter(out, "UTF-8");
				reader = new BufferedReader(isr);//再转换为缓冲流,方便我们大家可以使用readLine()
				
				System.out.println("文件的编码集:" + isr.getEncoding());
				String data = "";
				
				while((data = reader.readLine()) != null) {
					System.out.println(data);
					osw.write(data + "\n");
				
				}
				
				osw.flush();
				
			} catch (Exception e) {
				// TODO: handle exception
				e.printStackTrace();
			}finally {
				try {
					in.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			
		}
打印输出流:包括PrintWriter类,允许将基本类型数据打印输出到字符串流中,PrintWriter带有带自动刷新(Flush)功能。

Java既支持字节流,也支持字符流,但是有时候需要在字节流和字符流之间转换。Java I/O库中提供了InputStreamReader和OutputStreamWriter这两个类用于字节数据到字符数据之间的转换。

对象流
ORM(Object relationshipDB Mapping)对象关系数据库映射
ObjectInputStream/ObjectOutputStream之所以能完成基于对象的读写,是因为Java提供了一套对象序列化机制。序列化机制就是一套向流写入或读取对象数据的自动机制,这套机制将读写的实现封装在对象自身的实现之中。
序列化:对象转换为流数据
反序列化:流数据转换为对象
如果需要传输的对象类作了改动(加了新属性或删除了属性)只要serialVersionUID没有变,原来保存的对象还是可以读取。当然改动之后的类要与原来的对象兼容

JavaBeans

package com.gezhi.javaoo23.bean;

import java.io.Serializable;

/**
 * 学生实体类
 *
 * 
 */
public class StudentBean implements Serializable{

	/**
	 * 序列化版本号(作用:比较原来Java的序列化机制,
	 * 是通过在运行时判断类的serialVersionUID来验证版本的一致性的。在进行反序列化时,
	 * JVM会把传来的字节流中的serialVersionUID与本地相应实体类的serialVersionUID进行比较。)
	 */
	private static final long serialVersionUID = 5453124311904581252L;
	
	/**
	 * 数据的唯一标识	
	 */
	private String id;
	/**
	 * 学生名字
	 */
	private String stuName;
	/**
	 * 学生年龄
	 */
	private int age;
	
	/**
	 * 学生性别(0-女,1-男,-1 不男不女)
	 */
	private int gender;
	
	/**
	 * 学生学号
	 */
	private String stuNo;
	
	/**
	 * 提供无参构造 (可以显式写出,也可以不写,编译器会自动添加)
	 */
	public StudentBean() {
		super();
		// TODO Auto-generated constructor stub
	}

	
	public StudentBean(String id) {
		super();
		this.id = id;
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getStuName() {
		return stuName;
	}

	public void setStuName(String stuName) {
		this.stuName = stuName;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public int getGender() {
		return gender;
	}

	public void setGender(int gender) {
		this.gender = gender;
	}
	
	public String getStuNo() {
		return stuNo;
	}

	public void setStuNo(String stuNo) {
		this.stuNo = stuNo;
	}

	@Override
	public String toString() {
		return "StudentBean [id=" + id + ", stuName=" + stuName + ", age=" + age + ", gender=" + gender + ", stuNo="
				+ stuNo + "]";
	}
}

对象流:
package com.gezhi.javaoo23.io;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import com.gezhi.javaoo23.bean.StudentBean;

/**

  • 对象流

*/
public class ObjectStream {

public static void main(String[] args) {
	// TODO Auto-generated method stub
	//从硬盘的文件中,读取对象
	input();
	
	//向文件中持久化对象

// output();
}

private static void input() {
	// TODO Auto-generated method stub
	String fromPath = "C:" + File.separatorChar + "2" + File.separatorChar + "students.data";
	File file = new File(fromPath);
	if(file.exists()) {
		//定义低级字节流
		FileInputStream in = null;
		//定义高级对象输入流
		ObjectInputStream ois = null;
		try {
			//实例化
			in =  new FileInputStream(file);
			ois = new ObjectInputStream(in);
			
			//从文件中读取多个JAVA对象
			Object obj = null;
			while((obj = ois.readObject()) != null) {
				if(obj instanceof StudentBean) {
					StudentBean stu = (StudentBean) obj;
					System.out.println(stu);
				}
			}
			
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}finally {
			try {
				in.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}

private static void output() {
	// TODO Auto-generated method stub
	// 创建一个学生对象(代表何汉峰的相关数据)
	StudentBean stu = new StudentBean("9527");
	stu.setStuName("何汉峰");
	stu.setAge(18);

// stu.setGender(1);

	StudentBean stu02 = new StudentBean("9528");
	stu02.setStuName("小哥");
	stu02.setAge(68);

// stu02.setGender(1);

	// System.out.println(stu);

	// 此时我们需要将该对象“持久化”到硬盘上去
	String toPath = "C:" + File.separatorChar + "2" + File.separatorChar + "students.data";
	File file = new File(toPath);

	// 定义低级流
	FileOutputStream out = null;
	// 定义对象高级流
	ObjectOutputStream oos = null;
	try {
		// 实例化
		out = new FileOutputStream(file);
		oos = new ObjectOutputStream(out);

		oos.writeObject(stu);// 将学生对象丢入“对象流”中
		oos.writeObject(stu02);
		
		
		oos.flush();// 刷新流
	} catch (Exception e) {
		// TODO: handle exception
		e.printStackTrace();
	} finally {
		try {
			out.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}

}

**

流的使用原则:

**
对Java I/O库中的流类有如下的使用原则:
一、按数据源分类

  1. 如果数据源是非文本文件文件,使用字节流, FileInputStream和FileOutputStream;对于文本文件,使用字符流, FileReader和 FileWriter。
  2. 如果数据源是字节数组byte[],则使用ByteArrayInputStream和ByteArrayOutputStream。
  3. 如果数据源是字符数组Char[],则使用CharArrayReader和CharArrayWriter。
  4. 如果数据源是String对象,对于字节流,则使用StringBufferInputStream和StringBufferOuputStream;对于字符流,则使用StringReader和StringWriter。
  5. 如果数据源是网络数据流,对于字节流,使用InputStream和OutputStream;对于字符流,使用Reader和Writer。
    二、按是否格式化输出分:要格式化输出,则使用PrintStream或PrintWriter。
    三、按是否要缓冲分,要缓冲的话,对于字节流使用BufferedInputStream和BufferedOutputStream;对于字节流,使用BufferedReader和BufferedWriter。
    四、按数据格式分
  6. 二进制格式(只要不能确定是纯文本的):使用InputStream、OutputStream 及其所有带 Stream结束的子类。
  7. 纯文本格式(含纯英文与汉字或其他编码方式):使用Reader、Writer 及其所有带 Reader、Writer 的子类。
    五、按输入输出分
  8. 输入:使用Reader、InputStream 类型的子类。
  9. 输出:使用Writer、OutputStream 类型的子类。
    六、特殊需要
  10. 从Stream到Reader、Writer的转换类:InputStreamReader、OutputStreamWriter。
  11. 对象输入输出:ObjectInputStream、ObjectOutputStream。
  12. 线程间通信:PipeInputStream、PipeOutputStream、PipeReader、PipeWriter。
  13. 合并输入:SequenceInputStream。
  14. 更特殊的需要:PushbackInputStream、PushbackReader、LineNumberInputStream、LineNumberReader。
    在不考虑特殊需求的情况,决定使用哪个类以及它的构造进程的一般准则如下:
    首先,考虑最原始的数据格式是什么:原则四。
    第二,是输入还是输出:原则五。
    第三,是否需要转换流:原则六第1点。
    第四,数据源是什么:原则一。
    第五,是否要缓冲:原则三(特别注明:一定要注意的是readLine()是否有定义,有什么比 read()、write()更特殊的输入或输出方法)。
    第六,是否要格式化输出:原则二。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值