第九章 文件处理(IO) ① 笔记

  1. 内容回顾
    1.1 课前测试
    1.2 上节内容

2. 本章重点

2.1. 文件对象的使用
2.2. 流的分类
2.3. 输入输出字节流的使用
2.4. 缓冲字节流
2.5. 对象流
2.6. 字符流
2.7. 缓冲字符流
2.8. 转换流
2.9. 格式化打印字符流
2.10. IO流异常处理
2.11. Properties文件的使用

3. 具体内容

3.1. 文件对象的使用

File:文件对象,用于表示磁盘上的文件夹或数据文件
在这里插入图片描述

3.1.1.文件的基本操作
public class Test {
	public static void main(String[] args) {
		// 文件对象: 数据文件,目录文件
		// 使用java程序处理文件: 1.创建文件 2.删除文件 3.向文件写内容 4.读取文件内容
		File f1 = new File("e:/aaa.txt");
		//File f2 = new File("e:\\aaa.txt");
		// File.separator:路径分隔符
		//File f3 = new File("e:"+File.separator+"aaa.txt");
		//System.out.println(File.separator);
		//获取文件名
		System.out.println(f1.getName());
		//获取文件的路径
		System.out.println(f1.getPath());
		System.out.println(f1.getAbsolutePath());
		//获取文件大小
		System.out.println(f1.length());
		//获取文件文件属性:是否可读写,是否可执行
		System.out.println(f1.canRead());
		System.out.println(f1.canWrite());
		System.out.println(f1.canExecute());
		// 获取文件对象是否是数据文件
		System.out.println(f1.isFile());
		// 获取文件对象是否是一个目录
		System.out.println(f1.isDirectory());
		// 获取文件是否存在
		System.out.println(f1.exists());
	}
}
public class Test2 {
	public static void main(String[] args) throws IOException {
		File f = new File("e:/qqq/iii/ppp");
		File f2 = new File("e:/qqq/iii/ppp/xxx.txt");
		// 如果文件不存在,则创建文件
		if(!f.exists()){ //判断文件是否存在
			System.out.println("===文件不存在,创建文件====");
			// 先创建目录
			f.mkdirs(); //创建多级目录
			// 创建文件
			f2.createNewFile(); // 创建文件
		}else{
			//System.out.println("输出文件内容");
			//System.out.println(f.length());
			//删除文件
			f.delete();
		}
	}
}

3.1.2.文件的遍历

public class Test {
	public static void main(String[] args) {
		// 列出指定文件目录下的第一层所有的文件信息
		File file = new File("d:/iotest");
		//listFiles() :返回指定目录下的第一级所有文件对象
		File[] fs = file.listFiles();
		// 遍历获取的文件数组
		for (int i=0;i<fs.length;i++){
			File f = fs[i];
			//System.out.println(f.getName()+" "+f.getPath());
			System.out.println(f.getPath());
		}
	}
}

3.1.3.文件的递归遍历

public class Test2 {
	public static void main(String[] args) {
		// 显示指定目录下的所有文件
		showAllFiles("d:/iotest");
	}
	public static void showAllFiles(String path){
		// 使用传入的路径构建文件对象
		File file = new File(path);
		// 如果文件不存在,或者文件不是一个目录,则直接返回,不做遍历
		if(!file.exists() || !file.isDirectory()){
			return;
		}
		// 如果文件对象是一个目录文件,获取文件下的所有文件
		File[] fs = file.listFiles();
		// 遍历文件数组
		for(File f: fs){
			//System.out.println(f.getPath());
			// 如果遍历到的文件是一个目录,需要继续输出它里面的文件
			if(f.isDirectory()){
				System.out.println(f.getPath()+" <DIR>");
				// 继续遍历这个目录文件内部的文件信息
				showAllFiles(f.getPath()); // 递归调用
			}else{
				// 如果遍历到的文件是一个数据文件,则直接输出文件信息
				System.out.println(f.getPath()+" "+f.length());
			}
		}
	}
}

