Java中的File和IO流

File对象

File对象本质是一个文件或文件夹,用于写入和读取文件内容
注意:对于相对路径而言,在单元测试方法中的File是相对于Module,在main中的File是相对于Project

构造器

  1. File(String pathname)

    java 复制代码
    File file1 = new File("D:\\workspace"); // 对应一个文件夹
    File file2 = new File("D:\\workspace\test.txt"); // 对应一个文件
  2. File(String parent, String child)

    java 复制代码
    File file = new File("D:\\workspace", "test.txt"); // 第一个参数是文件夹,第二个参数可以是文件/文件夹
  3. File(File parent, String child)

    java 复制代码
    File file1 = new File("D:\\workspace");
    File file2 = new File(file1, "test.txt"); // 第一个参数传入一个File对象,且这个对象必须是个文件夹

常用方法

获取文件信息

  1. getName():获取文件名称
  2. gePath():获取相对路径
  3. getAbsolutePath():获取文件绝对路径
  4. File getAbsoluteFile():获取绝对路径表示的文件
  5. getParent():获取上层目录路径
  6. length():获取文件所占的字节
  7. lastModified():获取文件最后修改的时间(毫秒数)
  8. exists():判断文件或目录是否存在
  9. isDirectory():是否是一个目录
  10. isFile():是否是一个文件
  11. canRead():是否可读
  12. canWrite():是否可写
  13. isHidden():是否隐藏

遍历文件内部

  1. String[] list():返回目录中最外层的所有子目录及子文件
  2. File[] listFiles():返回目录中最外层的所有子目录及子文件

操作文件

  1. renameTo(File) :重命名(文件移动)
    前提:源文件必须存在,目标文件必须不存在,且目标文件所在文件夹必须存在

    java 复制代码
    File file1 = new File("hello.txt"); // 假设hello.txt存在
    File file2 = new File("workspace", "world.txt"); // 假设workspace存在,world.txt不存在
    Boolean isSuccess = file1.renameTo(file2); // 是否移动成功
    System.out.println(isSuccess); // 是否成功
  2. createNewFile():创建文件,若文件存在,则返回false

    java 复制代码
    File file = new File("workspace/hello.txt");
    try {
    	System.out.println(file.createNewFile()); // 不存在返回true,文件已存在返回false
    } catch(IOException e) {
    	e.printStackTrace();
    }
  3. delete():删除文件或目录,若文件/目录不存在,返回false
    说明:
    ① 对于目录而言,只能删除空目录
    ② 删除不走回收站

  4. mkdir():创建一个目录,如果当前目录的上层目录不存在,则创建失败

    java 复制代码
    // 前提:只有workspace目录存在
    File file = new File("workspace/test.txt");
    file.mkdir(); // 创建成功
    File file = new File("workspace/a/test.txt"); // a目录和test.txt不存在
    file.mkdir(); // 创建失败
  5. mkdirs():创建多级目录,如果当前目录的上层目录也不存在,一并创建

    java 复制代码
    // 前提:只有workspace目录存在
    File file = new File("workspace/a/test.txt"); // a目录和test.txt不存在
    file.mkdirs(); // 创建成功(a目录和test.txt都被创建)

IO流

  1. 按流向划分:输入流、输出流
  2. 按操作数据单位划分:字节流、字符流
  3. 按IO流的角色划分 :节点流、处理流

IO流的基础类

抽象基类 文件流(节点流) 缓冲流(处理流) 转换流(处理流) 数据流(处理流) 对象流(处理流)
InputStream(字节流输入流) FileInputStream BufferedInputStream InputStreamReader DataInputStream ObjectInputStream
ouputStream(字节输出流) FileOutputStream BufferedOutputStream OutputStreamWriter DataOutputStream ObjectOutputStream
Reader(字符输入流) FileReader BufferedReader
Writer(字符输出流) FileWriter BufferedWriter
PrintStream(打印流)

说明

① 字符流一般用于读取txt文件,字节流一般用于读取mp3、mp4、jpg等文件

字节流 可以用于txt文件的复制,但是用于读取txt文件可能会出现乱码(如果遇到汉字,一个汉字占3个字节,可能读不完整)

缓冲流 可以提高文件的读写效率(相当于在文件和内存中间架了一层8kb的缓存区,先从文件中读取到缓存中,最后再一并读入到内存中)

