Java IO流

Java I/O流

​ 在程序中运行的数据,一旦程序关闭后,数据就会丢失,所以需要用持久化的方式把数据保存起来。

​ 通常会把数据保存在文件中,然后放到硬盘、U盘等磁盘中去。然后就可以通过流把文件中的数据传到程序中来,再把程序中的数据传到文件中去。

在这里插入图片描述

File类

​ 在程序中,我们通过java.io包中的File类来对文件的属性进行访问操作。可以通过创建File类的对象,把文件的路径传进来,就可以通过文件对象的各种方法来操作文件或目录的属性(包括路径、权限、日期和时间等)了。

	File file=new File(String pathname);

创建File文件对象的构造方法中,可以放入文件或目录的路径,如“c:\test.txt”或"c:/test.txt".

File类中操作文件属性的常用方法如下:

返回值类型方法名说明
booleanexists()判断文件或目录是否存在
booleanisFile()判断是否是文件
booleanisDirectory()判断是否是目录
StringgetPath()返回此对象表示的文件的相对路径名
StringgetAbsolutePath()返回此对象表示的文件的绝对路径名
StringgetName()返回此对象表示的文件或目录的名称
booleandelete()删除此对象指定的文件或目录
booleancreateNewFile()创建名称的空文件,不创建文件夹
longlength()返回文件的长度,单位为字节,如果文件不存在,则返回0L
	public static void main(String[] args) {
		
		File file =new File("test.txt");
		System.out.println("文件是否存在"+file.exists());
		System.out.println("是否是文件"+file.isFile());
		System.out.println("是否是目录"+file.isDirectory());
		System.out.println("此文件的相对路径名:"+file.getPath());
		System.out.println("此文件的绝对路径名:"+file.getAbsolutePath());
		System.out.println("此文件的文件名是:"+file.getName());
		System.out.println("此文件的长度为:"+file.length());
	
		try {
			file.createNewFile();
		} catch (IOException e) {
			e.printStackTrace();
		}
		file.delete();
	}

​ 流是一组有序的数据序列,它是以先进先出的方式发送信息的通道,程序通过流来读写文件。

在这里插入图片描述

在这里插入图片描述

Java中的流可以根据流向来分类,分为:

(1)输入流。(以InputStream类和Reader类作为基类)

(2)输出流。(以OutputStream类和Writer类作为基类)

注意:这里的输入输出是相对计算机内存而言。

按处理数据单元划分,流可以分为:

(1)字节流

字节流是8位通用字节流。(1字节=8位)

其中可以细分为:

1.字节输入流。(以InputStream类作为基类)

2.字节输出流。(以OutputStream类作为基类)

(2)字符流

字符流是16位Unicode字符流。(1字符=2字节)

其中可以细分为:

1.字符输入流。(以Reader类作为基类)

2.字符输出流。(以Writer类作为基类)

InputStream类

​ InputStream类是一个抽象类,常用方法如下:

返回值类型方法名说明
intread()把数据源的数据一个字节一个字节读进来,以一个整数返回(返回字节对应的整数)
intread(byte[] b)从输入流读取若干字节,把这些字节保存在数组b中,返回的是读取到的字节数,如果读到末尾,则返回-1
intread(byte[]b,int off,int len)从输入流读取若干字节,把这些字节保存到数组b中,off指的是字节数组开始保存数据的起始下标,len指读取的字节数目,返回的是实际读取到的字节数,如果读到了末尾,则返回-1
voidclose()关闭流
intavailable()可以从输入流中读取的字节数目

​ 因为抽象类无法实例化对象,所以实际我们使用的是它的一个子类FileInputStream类

FileInputStream类

​ 是InputStream的子类,常用的构造方法有:

(1)FileInputStream(File file); 传输文件

(2)FileInputStream(String name); 传文件路径

用FileInputStream类读文本文件的步骤如下:
在这里插入图片描述

(1)引入相关的类,即导包

​ import java.io.*;

(2)构造文件输入流FileInputStream对象

​ InputStream is =new FileInputStream(”xxx.txt“);

(3)读取文本文件的数据

​ 即调用FileInputStream类的read()方法

​ is.read()

(4)关闭文件流对象