3.2 IO数据流的使用

流: 水流(有方向,有基本的构成单位:水滴),车流(有方向,基本单位:车)
数据流:以字节或字符为单位按特定的方向传送就构成了数据流。

3.2.1 流的分类

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

3.2.2 输入输出字节流的使用

字节流
在这里插入图片描述
在这里插入图片描述
输入字节流
抽象类:InputStream 程序可以从目标中连续读取字节的对象称为字节输入流
实现类:FileInputStream
在这里插入图片描述
输出字节流
抽象类:OutputStream 程序可以向其中连续写入字节的对象称为字节输出流
实现类:FileOutputStream
在这里插入图片描述
流的使用步骤:
在这里插入图片描述

// 字节数组和字符串的转换
public class Test2 {
	public static void main(String[] args) {
		/*
		String s = "abcde";
		byte[] bs = s.getBytes(); // 将字符串转为字节数组
		for(byte b : bs){
			System.out.println(b);
		}*/
		// 将字节数组转为字符串
		byte[] bs = {101,102,103,104,105};
		//String s = new String(bs); //将字节数组转为字符串
		//System.out.println(s);
		String s = new String(bs,1,3); // 使用字节数组中,指定位置指定长度的内容构
		System.out.println(s);
	}
}
public class Test1 {
	// 将数据写到文件中
	public static void w() throws IOException {
	//1. 创建一个目标文件对象
		File file = new File("d:/0214.txt");
		//2. 创建文件输出字节流对象, 用于将数据写到文件中
		// 通过append参数,配置是否以追加的方式写内容
		OutputStream os = new FileOutputStream(file,true);
		//3. 使用输出流对象将数据写到文件中
		//os.write(97); // 写一个字节数据到文件
		String msg = "I love you";
		os.write(msg.getBytes()); // 将字符串转为字节数组
		//4. 关闭流对象,节省系统资源(关闭水龙头)
		os.close();
	}
	// 将文件中的数据读取到程序中
	public static void r() throws IOException {
		//1. 创建目标文件对象
		File file = new File("d:/0214.txt");
		//2. 创建文件输入流对象用于读取文件内容
		InputStream is = new FileInputStream(file);
		//3. 使用输入流对象读取文件内容
		// 定义字节数组,用于存储读取的内容
		byte[] bs = new byte[1024];
		int count = is.read(bs); // 将读取的文件中的数据存储到字节数组中,并返回
		//4.输出信息
		System.out.println("读取的字节长度:"+count);
		/*for (byte b : bs){
			System.out.println(b);
		}*/
		// 将字节数组的内容,构建成字符串,从0的位置开始,指定数据长度
		String s = new String(bs,0,count);
		System.out.println(s);
		// 测试第二次读取
		//count = is.read(bs); // 读取的字节数是-1,说明读取结束
		//System.out.println("第二次读取的字节数:"+count);
		// 5.关闭流对象
		is.close();
	}
	public static void main(String[] args) throws IOException {
		//w(); // 将数据写到文件中
		r(); // 调用读取方法
	}
}
3.2.3 缓冲字节流(处理流/包装流)

缓冲流:缓冲流是一个处理流,在普通流的基础上添加了缓冲区,能够在传输数据的时候
提升读取或写入效率。
好处:
1.不带缓冲的流读取到一个字节或字符就直接输出
2.带有缓冲的流读取到一个字节或字符先不输出,等达到缓冲区容量再一次性写出
在这里插入图片描述
图:
在这里插入图片描述

注意:缓冲字节流写入时需要关闭缓冲流,或者bos.flush()清空缓冲区,才能正常输入(缓冲在缓冲区,关闭/清空缓冲流才能输入)。
输入字节流写入时,无论是否关闭缓冲流都能正常输入(直接输入)。

在这里插入图片描述