④ 输出流中的flush()方法,可以手动将数据立即写入到磁盘中

转换流 可以将字节流转换为字符流,或者将字符流转换为字节流

数据流 只可以读写基本数据类型、String类型数据

对象流既可以读写基本数据类型、String类型数据,又可以读写引用类型数据

案例1:将磁盘中的文本文件读入内存中,并打印文件内容(使用字符输入流 FileReader)

java 复制代码
File file = new File("hello.txt");
FileReader fr = null;
try {
	fr = new FileReader(file);
	char[] cBuffer = new char[5]; // 用于存储批量读出来的字符
	int len; // 用于存储本次读取出的长度
	// 开始读入
	while((len = fr.read(cBuffer)) != -1) {
		// 遍历本次所有读出的字符
		for(int i = 0; i < len; i++) {
			System.out.println(cBuffer[i]);
		}
	}
} catch(IOException e) {
	e.printStackTrace();
} finally {
	// 关闭字符输入流
	try {
		if (fr != null) {
			fr.close(); 
		}
	} catch(IOException e) {
		e.printStackTrace();
	}
}

案例2:将内存中的文本数据写入到磁盘文件中(使用字符输出流FileWriter)

java 复制代码
FileWriter fw = null;
try {
	File file = new File("world.txt"); // 与目标文件做映射
	fw = new FileWriter(file); // 覆盖原有文件内容
	// fw = new FileWriter(file, true); // 在原有文件基础上,追加内容
	// 开始写入
	fw.write("这是写入的第一行内容...\n");
	fw.write("这是写入的第二行内容...\n");
	fw.write("这是写入的第三行内容...\n");
	System.out.println("写入成功");
} catch(IOException e) {
	e.printStackTrace();
} finally {
	// 关闭字符输出流 
	try {
		if (fw != null) {
			fw.close();
		}
	} catch(IOException e) {
		e.printStackTrace();
	}
}

案例3:复制某个文本文件中的内容到新文件中(使用节点流)

java 复制代码
FileReader fr = null;
FileWriter fw = null;
try {
	File srcFile = new File("test.txt"); // 映射源文件
	File destFile = new File("test_copy.txt"); // 映射目标文件
	fr = new FileReader(srcFile);
	fw = new FileWriter(destFile);
	char[] cBuffer = new char[5]; // 存储每次读取出来的字符
	int len; // 记录每次读取出的字符长度
	// 开始读取
	while((len = fr.read(cBuffer)) != -1) {
		// 开始写入
		fw.write(cBuffer, 0, len); // 写入cBuffer中从下标0开始的len长度数据
	}
	System.out.println("复制成功");
} catch(IOException e) {
	e.printStackTrace();
} finally {
	// 关闭输入流、输出流
	try {
		if (fr != null) fr.close();
	} catch(IOException e) {
		e.printStackTrace();
	}
	try {
		if (fw != null) fw.close();
	} catch(IOException e) {
		e.printStackTrace();
	}
}

案例4:复制jpg文件(使用字节流)

java 复制代码
FileInputStream fis = null;
FileOutputStream fos = null;
try {
	File srcFile = new File("workspace", "screen.jpg");
	File destFile = new File("workspace", "screen_copy.jpg");
	fis = new FileInputStream(srcFile);
	fos = new FileOutputStream(destFile);
	byte[] bBuffer = new byte[1024]; // 存储每次读取出来的字节
	int len; // 记录每次读取出来字节的长度
	// 开始读取
	while((len = fis.read(bBuffer)) != -1) {
		// 开始写入
		fos.write(bBuffer, 0, len);
	}
	System.out.println("复制成功");
} catch(IOException e) {
	e.printStackTrace();
} finally {
	// 关闭流
	try {
		if (fis != null) fis.close();
	} catch(IOException e) {
		e.printStackTrace();
	}
	try {
		if (fos != null) fos.close();
	} catch(IOException e) {
		e.printStackTrace();
	}
}

案例5:复制jpg文件(使用字节缓冲流)

说明:关闭处理流会自动关闭内层流