​ is.close()

	public static void main(String[] args) {
		InputStream is =null;
		try {
			is =new FileInputStream("我的青春我做主.txt");
			int read =-1;
//			byte[] b =new byte[1024];
//			while( (read=is.read(b))!=-1 ) {
//				for(int i=0;i<read;i++) {
//					System.out.print((char)b[i]);
//				}
//			}
			while((read=is.read())!=-1) {
				System.out.print((char)read);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally {
			try {
				is.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

OutputStream类

​ OutputStream类是一个抽象类,常用方法如下:

返回值类型方法名说明
voidwrite(int c)把字节对应的数字通过输出流写到目标文件中
voidwrite(byte[]b)把数组b中的字节数据写到文件中去
voidwrite(byte[]b,int off,int len)把数组b中的字节数据写到文件中去,off表示数组开始写的位置,len表示写多少个字节
voidclose()关闭流
voidflush()强制把缓冲区的数据写到输出流中

​ 因为抽象类无法实例化对象,所以实际我们使用的是它的一个子类FileIOutputStream类

FileOutputStream类

​ 是OutputStream类的子类,常用构造方法如下:

(1)FileOutputStream(File file); 写到某个文件,会覆盖文件原有内容

(2)FileOutputStream(String name); 写到某个路径,会覆盖文件原有内容

(3)FileOutputStream(String name,boolean append); 写到某个路径,布尔值为true时,可以指定不覆盖文件原有内容,而是在后面追加新内容

使用FileOutputStream类写文本文件的步骤:

在这里插入图片描述

(1)引入相关的类,即导包

​ import java.io.*;

(2)构造文件输出流FileOutputStream对象

​ OutputStream os =new FileOutputStream(”xxx.txt“);

(3)把数据写入文本文件

​ 即调用FileOutputStream类的write()方法

​ os.write(byte[]b)

(4)关闭文件流对象

​ os.close()

	public static void main(String[] args) {
		OutputStream os =null;
		try {
			os =new FileOutputStream("szxs.txt",true);
			String msg = "您好呀,信狮教育";
			byte[] b =msg.getBytes();
			os.write(b);
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally {
			try {
				os.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

Reader类

如果文本文件中有汉字,如果用字节流来输入,会出现乱码的情况。对于有汉字的文本,就需要使用字符流来进行读写。而字符的输入流用的就是Reader类。

​ Reader类是个抽象类,不能够实例化对象,通常是作为引用指向子类对象。Reader类中常用的方法有:

(1) read(); 一个字符一个字符读文件,返回值类型为int

(2) read(char[]c); 将文件读到数组c中,返回值类型为int

(3) read(char[]c ,int off, int len); 将文件读到数组c中,从第off位置开始存数据,读len长度,返回值类型为int

(4)close(); 关闭输入流,返回值类型为void

InputStreamReader类

​ 是Reader的子类。当文件编码格式和程序环境编码格式不一致时,我们用字符流去读文件,就需要指定字符流的编码格式,否则可能会出现中文乱码的情况。而在字符流中,InputStreamReader类是可以在读文件的时候指定编码格式的。

​ InputStreamReader类的常用构造方法如下:

​ (1)InputStreamReader(InputStream in); //参数为字节输入流对象

​ (2)InputStreamReader(InputStream in , String charsetName); // 参数有两个,第一个是字节输入流的对象,第二个参数是指定编码格式。

​ 由构造方法可以看出,InputStreamReader类可以在构造实例化对象的时候指定输入流的编码格式,并且是间接使用了字节流来进行操作的,即将字节流包成了字符流。

FileReader类

​ 是InputStreamReader类的子类。该类只能按照本地平台(电脑当前系统的jdk编码格式)的字符编码来读取数据,用户不能指定其他的字符编码类型。

​ 常用的构造方法如下:

(1)FileReader(File file); //传文件

(2)FileReader(String name); //传文件路径

​ FileReader类在创建对象的时候可以直接把文件当参数传进来,就不需要再创建一个字节输入流InputStream类型的对象了,但是不能自己指定字符编码格式。

​ 如果想要获取本地平台的字符编码类型,就可以通过方法:System.getProperty(“file.encoding”);来查询。

BufferedReader类

​ 字符流中还有一种更高效读取数据的方式,就是通过BufferedReader类这个带缓冲区的流来读取数据,他是先将文件读到缓冲区中,当缓冲区里存满了或执行了flush()指令时,再把数据一次性读取到程序中。

​ BufferedReader类是Reader类的子类,它带有缓冲区,这个类的特点就是可以通过readLine()方法,按行来读取文件内容。

使用BufferedReader读文本文件的步骤:

(1)引入相关的类

	import java.io.FileReader;
	import java.io.BufferedReader;
	import java.io.IOException;

(2)构造BufferedReader对象和FileReader对象

	Reader fr = new FileReader("c:\\myTest.txt");
	BufferedReader br = new BufferedReader(fr);

(3)调用readLine()方法读取数据

	br.readLine();

(4)关闭文件流对象

	br.close();
    fr.close();

Writer类

​ 如果需要写一个带汉字的文件,就不能通过字节输出流OutputStream来写数据了,这时候就需要用到字符输出流Writer。

​ Writer类是个抽象类,它有一些常用方法:

​ (1)write(String str);

​ (2)write(String str ,int off , int len);

​ (3)close(); 关闭文件流对象,关闭前也会清空缓存

​ (4)flush(); 清空缓存区

OutputStreamWriter类

​ 是Writer类的子类。与InputStreamReader类似,可以在实例化对象的时候指定字符编码格式。

​ 常用构造方法如下:

​ (1)OutputStreamWriter(OutputStream out);

​ (2)OutputStreamWriter(OutputStream out, String charsetName);

​ 构造方法可以看出,OutputStreamWriter类可以在构造实例化对象的时候指定输出流的编码格式,并且是间接使用了字节流来进行操作的,即将字节流包成了字符流。

FileWriter类

​ 是OutputStreamWriter类的子类,常用构造方法如下:

​ (1)FileWriter(File file);

​ (2)FileWriter(String path);

​ 以上两种构造方法都可以重载,指定一个boolean类型的参数,用来指定追加还是覆盖文件内容,即:

​ (1)FileWriter(File file, boolean append);

​ (2)FileWriter(String path, boolean append);

​ 当append为true时,将在文件原内容末尾追加新写入的内容,否则将覆盖原文件内容。

BufferedWriter类

​ 与字符输入流相同,在字符输出流中也有个比较高效的方式,即通过BufferedWriter类来写文件。

​ BufferedWriter类是Writer类的子类,它带有缓冲区,常用构造方法如下:

​ BufferedWriter(Writer out);

​ 如果需要换行,可以使用newline()方法

使用BufferedWriter写文件的步骤:

(1)引入相关的类

	import java.io.FileWriter;
	import java.io.BufferedWriter;
	import java.io.IOException;

(2)构造BufferedWriter对象和FileWriter对象

	FileWriter fw =new FileWriter("c:\\myTest.txt");
	BufferedWriter bw =new BufferedWriter(fw);

(3)调用write()方法写数据

	bw.write("hello");

(4)关闭文件流对象

	bw.close();
    fw.close();

DataInputStream类

​ 如果需要读写一些二进制文件,就可以使用DataInputStream和DataOutputStream类。

​ DataInputStream类是FileInputStream的子类,它通过与FileInputStream类结合使用来读取二进制文件。

步骤如下:

(1)引入相关的类

	import java.io.FileInputStream;
	import java.io.DataInputStream;

(2)构造数据输入流对象

	FileInputStream fis =new FileInputStream("xxx.class");
	DataInputStream dis =new DataInputStream(fis);

(3)调用read()方法读取二进制数据

	dis.read();

(4)关闭数据输入流

	dis.close();
	fis.close();

与字节流FileInputStream类实现文本文件读取步骤极其相似。

DataOutputStream类

​ 是FileOutputStream的子类,通过与FileOutputStream类结合使用来写二进制文件。

步骤如下:

(1)引入相关的类

	import java.io.FileOutputStream;
	import java.io.DataOutputStream;

(2)构造数据输出流对象

	FileOutputStream fos =new FileOutputStream("c:\\temp.class");
	DataOutputStream dos =new DataOutputStream(fos);

(3)调用write()方法写二进制文件的数据

	dos.write();

(4)关闭数据输入流

	dos.close();
	fos.close();

序列化与反序列化

​ 前面所用的输入输出流针对的都是一些基本类型和String类型的数据在文件中的读写,如果要对一个对象数据进行文件中的读写操作,就需要用到序列化和反序列化。

在这里插入图片描述

序列化

​ 序列化是将对象的状态写入到特定的流中的过程。通过ObjectOutputStream类来实现。

​ 序列化的步骤如下:

​ (1)实现Serializable接口

​ (2)创建对象输出流(ObjectOutputStream)

​ (3)调用writeObject()方法将对象写入文件

​ (4)关闭对象输出流

​ 在序列化时常常会碰见异常:NotSerializableException。出现这种异常的原因是你要写的那个对象所在的类没有去实现Serializable接口,所以没有序列化的能力。

反序列化

​ 反序列化是从特定的流中获取数据重新构建对象的过程。通过ObjectInputStream类来实现。

​ 反序列化的步骤如下:

​ (1)实现Serializable接口

​ (2)创建对象输入流(ObjectInputStream)

​ (3)调用readObject()方法读取对象

​ (4)关闭对象输入流

​ 在反序列化时同样容易碰见异常:NotSerializableException。出现这种异常的原因是你要写的那个对象所在的类没有去实现Serializable接口,所以没有序列化的能力。

实现学员对象的序列化和反序列化实例:

import java.io.Serializable;

public class Student implements Serializable{
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private String name;
	private int age;
	
	public Student(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	public Student() {
		super();
	}
	@Override
	public String toString() {
		return "Student [name=" + name + ", age=" + age + "]";
	}
}
import java.io.*;

public class Test6 {

	public static void main(String[] args) {
		OutputStream os=null;
		ObjectOutputStream oos=null;
		InputStream fis =null;
		ObjectInputStream ois =null;
		try {
			Student stu =new Student("张三",18);
			os = new FileOutputStream("Object.txt");
			oos= new ObjectOutputStream(os);
			oos.writeObject(stu);
			
			fis =new FileInputStream("Object.txt");
			ois=new ObjectInputStream(fis);
			Student stu1 =(Student)ois.readObject();
			System.out.println(stu1);
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}finally {
			try {
				if(ois!=null) {
					ois.close();
				}
				if(fis!=null) {
					fis.close();
				}
				if(oos!=null) {
					oos.close();
				}
				if(os!=null) {
					os.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值