public class Test1 {
	// 写数据
	public static void w() throws IOException {
		// 1.创建目标文件对象
		File file = new File("d:/aaa.txt");
		// 2.创建字节流输出流对象,创建缓冲流对象
		OutputStream os = new FileOutputStream(file);
		// 创建缓冲流对象(处理流、包装流)
		BufferedOutputStream bos = new BufferedOutputStream(os);
		// 3.使用缓冲流写内容
		bos.write("abcdefg".getBytes());
		// 4.关闭缓冲流和字节流,多个流对象的关闭次序:先使用的后关闭,后使用的先关闭
		bos.flush(); // 清空缓冲区
		bos.close(); // 关闭缓冲流对象
		os.close(); // 关闭字节流对象
	}
	// 读数据
	public static void r() throws IOException {
		// 1. 创建目标文件对象
		File file = new File("d:/aaa.txt");
		// 2. 创建字节流输入流和缓冲流对象
		//InputStream is = new FileInputStream(file);
		BufferedInputStream bis = new BufferedInputStream(FileInputStream(file));
		// 3. 使用缓冲流读取内容
		byte[] bs = new byte[1024];
		int count = bis.read(bs);
		System.out.println("读取的个数:"+count);
		String s = new String(bs,0,count);
		System.out.println("读取的内容:"+s);
		// 4. 关闭流对象
		bis.close();
	}
	public static void main(String[] args) throws IOException {
		//w(); // 使用缓冲流写数据
		r(); // 读取内容
	}
}

缓冲流实现图片复制:
在这里插入图片描述

package com.yzh70707.test1;

import java.io.*;

/**
 * @author: XYT
 * @create-date: 2022/7/7 10:13
 */
public class TuPianFuZhi {
    public static void copy(String pathscr1,String pathscr2) throws IOException {
        //缓冲输入
        File file=new File(pathscr1);
        InputStream is=new FileInputStream(file);
        BufferedInputStream bis=new BufferedInputStream(is);
        //缓冲输出
        File file1=new File(pathscr2);
        OutputStream is2=new FileOutputStream(file1);
        BufferedOutputStream bos=new BufferedOutputStream(is2);
        //设置字节数组 用于存放读取的内容 //注意
        byte[] b=new byte[1024];
        while (true){
            //设置变量 表示读取的字节个数 //注意
            int count=bis.read(b);
            //判断读取是否为空
            if(count==-1){
                break;
            }
        }
        //清空缓冲
        bis.close();
        //关闭流 //注意:先使用的后关闭 后使用的先关闭
        bos.close();
        bis.close();
    }

    public static void main(String[] args) throws IOException {
        //调用方法 通过实例对象调用
        TuPianFuZhi tuPianFuZhi=new TuPianFuZhi();
        tuPianFuZhi.copy("D:/shuaige.jpg","D:/shuaige2.jpg");
        System.out.println("输出成功");
    }
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

缓冲流实现文件复制

在这里插入图片描述

public class Test2 {
	public static void main(String[] args) throws IOException {
		// 使用缓冲字节流复制文件
		// 将文件e:/getcolor.exe 复制到 f:/xxx.exe
		// 源文件
		File srcFile = new File("e:/getcolor.exe");
		// 目标文件
		File destFile = new File("f:/xxx.exe");
		// 创建缓冲文件流
		// 缓冲输入流
		BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFile));
		// 缓冲输出流
		BufferedOutputStream bos = new BufferedOutputStream(new FileInputStream(destFile));
		// 循环读取复制
		byte[] bs = new byte[1024];
		while (true){
			int count = bis.read(bs); // 读取一批内容存储byte数组,返回读取个数
			// 读取个数为-1,说明读取结束
			if (count==-1){
				// 退出循环
				break;
			}
			// 如果读取到内容,则将内容写出去
			bos.write(bs,0,count);
		}
		// 关闭流对象
		bos.close();
		bis.close();
	}
}
3.2.4 对象流(处理流/包装流)