java 复制代码
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
	File srcFile = new File("workspace", "screen.jpg");
	File destFile = new File("workspace", "screen_copy.jpg");
	FileInputStream fis = new FileInputStream(srcFile);
	FileOutputStream fos = new FileOutputStream(destFile);
	bis = new BufferedInputStream(fis); // 将输入流用处理流包裹
	bos = new BufferedOutputStream(fos); // 将输出流用处理流包裹
	byte[] bBuffer = new byte[1024];
	int len;
	// 使用输入的处理流读取
	while((len = bis.read(bBuffer)) != -1) {
		// 使用输出的处理流写入
		bos.write(bBuffer, 0, len);
	}
	System.out.println("复制成功");
} catch(IOException e) {
	e.printStackTrace();
} finally {
	// 关闭处理流
	try {
		if (bis != null) bis.close();
	} catch(IOException e) {
		e.printStackTrace();
	}
	try {
		if (bos != null) bos.close();
	} catch(IOException e) {
		e.printStackTrace();
	}
}

案例6:复制文本文件(使用字符缓冲流)

说明:BufferReader增加了readLine()方法,可以一次性读取一行数据,但是换行不能读出来

java 复制代码
BufferedReader br = null;
BufferedWriter bw = null;
try {
	br = new BufferedReader(new FileReader(new File("workspace", "hello.txt"))); // 包裹字符输入流
	bw = new BufferedWriter(new FileWriter(new File("workspace", "hello_copy.txt"))); // 包裹字符输出流
	String data = null; // 存储本次读取出的一行数据
	while((data = br.readLine()) != null) {
		bw.write(data);
		bw.newLine(); // 换行
	}
	System.out.println("复制成功");
} catch(IOException e) {
	e.printStackTrace();
} finally {
	try {
		if (br != null) br.close();
	} catch(IOException e) {
		e.printStackTrace();
	}
	try {
		if (bw != null) bw.close();
	} catch(IOException e) {
		e.printStackTrace();
	}
}

案例7:将GBK类型的文件转为UTF-8类型的文件(使用转换流)

java 复制代码
InputStreamReader isr = null;
OutputStreamWriter osw = null;
try {
	File srcFile = new File("workspace", "hello_GBK.txt");
	File destFile = new File("workspace", "hello_UTF8.txt");
	isr = new InputStreamReader(new FileInputStream(srcFile), "GBK");
	osw = new OutputStreamWriter(new FileOutputStream(destFile), "UTF-8");
	char[] cBuffer = new char[5];
	int len;
	while((len = isr.read(cBuffer)) != -1) {
		String s = new String(cBuffer, 0, len);
		osw.write(s);
	}
	System.out.println("转换成功");
} catch(IOException e) {
	e.printStackTrace();
} finally {
	try {
		if (isr != null) isr.close();
	} catch(IOException e) {
		e.printStackTrace();
	}
	try {
		if (osw!= null) osw.close();
	} catch(IOException e) {
		e.printStackTrace();
	}
}

案例8:将Java对象存储在本地文件中,并从本地文件中把Java对象读取到内存中(使用对象流)

