学习Java第三十一天--IO框架之字节流

流的概念、流的分类、字节流、序列化

  • 15. I/O框架
    • 15.1 流的概念
    • 15.2 流的分类
      • 15.2.1 流的分类(方向)
      • 15.2.2 流的分类(单位、功能)
    • 15.3 字节流
      • 15.3.1 字节流的父类
      • 15.3.2 字节节点流
      • 15.3.3 字节过滤流(缓冲流)
      • 15.3.4 字节过滤流(对象流)
      • 15.3.5 对象序列化

15. I/O框架

15.1 流的概念

  • 概念:内存与存储设备之间传输数据的通道
  • 如果水相当于数据,则传输水的管道就相当于流;
  • 水借助管道传输;数据借助流传输;

15.2 流的分类

15.2.1 流的分类(方向)

按方向【重点】:

  • 输入流:将<存储设备>中的内容读入到<内存> 中;

  • 输出流:将<内存>中的内容写入到<存储设备>中;

15.2.2 流的分类(单位、功能)

按单位:

  • 字节流:以字节为单位,可以读写所有数据;
  • 字符流:以字符为单位,只能读写文本数据;

按功能:

  • 节点流:具有实际传输数据的读写功能;
  • 过滤流:在节点流的基础之上增强功能;

15.3 字节流

15.3.1 字节流的父类

字节流的父类(抽象类):

  • InputStream:字节输入流
    public int read(){}
    public int read(byte[] b){}
    public int read(byte[] b , int off , int len){}

  • OutputStream:字节输出流
    public void write(int n){}
    public void write(byte[] b){}
    public void write(byte[] b , int off , int len){}

15.3.2 字节节点流

FileOutputStream:

  • public void write(byte[] b) //一次写多个字节,将b数组中所有字节,写入输出流
import java.io.FileOutputStream;
import java.io.IOException;

public class TestFileOutPutStream {

	public static void main(String[] args) throws IOException {
		//1.输出字节流OutPutStream
		//2.输出字节节点流  具有实际传输数据的功能(文件路径,boolean append) true代表追加不覆盖
		//路径正确:但是文件不存在,则会自动创建一个文件,但目录和盘符要提前有
		FileOutputStream fos = new FileOutputStream("D:\\JAVAEE\\Study\\Study\\com\\qf\\Day31\\test.txt");

		//相对路径:"Files\\test.txt" 与上一种形式等级,相对于当前项目的路径下,寻找该路径和文件
//		FileOutputStream fos = new FileOutputStream("Files\\test.txt");
		
		fos.write(65);
		fos.write(66);
		fos.write(67);
		fos.write('D');
		
		byte[] bytes = new byte[] {65,66,67,68,'G'};
//		fos.write(bytes);//一次输出一组字节
		
		//		字节数组  起始下标  长度
		fos.write(bytes, 1, 3);
		
//		String s = "你";
//		byte[] bs = s.getBytes();
//		System.out.println(bs[0] +"\t"+bs[1]);
//		fos.write(bs);
		
		fos.close();
	}

}

运行后完成了文件的创建和数据的写入。

FileInputStream:

  • public int read(byte[] b) //从流中读取多个字节,将读到内容存入b数组,返回实际读到的字节数;如果达到文件的尾部,则返回-1;
import java.io.FileInputStream;
import java.io.IOException;

public class TestFileInputStream {
	public static void main(String[] args) throws IOException {
		
		FileInputStream fis = new FileInputStream("D:\\JAVAEE\\Study\\Study\\com\\qf\\Day31\\test.txt");

		
		//读到了-1,就代表了文件末尾
//		while(true) {
//			int n = fis.read();//一次读一个字节
//			if(n == -1) {//文件末尾
//				break;//停止读的操作
//			}
//			System.out.println((char)n);
//		}
		
		byte[] bytes = new byte[4];//该数组作为读取时的存储
		while(true) {
			int count = fis.read(bytes);//每次读取到的有效字节个数
			if(count == -1) {
			break;
			}
			//读多少个,打印多少个
			for(int i = 0 ; i < count ; i++) {
				System.out.println((char)bytes[i]+"\t");
			}
			System.out.println();
		}
		
		fis.close();
		
	}

}

输入结果:

A	
B	
C	
D	

B	
C	
D	
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class TestFileIO {

	public static void main(String[] args) throws IOException {
		// 将指定图片,上传一份到项目里来
		
		//文件是在存储设备中的--》读到程序中来--》写入到存储设备中
		
		FileInputStream fis = new FileInputStream("C:\\Users\\xuhao\\Desktop\\千锋教育Java2002逆战班(20200203)\\打卡\\第六周\\26\\博客.png");

		//223KB
		//缓冲空间过大过小都容易有小问题
//		byte[] cache = new byte[1024*223];
		
//		fis.read(cache);
		
		//输出流
		FileOutputStream fos = new FileOutputStream("Files\\博客.png");
		
//		fos.write(cache);
		
		int len = 0;//代表每次读到的字节
		
		while((len = fis.read()) != -1) {//只要不读到-1
			fos.write(len);//读多数写多少
		}
		
		
		fis.close();
		fos.close();
	}

}