idea自动生成序列化id的配置
File—》settings—》Editor–》 inspections–》java—》Serialization issues-
–》Serializable class without ‘serialVersionUID’—》打对勾。
在这里插入图片描述
在这里插入图片描述
序列化版本号的使用:

  1. 在类上加序列化版本号定义:serialVersionUID
  2. 序列化对象到磁盘上
  3. 修改类:添加属性
  4. 反序列化,此时能正常处理
    对象流:可以将内存中的对象数据序列化到磁盘文件中
     ObjectInputStream 将文件中的对象读取到程序中。
     ObjectOutputStream 将程序中的对象写入到文件中。
    序列化和反序列化 Serializable 实现
     序列化 (Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程。在
    序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存
    储区中读取或反序列化对象的状态,重新创建该对象。比如:存储游戏进度,下次
    再接着玩
     反序列化:反向操作。将数据从存储状态恢复到内存中。
注意:1.如果要将一个对象序列化到磁盘上,那么该对象必须实现Serializable接口
	2.为了保证类的一致性,需要在类中定义版本序列号serialVersionUID
	3.如果类中某个属性不需要序列化,则可以给该字段标记transient
//注意:1.如果要将一个对象序列化到磁盘上,那么该对象必须实现Serializable接口
// 2.为了保证类的一致性,需要在类中定义版本序列号serialVersionUID
public class Game implements Serializable {
	private static final long serialVersionUID = 4267181850311063747L;
	// 配置当前类的版本号,用于反序列化时,能够正常识别为原始的类型,保持类的一致性
	//private static final long serialVersionUID=1234123123;
	// 游戏名字
	private transient String name; //transient:当一个字段不需要序列化的时候,加该
	// 关卡
	private int guanka;
	public Game(String name, int guanka) {
		this.name = name;
		this.guanka = guanka;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getGuanka() {
		return guanka;
	}
	public void setGuanka(int guanka) {
		this.guanka = guanka;
	}
	@Override
	public String toString() {
		return "Game{" +
		"name='" + name + '\'' +
		", guanka=" + guanka +
		'}';
	}
}

public class Test {
	// 写对象数据
	public static void w() throws IOException {
		//1.目标文件
		File file = new File("d:/game.obj");
		//2.文件流,对象流
		OutputStream os = new FileOutputStream(file); //文件流
		ObjectOutputStream oos = new ObjectOutputStream(os); //对象流
		//3.写目标数据
		Game game=new Game("荣耀",5);
		oos.writeObject(game);
		//4.关闭流
		oos.close();
		os.close();
	}
	// 读对象数据
	public static void r() throws IOException, ClassNotFoundException {
		File file =new File("d:/game.obj");
		// 文件流,对象输入流
		InputStream is = new FileInputStream(file);
		ObjectInputStream ois = new ObjectInputStream(is);
		// 读取对象数据
		Game game = (Game) ois.readObject();
		System.out.println(game);
		// 关闭
		ois.close();
		is.close();
		}
		public static void main(String[] args) throws IOException, ClassNotFoundException {
		//w();
		r();
	}
}
3.2.5 字符流

字符流:以字符为基本单位进行数据的传输

3.2.5.1 输入字符流

抽象类:Reader
实现类:FileReader
在这里插入图片描述

3.2.5.2 输出字符流

抽象类:Writer
实现类:FileWriter

在这里插入图片描述

public class Test {
	// 写数据
	public static void w() throws IOException {
		//1.创建目标文件对象
		File file = new File("d:/qy149.txt");
		//2.创建字符输出流对象
		//Writer writer = new FileWriter("d:/qy149.txt");// 写目标文件路径
		Writer writer = new FileWriter(file); // 写目标文件对象
		//3.写数据到磁盘
		//char[] cs = {'我','爱','中','国'};
		//writer.write(cs);
		writer.write("我爱北京天安门");
		//4.关闭流
		writer.close();
	}
	//读取数据
	public static void r() throws IOException {
		//1.定义目标文件对象
		File file = new File("d:/qy149.txt");
		//2.创建字符串输入流
		Reader reader = new FileReader(file);
		//3.读取数据
		char[] cs = new char[1024];
		int count = reader.read(cs);
		System.out.println("读取的内容个数:"+count);
		// 将读取的字符数组,转为字符串
		String s = new String(cs,0,count);
		System.out.println("读取的内容是:"+s);
		//4.关闭流
		reader.close();
	}
	public static void main(String[] args) throws IOException {
		//w();
		r();
	}
}
3.2.6 缓冲字符流

BufferedReader: 缓冲字符输入流
BufferedWriter: 缓冲字符输出流

public class Test {
	// 缓冲输出字符流
		public static void w() throws IOException {
		//1.目标文件对象
		File file = new File("d:/aaa.txt");
		//2.输出字符流对象,缓冲输出字符流对象
		BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(file));
		//3.使用缓冲流写数据
		bufferedWriter.write("今天是元宵节,吃元宵");
		//4.关闭流
		bufferedWriter.close();
	}
	// 缓冲输入字符流
	public static void r() throws IOException {
		//1.目标文件
		File file = new File("d:/aaa.txt");
		//2.字符输入流,缓冲输入字符流
		BufferedReader bufferedReader = new BufferedReader(new FileReader(file));
		//3.读取数据
		String str = bufferedReader.readLine();
		System.out.println("读取的内容:"+str+" 长度:"+str.length());
		//4.关闭流
		bufferedReader.close();
	}
	public static void main(String[] args) throws IOException {
		// 缓冲输出字符流
		//w();
		r(); //读取内容
	}
}
3.2.7 字节字符转换流(处理流/包装流)

InputStreamReader 将字节输入流转换成字符输入流
OutputStreamWriter 将字符输出流转为字节输出流

在这里插入图片描述
在这里插入图片描述
InputStreamReader(InputStream in); 将读取的字节流抓换成字符流
OutputStreamWriter(outPutStream os);将书写的字符流转换成字节流写到文件
里。
InputStreamReader(InputStream in,“gb2312”); //将读取的字节流抓换成字符流,可
以指明编码格式
OutputStreamWriter(outPutStream os,“utf-8”); //将书写的字符转换成字节流
——可以指明编码格式
转换流就是对字节流的封装,将字节流封装成一个字符流,可以指明编码格式。字符流
要关闭。
默认按照GBK的编码转化。
注意:字节流可以用来操作所有文件,字符流操作文本文件!

public class Test2 {
	// 字节字符输出流
	public static void w() throws IOException {
		//1.目标文件
		File file = new File("d:/demo.txt");
		//2.定义字节字符输出流对象
		OutputStream os = new FileOutputStream(file);
		OutputStreamWriter osw = new OutputStreamWriter(os); //底层依赖于字节流
		//3.写数据
		osw.write("今天天气不错,风和日丽");
		//4.关闭流
		osw.close();
		os.close();
		// 用缓冲流包装字符流,再包装字节流
		//BufferedWriter b = new BufferedWriter(new OutputStreamWriter(new F
	}
	//字节字符输入流
	public static void r() throws IOException {
		//1.目标文件对象
		File file = new File("d:/demo.txt");
		//2.字节字符输入流
		//InputStreamReader iss = new InputStreamReader(new FileInputStream(
		// 用缓冲流包装字符输入流
		//BufferedReader bufferedReader = new BufferedReader(iss);
		// 缓冲流->字节字符流->字节流
		BufferedReader bufferedReader = new BufferedReader(new InputStreamRe
		//3.读取数据
		String str = bufferedReader.readLine();
		System.out.println(str);
		//4.关闭流
		bufferedReader.close();
		//iss.close();
	}
	public static void main(String[] args) throws IOException {
		// 字节字符输出
		//w();
		r();
	}
}
3.2.8 格式化打印流(对于输出流的功能进行增强)

PrintWriter: 是Writer的子类,其作用是将格式化对象打印到一个文本输出流, 主要方
法:print()、println()、write()

public class Test {
	public static void main(String[] args) throws FileNotFoundException {
		//PrintWriter:打印输出字符流,将内容写到文件中
		PrintWriter out = new PrintWriter("d:/aaa.txt");
		out.println("这是第1行内容");
		out.println("这是第2行内容");
		out.println("这是第3行内容");
		out.println("这是第4行内容");
		out.println("这是第5行内容");
		String name="张三";
		String sex = "男";
		int age = 20;
		double tall = 1.7;
		//占位符: %s 字符串 %d 整数 %f 小数
		// 格式化输出
		out.printf("姓名:%s 性别:%s 年龄:%d 身高:%f",name,sex,age,tall);
		// 清空缓冲区
		out.flush();
		// 关闭流
		out.close();
	}
}
3.2.9 IO流中的异常处理
public class Test {
	public static void main(String[] args) {
		// IO流的异常处理
		// 实现文件复制
		String srcPath = "d:/aaa.txt"; //原始文件
		String destPath = "f:/xxx.txt"; //目标文件
		//再try代码块外部定义变量,这样finally代码块就可以使用这个变量
		InputStream is = null;
		OutputStream os = null;
		try {
			// 字节输入流
			is = new FileInputStream(srcPath);
			// 字节输出流
			os = new FileOutputStream(destPath);
			// 定义缓存数组,用于存储读取内容
			byte[] bs = new byte[1024];
			//int count = is.read(bs);
			while (true){
				// 读取一次
				int count = is.read(bs);
				// 判断读取的数据个数,如果个数是-1,说明读取结束
				if(count==-1){
					// 读取结束
					break;
				}
				// 将读取的内容写到文件中
				os.write(bs,0,count);
			}
		} catch (FileNotFoundException e) {
			// FileNotFoundException:文件不存在异常
			e.printStackTrace();
		} catch (IOException e) {
			// IOException: 输入输出异常(读写文件异常)
			e.printStackTrace();
		}finally {
			//为了确保一定执行关闭操作,把关闭的代码放入finally
			// 先判断输出流不为空,再进行关闭
			if(os!=null){
				try {
					os.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			//先判断输入流不为空再关闭
			if(is!=null){
				try {
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		System.out.println("==========================");
	}
}
3.2.10 Properties文件的使用

在src跟目录下创建properties文件

在这里插入图片描述
a. 创建 .properties 文件
b. 创建Properties类对象,加载 .properties 文件
c. 访问属性文件中的键值对数据

public static void main(String[] args) throws IOException {
	// 键值对集合(Map接口的实现类)(属性文件处理类)
// 	Properties properties = new Properties();
// 	properties.put("aaa",100);
// 	properties.put("bbb",200);
// 	System.out.println(properties);
	// 使用Properties处理properties文件(键值对文本文件)
	// 1.在src根目录下新建文本文件,命名为 xxx.properties
	// 2.使用当前类的加载器获取my.properties文件的字节输入流
	InputStream is = MyTest2.class.getClassLoader().getResourceAsStream(
	//System.out.println(is);
	// 3. 使用Properties对象来加载文件字节流
	Properties p = new Properties();
	// 加载properties文件生成的字节流,将文件中的键值对存储到Properties对象中
	p.load(is);
	// 4. 访问Properties对象中的数据
	System.out.println(p.getProperty("aaa"));
	System.out.println(p.getProperty("bbb"));
	System.out.println(p.getProperty("ccc"));
	System.out.println(p.getProperty("ddd"));
}

4. 本章总结

 文件对象的使用
 流的分类
 输入输出字节流的使用
 缓冲字节流
 对象流
 字符流
 缓冲字符流
 转换流
 格式化打印字符流
 IO流异常处理
 Properties文件的使用

5. 课后作业

文件遍历,以树状结构显示
在这里插入图片描述
 实现指定目录下所有文件的复制功能:遍历目录,复制文件
 使用缓冲字符流实现文件读取。循环方式读取内容,读取结束的条件(读取的内容为null)
 要求能独立画出IO类的结构图

 使用java程序读取网站小说并存储到本地【扩展】

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值