对象的序列化机制 :允许把内存中的Java对象转换成二进制流,从而允许把这种二进制流永久的保存在磁盘上,或者通过网络将这种二进制流传输到另一个网络节点,当其他程序获取到了这种二进制流,就可以恢复成原来的Java对象
序列化 :将Java对象转成二进制流的过程(ObjectOutputStream)
反序列化:将二进制流恢复成Java对象的过程(ObjectInputStream)

  1. 声明Person类和Account类
    注意:
    ① 自定义的类必须实现Serializable接口才能被序列化,并且需要声明static final long serialVersionUID(serialVersionUID是用于标识类的,如果不声明serialVersionUID,则当类改变时,serialVersionUID会自动改变)
    ② 自定义类中的各个属性也必须是可序列化的,比如本例中的Account
    ③ 类中的属性如果加上transient(瞬时的)或者static(属于类,跟对象无关)修饰,则这些属性不会被序列化,会以默认值保存到文件中

    java 复制代码
    public class Person implements Serializable{
    	private static final long serialVersionUID = 1L;
    	private String name;
    	private int age;
    	private Account account;
    	public Person() {}
    	public Person(String name, int age, Account account) {
    		this.name = name;
    		this.age = age;
    		this.account = account;
    	}
    	// ... setter、getter、toString等方法省略
    }
    class Account implements Serializable{
    	private static final long serialVersionUID = 2L;
    	private double balance;
    	public Account() {}
    	public Account(double balance) {
    		this.balance = balance;
    	}
    	// ... setter、getter、toString等方法省略
    }
  2. 将Java对象存储在本地文件中(序列化过程)

    java 复制代码
    ObjectOutputStream oos = null;
    try {
    	// 创建文件对象和对象流
    	File file = new File("object.dat");
    	oos = new ObjectOutputStream(new FileOutputStream(file));
    	// 开始序列化写入
    	oos.writeObject(new Person("a", 18, new Account(1000)));
    	oos.writeUTF("这是一段字符串");
    	System.out.println("写入完成");
    } catch(IOException e) {
    	e.printStackTrace();
    } finally {
    	// 关闭对象流
    	try {
    		if (oos != null) {
    			oos.close();
    		}
    	} catch(IOException e) {
    		e.printStackTrace();
    	}
    }
  3. 从本地文件中把Java对象读取到内存中(反序列化过程)

    java 复制代码
    ObjectInputStream ois = null;
    try {
    	// 创建文件对象和对象流
    	File file = new File("object.dat");
    	ois = new ObjectInputStream(new FileInputStream(file));
    	// 开始反序列化读入
    	Person p = (Person)ois.readObject();
    	System.out.println(p);
    	String s = (String)ois.readUTF();
    	System.out.println(s);
    	System.out.println("读取完成");
    } catch(IOException | ClassNotFoundException e) {	
    	e.printStackTrace();
    } finally {
    	// 关闭对象流
    	try {
    		if (ois != null) {
    			ois.close();
    		}
    	} catch(IOException e) {
    		e.printStackTrace();
    	}
    }

标准输入流:System.in

案例:从键盘输入,并转成大写输出

java 复制代码
BufferedReader br = null;
System.out.print("请输入(输入exit退出程序):");
try {
	// 这里使用BufferedReader,可以调用readLine()来读取输入的一整行数据。
	// 因为System.in是字节数据,所以需要使用转换流把字节流转换为字符流
	br = new BufferedReader(new InputStreamReader(System.in));
	String line;
	while((line = br.readLine()) != null) {
		if (line.equalsIgnoreCase("exit")) {
			break;
		}
		System.out.println(line.toUpperCase());
		System.out.print("请输入(输入exit退出程序):");
	}
} catch(IOException e) {
	e.printStackTrace();
} finally {
	try {
		if (br != null) {
			br.close();
		}
	} catch(IOException e) {
		e.printStackTrace();
	}
}

标准输出流:System.out

说明:System.out默认将内容打印到控制台中

案例:修改System.out默认行为,使用System.out输出到某个txt文件中

java 复制代码
PrintStream ps = null;
try {
	ps = new PrintStream(new FileOutputStream(new File(""test.txt")));
	ps.println("这是写入的第一行数据");
	ps.println("这是写入的第二行数据");
	// 修改System.out的默认输出方式:输出到test.txt中
	System.setOut(ps);
	System.out.println("这是写入的第三行数据");
} catch(FileNotFoundException e) {
	e.printStackTrace();
} finally {
	if (ps != null){
		ps.close();
	}
}
相关推荐
苏-言26 分钟前
SSM框架探秘:Spring 整合 Mybatis 框架
java·spring·mybatis
qq_447663051 小时前
java-----多线程
java·开发语言
a辰龙a1 小时前
【Java报错解决】警告: 源发行版 11 需要目标发行版 11
java·开发语言
听海边涛声1 小时前
JDK长期支持版本(LTS)
java·开发语言
IpdataCloud1 小时前
Java 获取本机 IP 地址的方法
java·开发语言·tcp/ip
MyMyMing1 小时前
Java的输入和输出
java·开发语言
忆~遂愿1 小时前
3大关键点教你用Java和Spring Boot快速构建微服务架构:从零开发到高效服务注册与发现的逆袭之路
java·人工智能·spring boot·深度学习·机器学习·spring cloud·eureka
Easonmax1 小时前
【javaSE】内部类(来自类和对象的补充)
开发语言·javascript·ecmascript
云夏之末1 小时前
【Java报错已解决】java.lang.UnsatisfiedLinkError
java·开发语言
计算机-秋大田2 小时前
基于SpringBoot的假期周边游平台的设计与实现(源码+SQL脚本+LW+部署讲解等)
java·vue.js·spring boot·后端·课程设计