15.3.3 字节过滤流(缓冲流)

缓冲流:BufferedOutputStream / BufferedInputStream

  • 提高IO效率,减少访问磁盘的次数;
  • 数据存储在缓冲区,flush是将缓存区的内容写入文件中,也可以直接close;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class TestBufferOutput {

	public static void main(String[] args) throws IOException {
		
		//有参构造需要一个字节输出节点流
		//先创建字节输出节点流
		FileOutputStream fos = new FileOutputStream("Files/buff.txt");
		
				//增强节点流	
		BufferedOutputStream bos = new BufferedOutputStream(fos);
		
		bos.write('A');
		bos.write('B');
		
		bos.flush();//刷新缓冲区(将缓冲区的数据,一次性写入到文件中,并清空当前缓冲区)
		
		bos.write('C');
		bos.write('D');
		
		bos.close();//级联的执行了flush();释放资源的同时,将缓冲区的数据一次性写入到文件里
	
		
		//-----------------------------------------
		
		FileInputStream fis = new FileInputStream("Files/buff.txt");
		
		BufferedInputStream bis = new BufferedInputStream(fis);
		
		byte[] bytes = new byte[100];
		int count = bis.read(bytes);
		
		for(int i = 0 ; i < count ; i++) {
			System.out.println(bytes[i]);
		}
	}

}

输出结果:

65
66
67
68

15.3.4 字节过滤流(对象流)

对象流:ObjectOutputStream / ObjectInputStream

  • 增强了缓冲区功能;
  • 增强了读写8种基本数据类型和字符串功能
  • 增强了读写对象的功能:
    readObject() 从流中读取一个对象;
    writeObject(Object obj) 向流中写入一个对象

使用流传输对象的过程称为序列化、反序列化;

15.3.5 对象序列化

对象序列化的细节:

  • 必须实现Serializable接口;
  • 必须保证其所有属性均可序列化;
  • transient修饰为临时属性,不参与序列化;
  • 读取到文件尾部的标志:java.io.EOFException;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;

public class TestObjectStream {

	public static void main(String[] args) throws IOException, ClassNotFoundException {
		OutputStream os = new FileOutputStream("Files/obj.txt");
		
		ObjectOutputStream oos = new ObjectOutputStream(os);
		
	//	oos.writeInt(60);
		
	//	oos.writeDouble(6.6);
		
	//	oos.writeBoolean(true);
		
		Student stu1 = new Student("Tom" , 22 , "男" , 99D , new Address());
		Student stu2 = new Student("Jack" , 21 , "男" , 95D , new Address());
		Student stu3 = new Student("Rose" , 20 , "女" , 99D , new Address());
		
		oos.writeObject(stu1);
		oos.writeObject(stu2);
		oos.writeObject(stu3);
		
		oos.flush();
		
		//------------
		InputStream is = new FileInputStream("Files/obj.txt");
		ObjectInputStream ois = new ObjectInputStream(is);
		
//		int result = ois.readInt();
//		System.out.println(result);
		
//		Object obj1 = ois.readObject();
//		System.out.println(obj1);
//		Student s = (Student)obj1;
//		System.out.println(s.name);
		
//		Object obj2 = ois.readObject();
//		System.out.println(obj2);
		
//		Object obj3 = ois.readObject();
//		System.out.println(obj3);
		
		while(true) {
			try {
				Object obj = ois.readObject();
				System.out.println(obj);
			}catch(Exception e) {
				//到达文件末尾  获取EOFException一次,就停止循环
				break;//自定义处理异常
			}
		}
	}

}

//对象要支持序列化
//属性也要支持序列化
class Student implements Serializable{//实现该接口已序列化,对static修饰的值进行序列化,则该值属于所有类,影响序列化
	String name;
	Integer age;
	String sex;
	Double score;
	Address add;	
	
	//transient修饰的属性,不参与序列化
	
	//基本数据类型的数组,可以序列化
	//引用数据类型的数组,数组类型要支持序列化
	
	public Student(String name, Integer age, String sex, Double score, Address add) {
		super();
		this.name = name;
		this.age = age;
		this.sex = sex;
		this.score = score;
		this.add = add;
	}
	@Override
	public String toString() {
		return "Student [name=" + name + ", age=" + age + ", sex=" + sex + ", score=" + score + ", add=" + add + "]";
	}
	
}

class Address implements Serializable{
	String position;
	String zipCode;
	public Address() {}
	public Address(String position, String zipCode) {
		super();
		this.position = position;
		this.zipCode = zipCode;
	}
	
}

输出结果:

Student [name=Tom, age=22, sex=, score=99.0, add=com.qf.Day31.Address@b4c966a]
Student [name=Jack, age=21, sex=, score=95.0, add=com.qf.Day31.Address@2f4d3709]
Student [name=Rose, age=20, sex=, score=99.0, add=com.qf.Day31.Address@4e50df2e]

你可能感兴趣的:(学习Java)