Java从入门到入土|[Java] 神秘的IO流 (下)

信仰:一个人走得远了,就会忘记自己为了什么而出发,希望你可以不忘初心,不要随波逐流,一直走下去
欢迎关注点赞收藏留言
本文由 程序喵正在路上 原创,CSDN首发!
系列专栏:Java从入门到入土
首发时间:2022年7月8日
? 如果觉得博主的文章还不错的话,希望小伙伴们三连支持一下哦

阅读指南
  • 常用的I/O处理方式
    • ? 文件类
      • 创建文件类
      • File类的常用方法
    • ? 文件的字节输入/输出流
      • 创建文件字节输入流
      • 创建文件字节输出流
      • 文件字节输入/输出流的应用
        • 1. 创建FileInAndOut类
        • 2. loadConfig()方法
        • 3. putConfig()方法
    • ? 文件的字符输入/输出流
      • 创建文件字符输入流
      • 创建文件字符输出流
      • 文件字符输入/输出流的应用
        • 1. 创建FileInAndOutChar类
        • 2. readFile()方法
        • 3. writeFile()方法
    • ? 带缓存的输入/输出流
      • BufferedInputStream 与 BufferedOutputStream 类
      • BufferedReader 与 BufferedWriter 类
    • ? 对象序列化
  • 文件及文件夹操作
    • ? 复制文件
    • ? 复制文件夹
    • ? 删除文件
    • ? 分行写入文件

常用的I/O处理方式 之前我们学习了 InputStream 类、OutputStream 类、Reader 类和 Writer 类,所有流的操作类都是它们其中某个类的子类。但是这 4 个类只定义了操作流的方法,并没有具体的方法实现。
要处理文件或音频等数据流,必须使用指定设备的数据流类
? 文件类 在开始使用数据流之前,首先介绍有关 File 文件类的使用方法,这是因为数据流可以将数据写入到文件中,另外,文件也是数据流最常用的数据媒体。
File 类用于封装系统的文件和目录的相关信息,如文件大小、修改时间、文件路径等。
创建文件类
创建 File 类可以使用它的构造方法,下面介绍一下该类的常用构造方法。
(1) File(String pathname) 方法
该构造方法通过指定的文件路径字符串来创建一个新的 File 实例对象。
语法如下:
new File(filePath);

filePath:文件路径字符串,包括文件名称,如 “C:/test.txt”。
(2) File(String parent, String child) 方法
该构造方法根据指定的父路径字符串和子路径字符串(包括文件名称)创建 File 类的实例对象。
语法如下:
new File(parent, child);

parent:父路径字符串,如 “D:/doc/”。
child:子路径字符串,如 “test.txt”。
(3)File(File parent, String child)方法
该构造方法根据指定的File类的父路径和字符串类型的子路径(包括文件名称)创建File类的实例对象。
语法如下:
new File(parent, child);
? parent:父路径对象,如new File(“D:/demo/”)。
? child:子路径字符串,例如 “help.txt”。
File类的常用方法
File 类是对文件和文件夹的抽象,包含文件和文件夹的多种属性和操作方法。
File 类的常用方法如下表所示。
返回类型 方法名称 说明
String getName() 获取文件名称
String getParent() 获取文件的父路径字符串
String getPath() 获取文件的相对路径字符串
String getAbsolutePath() 获取文件的绝对路径字符串
boolean exists() 判断文件或文件夹是否存在
boolean isFile() 判断是不是文件类型
boolean isDirectory() 判断是不是文件夹类型
boolean isAbsolute() 判断是不是绝对路径
boolean delete() 删除文件或文件夹,如果删除成功,返回结果为 true
boolean mkdir() 创建文件夹,如果创建成功,返回结果为 true
boolean mkdirs() 创建路径中包含的所有父文件夹和子文件夹,如果所有父文件夹和子文件夹都成功创建,返回结果为 true
boolean setReadOnly() 设置文件或文件夹的只读属性
long length() 获取文件的长度
long lastModified() 获取文件的最后修改日期
String[] list() 获取文件夹中的文件和子文件夹的名称,并存放到字符串数组中
File[] listFiles() 获取文件夹中的文件和子文件夹的名称,并存放到 File 类型的数组
下面我们通过一个实例来了解如何使用 File 类获取文件信息。
首先,我们在桌面创建一个 txt 文件用来测试,然后创建一个 GetFileInfo 类。编写主方法,在主方法中根据指定文件路径创建 File 文件类的实例对象,并将文件的各种属性输出到控制台。
import java.io.File; import java.util.Date; public class GetFileInfo { public static void main(String[] args) {//根据开发环境指定文件路径 String filePath = "C:\\Users\\15269\\Desktop\\test.txt"; //创建文件对象 File file = new File(filePath); //输出文件属性 System.out.println("文件名称:" + file.getName()); System.out.println("文件是否存在:" + file.exists()); System.out.println("文件的相对路径:" + file.getPath()); System.out.println("文件的绝对路径:" + file.getAbsolutePath()); System.out.println("文件上级路径:" + file.getParent()); System.out.println("文件大小:" + file.length() + "B"); System.out.println("是否是文件类型:" + file.isFile()); System.out.println("是否是文件夹类型:" + file.isDirectory()); System.out.println("文件是否可以读取:" + file.canRead()); System.out.println("文件是否可以写入:" + file.canWrite()); System.out.println("文件是否可执行:" + file.canExecute()); System.out.println("文件最后修改时间:" + new Date(file.lastModified())); } }

该实例的运行结果如下:
Java从入门到入土|[Java] 神秘的IO流 (下)
文章图片

? 文件的字节输入/输出流 在程序运行期间,大部分数据都是在内存中进行操作的,当程序结束或关闭时,这些数据将完全消失,但是有些数据需要永久保存,如程序的配置信息、日志信息等。那么我们该怎么办呢?
使用文件输入/输出流,可以和指定的文件建立关联,然后把需要永久保存的数据输出到文件中,程序在下次运行时,可以从文件中取回这些数据。
创建文件字节输入流
文件字节输入流可以从指定路径的文件中读取字节数据。文件字节输入流继承自 InputStream 类,并实现了读取输入流的各种方法。要使用文件字节输入流,必须使用构造方法创建它的实例对象。
创建文件字节输入流的常用构造方法如下。
(1) FileInputStream(File file) 方法
使用 File 类型的文件对象创建 FileInputStream 类的实例对象。
语法如下:
new FileInputStream(file);

file:File 文件类型的实例对象。
(2) FileInputStream(String name) 方法
根据指定的文件名称和路径,创建 FileInputStream 类的实例对象。
语法如下:
new FileInputStream(filePath);

filePath:文件的绝对路径或相对路径。
创建文件字节输出流
文件字节输出流关联指定路径的文件,数据通过文件字节输出流以字节为单位输出并保存到文件中。字节文件输出流继承自 OutputStream 类,并实现了输出数据的各种方法。要使用文件字节输出流,必须使用构造方法创建它的实例对象。
创建文件字节输出流的常用构造方法如下。
(1) FileOutputStream(File file) 方法
该构造方法使用 File 类型的文件对象,创建与该文件关联的 FileOutputStream 类的实例对象。
语法如下:
new FileOutputStream(file);

file:File 文件类型的实例对象。
(2) FileInputStream(String name) 方法
该构造方法根据指定的文件名称和路径,创建关联该文件的 FileOutputStream 类的实例对象。
语法如下:
new FileOutputStream(filePath);

filePath:文件的绝对路径或相对路径。
文件字节输入/输出流的应用
字节输/输出流的父类 InputStream 类和 OutputStream 类已经定义了访问数据流的基本方法,文件字节输入/输出流针对文件类型实现了这些访问数据流的方法。
下面我们通过一个实例来了解如何使用文件字节输入/输出流读写指定的文本文件。
本实例在第一次运行时,将运行次数、运行时间和操作系统的名称保存到配置文件中,在第二次运行时,会从配置文件中读取上次运行实例的信息。
1. 创建FileInAndOut类 创建 FileInAndOut 类,定义类的运行次数、运行时间、操作系统名称等属性,然后编写主方法,在主方法中调用 loadConfig() 方法从 “myProgram.cfg” 配置文件中获取程序上次运行时的属性信息。如果没有配置文件或者配置文件中没有内容,将在控制台输出 “这是程序第一次运行,其他信息还没有初始化。” 的信息,否则输出程序上次运行时定义的属性信息,并且将本次程序运行的属性通过调用 putConfig() 方法保存到配置文件中。
import java.io.File; import java.util.Date; public class FileInAndOut { private static String filePath = "./myProgram.cfg"; private static File file = new File(filePath); //程序运行次数 private static int runCount = 0; //上次运行时间 private static String date = String.format("%tF %

2. loadConfig()方法 定义装载配置信息的 loadConfig() 方法,该方法首先判断配置文件是否存在,如果不存在配置文件,就调用 createNewFile() 方法创建一个。然后创建文件字节输入流对象 fis,并且从输入流中读取配置文件的属性配置信息,通过解析属性配置信息,更新程序的属性值,关键代码如下。
//装载配置信息 private static void loadConfig() { try { //如果文件不存在 if (!file.exists()) //创建新文件 file.createNewFile(); byte[] data = https://www.it610.com/article/new byte[64]; //创建文件字节输入流 FileInputStream fis = new FileInputStream(file); //在循环中读取输入流的数据 int rs = 0; while ((rs = fis.read(data))> 0) { dataStr += new String(data, 0, rs); }if(!dataStr.isEmpty()){ //使用读取的数据初始化属性信息 String[] sets = dataStr.split(","); runCount = Integer.parseInt(sets[0]); date = sets[1]; os = sets[2]; }//关闭输出流 fis.close(); } catch (Exception e) { e.printStackTrace(); } }

3. putConfig()方法 定义保存配置信息的 putConfig() 方法,该方法首先判断配置文件是否存在,如果不存在就创建一个。然后将程序的属性使用 “,” 符号连接成字符串,并输出到配置文件中,最后刷新并关闭文件字节输出流,关键代码如下。
//保存配置信息 private static void putConfig(){ String dataStr; try{ //如果文件不存在 if(!file.exists()) //创建新文件 file.createNewFile(); dataStr = (runCount+1) + "," + date + "," + os; byte[] data = https://www.it610.com/article/dataStr.getBytes(); FileOutputStream fout = new FileOutputStream(file); //将数据写入输出流 fout.write(data); //刷新缓冲区 fout.flush(); //关闭输出流 fout.close(); }catch (Exception e){ e.printStackTrace(); } }

第一次运行该实例,结果如下:
Java从入门到入土|[Java] 神秘的IO流 (下)
文章图片

第二次运行该实例,结果如下:
Java从入门到入土|[Java] 神秘的IO流 (下)
文章图片

? 文件的字符输入/输出流 文件的字符输入/输出流和文件的字节输入/输出流有相同的功能,但是传送数据的方式不一样,字节流以字节为单位传送数据,可以是任何类型的数据,如文本、音频、视频、图片等,而字符流以字符为单位传送数据,只能传送文本类型的数据。
创建文件字符输入流
文件字符输入流可以从指定路径的文件中读取字符数据。文件字符输入流继承自 Reader 类,并实现了读取字符输入流的各种方法。要使用文件字符输入流,必须使用构造方法创建它的实例对象。
创建文件字符输入流的常用构造方法如下。
(1) FileReader(File file) 方法
使用 File 类型的文件对象创建 FileReader 类的实例对象。
语法如下:
new FileReader(file);

file:File 文件类型的实例对象。
(2) FileReader(String name) 方法
根据指定的文件名称和路径,创建 FileReader 类的实例对象。
语法如下:
new FileReader(filePath);

filePath:文件的绝对路径或相对路径。
创建文件字符输出流
文件字符输出流关联指定路径的文件,数据通过文件字符输出流以字符为单位输出并保存到文件中。文件字符输出流继承自 Writer 类,并实现了向文件输出数据的各种方法。要使用文件字符输出流,必须使用构造方法创建它的实例对象。
创建文件字符输出流的常用构造方法如下。
(1) FileWriter(File file) 方法
使用 File 类型的文件对象,创建与该文件关联的 FileWriter 类的实例对象。
语法如下:
new FileWriter(file);

file:File 文件类型的实例对象。
(2) FileWriter(String name) 方法
根据指定的文件名称和路径,创建与该文件关联的 FileWriter 类的实例对象。
语法如下:
new FileWriter(filePath);

filePath:文件的绝对路径或相对路径。
文件字符输入/输出流的应用
文件字符输入/输出流的父类 Reader 和 Writer 类已经定义了访问数据流的基本方法,文件字符输入/输出流针对文件类型实现了这些访问数据流的方法。
下面我们通过一个实例来了解如何使用文件输入流和文件输出流,读写指定的文本文件。
本实例创建了关联程序源代码文件(即 FileInAndOutChar.java 文件)的文件字符输入流,通过该输入流读取文件信息到 StringBuilder 类的实例对象(即字符串生成器对象)strBuilder 中,并在控制台显示 strBuilder 对象的内容,然后将这些内容通过文件字符输出流保存到实例所在路径下的 FileInAndOutChar.bak 文件中。
温馨提示:
如果你将 FileInAndOutChar.java 类创建在其他包中,需要根据自己定义的路径进行修改。
1. 创建FileInAndOutChar类 创建 FileInAndOutChar 类,编写主方法,在主方法中定义 StringBuilder 类的实例对象 strBuilder,调用 readFile() 方法读取程序源代码到 strBuilder 对象中,然后把 strBuilder 对象的内容输出到控制台,并通过 writeFile() 方法保存到 FileInAndOutChar.bak 文件中,关键代码如下。
public static void main(String[] args) { StringBuilder stringBuilder = new StringBuilder(); //调用读取字符输入流数据的方法 readFile(stringBuilder); System.out.println(stringBuilder); //调用写入数据到字符输出流的方法 writeFile(stringBuilder); }

2. readFile()方法 编写读取字符输入流数据的 readFile() 方法,在该方法中创建文件字符输入流 fReader,通过该文件字符输入流获取文件的内容到 strBuilder 对象中,关键代码如下。
//读取字符输入流数据 private static void readFile(StringBuilder stringBuilder) { try{ String filePath = "D:\\IDEA\\idea_Demo\\IO流\\FileInAndOutChar.java"; File file = new File(filePath); //创建文件字符输入流 FileReader fileReader = new FileReader(file); char[] data = https://www.it610.com/article/new char[512]; int rs = 0; while((rs = fileReader.read(data))> 0){ //在循环中读取数据 stringBuilder.append(data,0,rs); }//关闭流 fileReader.close(); }catch (Exception e){ e.printStackTrace(); } }

3. writeFile()方法 编写输出数据到文件字符输出流的 writeFile() 方法,在方法中创建文件字符输出流 fWriter,然后将 strBuilder 对象中的内容通过文件字符输出流保存到实例所在路径中的 FileInAndOutChar.bak 文件中,关键代码如下。
//写入数据到字符输出流 private static void writeFile(StringBuilder stringBuilder) { try { String filePath = "D:\\IDEA\\idea_Demo\\IO流\\FileInAndOutChar.bak"; File file = new File(filePath); //创建文件字符输出流 FileWriter fileWriter = new FileWriter(file); //将数据写入输出流 fileWriter.write(stringBuilder.toString()); //关闭流 fileWriter.close(); } catch (Exception e) { e.printStackTrace(); } }

该实例的运行结果如下:
控制台会读取本类的代码输出
Java从入门到入土|[Java] 神秘的IO流 (下)
文章图片

同时将读取到的数据写到新生成的 FileInAndOutChar.bak 文件中
Java从入门到入土|[Java] 神秘的IO流 (下)
文章图片

? 带缓存的输入/输出流 缓存可以说是 I/O 的一种性能优化。缓存流为 I/O 流增加了内存缓存区。有了缓存区,使得在流上执行 skip()、mark() 和 reset() 等方法都成为可能。
BufferedInputStream 与 BufferedOutputStream 类
BufferedInputStream 类可以对任何 InputStream 类进行带缓存区的包装,以达到性能的优化
BufferedInputStream 类有两个构造函数:
BufferedInputStream(InputStream in);
BufferedInputStream(InputStream in, int size);
第一种形式的构造函数创建了一个带有 32 字节的缓存流;第二种形式的构造函数按指定的大小来创建缓存区。一个最优的缓存区的大小,取决于它所在的操作系统、可用的内存空间及机器配置。从构造函数可以看出,BufferedInputStream 对象位于 InputStream 类对象之前。
下图描述了字节数据读取文件的过程
Java从入门到入土|[Java] 神秘的IO流 (下)
文章图片

使用 BufferedOutputStream 输出信息和往 OutputStream 输出信息完全一样,只不过 BufferedOutputStream 有一个用来将缓存区的数据强制输出完的 flush() 方法。
BufferedOutput Stream类也有两个构造方法:
BufferedOutputStream(OutputStream in);
BufferedOutputStream(OutputStream in , int size);
第一种构造函数创建一个 32 字节的缓存区,第二种形式以指定的大小来创建缓存区。
注意
flush() 方法用于即使缓存区没有满的情况下,也将缓存区的内容强制写入到外设,习惯上称这个过程为刷新。flush() 方法只对使用缓存区的 OutputStream 类的子类有效。当调用 close() 方法时,系统在关闭流之前,也会将缓存区中的信息刷新到磁盘文件中。
BufferedReader 与 BufferedWriter 类
BufferedReader 类与 BufferedWriter 类分别继承 Reader 类与 Writer 类。这两个类同样具有内部缓存机制,并可以以行为单位进行输入和输出。
BufferedReader 类常用的方法如下
● read() 方法:读取单个字符
● readLine() 方法:读取一个文本行,并将其返回为字符串。若无数据可读,则返回null
BufferedWriter 类中的方法都返回 void,常用的方法如下
● write(String s, int off, int len) 方法:写入字符串的某一部分
● flush() 方法:刷新该流的缓存
● newLine() 方法:写入一个行分隔符
在使用 BufferedWriter 类的 write() 方法时,数据并没有被立刻写入到输出流中,而是首先进入缓存区中。如果想立刻将缓存区中的数据写入输出流中,一定要调用 flush() 方法。
实例
向指定的磁盘文件中写入数据,并通过 BufferedReader 类将文件中的信息分行显示。
import java.io.*; public class Student { public static void main(String[] args) { //定义字符数组 String content[] = {"好久不见", "最近好吗", "常联系"}; //创建文件对象 File file = new File("D:/word.txt"); try { //创建FileWriter类对象 FileWriter fw = new FileWriter(file); //创建BufferedWriter类对象 BufferedWriter bufw = new BufferedWriter(fw); //循环遍历数组 for (int k = 0; k < content.length; k++) { //将字符串数组中的元素写入到磁盘文件中 bufw.write(content[k]); //将数组中的单个元素以单行的形式写入文件 bufw.newLine(); }//将BufferedWriter流关闭 bufw.close(); //将FileWriter流关闭 fw.close(); } catch (Exception e) { e.printStackTrace(); }try { //创建FileReader类对象 FileReader fr = new FileReader(file); //创建BufferedReader类对象 BufferedReader bufr = new BufferedReader(fr); //创建字符串对象 String s = null; int i = 0; //如果文件的文本行数不为null,则进入循环 while ((s = bufr.readLine()) != null) { i++; System.out.println("第" + i + "行: " + s); }//将BufferedReader流关闭 bufr.close(); //将FileReader流关闭 fr.close(); } catch (Exception e) { e.printStackTrace(); } } }

运行结果如下
Java从入门到入土|[Java] 神秘的IO流 (下)
文章图片

? 对象序列化 程序在运行的过程中可能需要保存数据,对于基本的数据类型,如 int、float、char 等,可以简单地保存到文件中,程序下次启动时,可以读取文件中的数据初始化程序。
但是对于复杂的对象类型,如果需要永久保存,则需要把对象中不同的属性分解为基本数据类型,然后分别保存到文件中,当程序再次运行时,需要建立新的对象,然后从文件中读取与对象有关的所有数据,再使用这些数据分别为对象的每个属性初始化。
Java 的 ObjectInput 接口与 ObjectOutput 接口分别继承了 DataInput 接口和 DataOutput 接口,提供了对基本数据类型和对象序列化的方法。
使用对象序列化功能,可以非常方便地将对象写入输出流,或者从输入流读取对象数据。
下面将介绍 ObjectInput 接口与 ObjectOutput 接口中定义的对象序列化和反序列化方法。
? readObject() 反序列化方法
所谓反序列化,就是从输入流中获取序列化的对象数据,用这些数据生成新的 Java 对象。该方法定义在 ObjectInput 接口中,由 ObjectInputStream 类实现。
语法如下:
Object object = readObject();

? object:Java 对象
注意
使用该方法获取的序列化对象是 Object 类型的,必须执行强制类型转换后才能使用
? writeObject() 序列化方法
序列化就是将对象写入到输出流,这个输出流可以是文件输出流、网络输出流或其他数据输出流。该方法定义在 ObjectOutput 接口中,由 ObjectOutputStream 类实现。
语法如下:
writeObject(object)

? object:将要序列化的对象
实例
创建 Worker 工人类,将该类的实例对象序列化到文件字节输出流,然后从文件字节输入流中反序列化该类的实例对象,并输出该对象的内容。
? 创建 Worker 类,该类必须实现 Serializable 接口,然后定义姓名、性别、年龄三个属性,并提供访问属性的方法,代码如下
import java.io.*; public class Worker implements Serializable { //定义表示姓名的字符串变量 private String name; //定义表示性别的字符串变量 private String gender; //定义表示年龄的int变量 private int age; public String getName() { return name; }public void setName(String name) { this.name = name; }public String getGender() { return gender; }public void setGender(String gender) { this.gender = gender; }public int getAge() { return age; }public void setAge(int age) { this.age = age; } }

? 创建 ObjectSerializable 类,编写主方法,在主方法中创建工人对象(即 Worker 类的实例对象),设置该对象的姓名、性别和年龄属性,然后将该对象序列化到 worker.dat 文件中,这样就实现了对象到文件的序列化。为验证对象序列化的内容,再从 worker. dat 文件中反序列化工人对象,并将对象的属性输出到控制台,代码如下
import java.io.*; public class ObjectSerializable { public static void main(String[] args) { //将工人对象序列化 try { //创建工人对象 Worker worker = new Worker(); //设置对象属性 worker.setName("青龙"); worker.setGender("男"); worker.setAge(24); //创建FileOutputStream对象 FileOutputStream fout = new FileOutputStream("./worker.dat"); //创建ObjectOutputStream对象 ObjectOutputStream oops = new ObjectOutputStream(fout); //将对象序列化 oops.writeObject(worker); } catch (Exception e) { e.printStackTrace(); }//反序列化工人对象 try { //创建FileInputStream对象 FileInputStream fis = new FileInputStream("./worker.dat"); //创建ObjectInputStream对象 ObjectInputStream oi = new ObjectInputStream(fis); //对象反序列化 Worker newWorker = (Worker) oi.readObject(); //输出对象信息 System.out.println("姓名: " + newWorker.getName()); System.out.println("性别: " + newWorker.getGender()); System.out.println("年龄: " + newWorker.getAge()); } catch (Exception e) { e.printStackTrace(); } } }

? 运行本实例,将在实例所在的文件夹中创建 worker.dat 文件,并且在控制台输出以下信息
Java从入门到入土|[Java] 神秘的IO流 (下)
文章图片

文件及文件夹操作 通过 I/O 技术可以实现文件管理,如复制文件、删除文件、创建文件等。这些操作在实际开发中应用得非常广泛。下面我们将介绍通过 I/O 技术实现的各种文件及文件夹操作。
? 复制文件 复制文件是将文件内容复制到指定位置的新文件中,类似于操作系统中的复制文件功能。在复制文件的过程中,如果目标文件不存在,则以目标文件名为名创建新的文件,并将原文件内容复制到该文件中,否则覆盖目标文件。
实例
创建类 FileCopy,在该类的主方法中编写代码,实现将该类中的代码复制到 FileCopyrepeat 类中。
import java.io.*; public class FileCopy { public static void main(String[] args) { //定义要进行复制的文件路径 String sfpath = "Solution/FileCopy.java"; //定义复制后文件的保存路径 String dfpath = "Solution/FileCopyRepeat.java"; //创建要进行复制的文件对象 File sFile = new File(sfpath); //创建保存复制后的文件对象 File dFile = new File(dfpath); try { //新建文件 dFile.createNewFile(); //定义FileInputStream对象 FileInputStream fis = new FileInputStream(sFile); //定义FileOutputStream对象 FileOutputStream fout = new FileOutputStream(dFile); //定义byte数组 byte[] date = new byte[512]; int rs = -1; //如果没有读到文件末尾 while ((rs = fis.read(date)) > 0) { //向流中写数据 fout.write(date, 0, rs); }//关闭流 fout.close(); fis.close(); System.out.println("文件复制成功!"); } catch (Exception e) { e.printStackTrace(); } } }

? 复制文件夹 复制文件夹要比复制文件复杂一些,因为文件夹内可能包含很多文件甚至其他文件夹,必须对它们分别执行复制操作。
实例
本实例的主要功能是实现文件夹的复制。前面介绍了文件的复制,文件夹的复制方法和文件的复制方法基本类似。
? 创建 FolderCopy 类,在该类中创建 copy() 方法,该方法接收文件数组和目标文件夹两个参数,如果目标文件夹不存在,则调用 mkdir() 方法创建文件夹,然后用循环语句判断文件数组中的每个文件对象。如果文件对象是文件类型,则复制该文件到目标文件夹中,如果该文件对象是文件夹类型,则调用该方法的 listFiles() 方法获取该文件夹的文件数组(即文件夹的文件列表),创建新的目标文件夹对象,再通过文件数组和目标文件夹嵌套调用该方法,这样就能把这个文件夹中所有内容复制到另外一个文件夹中。
import java.io.*; public class FolderCopy { private static void copy(File[] s, File d) { //如果文件夹不存在 if (!d.exists()) { //建立新的文件夹 d.mkdir(); }for (int i = 0; i < s.length; i++) { //如果是文件类型就复制文件 try { FileInputStream fis = new FileInputStream(s[i]); FileOutputStream fout = new FileOutputStream(new File(d.getPath() + File.separator + s[i].getName())); int count = fis.available(); byte[] data = https://www.it610.com/article/new byte[count]; if ((fis.read(data)) != -1) { //复制文件内容 fout.write(data); }//关闭流 fout.close(); fis.close(); } catch (Exception e) { e.printStackTrace(); }//如果是文件夹类型 if (s[i].isDirectory()) { //在目标文件夹中创建相同的文件夹 File des = new File(d.getPath() + File.separator + s[i].getName()); //递归调用本身 copy(s[i].listFiles(), des); } } }

? 创建主方法,在方法中建立源文件夹和目标文件夹两个对象,调用源文件夹的 listFiles() 方法获取文件数组(即文件列表),通过这个文件数组和目标文件夹调用 copy() 方法完成文件夹的复制,关键代码如下
//主方法 public static void main(String[] args) { File sourFile = null, desFile = null; //可以修改源文件夹路径 String sourFolder = "./sourceFolder"; //可以修改目标文件夹路径 String desFolder = "./desFolder"; sourFile = new File(sourFolder); if (!sourFile.isDirectory() || !sourFile.exists()) { System.out.println("源文件夹不存在"); } desFile = new File(desFolder); desFile.mkdir(); //调用copy()方法 copy(sourFile.listFiles(), desFile); }

? 在本实例的当前文件夹中建立 sourceFolder 文件夹,给这个文件夹复制一些文件或其他文件夹,然后运行本实例,sourceFolder 文件夹的内容将全部复制到 desFolder 文件夹中。
? 删除文件 File 类的 delete() 方法用于删除指定的文件,但是必须使用目标文件路径创建一个 File 类的实例对象,然后调用该实例对象的 delete() 方法删除指定文件。
? 创建 FileDelete 类,编写 delFile() 方法,该方法接收一个文件对象参数,即 File 类的实例对象,调用文件对象的 exists() 方法判断文件是否存在,如果不存在,则在控制台输出 “文件不存在” 的提示信息,如果文件存在,则调用 delete() 方法删除该文件,关键代码如下。
public class FileDelete { public static void delFile(File file) { //判断文件是否存在 if (!file.exists()) { System.out.println("文件不存在"); return; }//调用delete()方法 boolean rs = file.delete(); //如果文件删除成功 if (rs) { System.out.println("文件删除成功"); } else { System.out.println("文件删除失败"); } } }

? 编写主方法,在主方法中创建将要删除的文件的 File 类实例对象,然后调用 delFile() 方法删除该文件,关键代码如下。
public static void main(String[] args) { //定义要删除的文件 String filePath = "Solution\\FileDelete.java"; //创建该文件对象 File file = new File(filePath); //调用删除文件的方法 delFile(file); }

? 运行本实例后,刚刚你写的文件就没有了
? 分行写入文件 FileWriter 类可以向文件写入字符数据,如果将 FileWriter 类封装到 BufferedWriter 类的缓冲字符流中,则能够实现缓冲字符输出流,并且可以通过该输出流的 newLine() 方法实现数据的分行写入
? 创建 LineWriterData 类,编写主方法,在主方法中定义要写入数据的文件的路径,通过该路径建立一个 FileWriter 类的实例对象,再使用该对象创建一个 BufferedWriter 类的实例对象(即缓冲数据流对象),调用缓冲数据流对象的 writer() 方法把数据写入到文件中,然后调用 newLine() 方法写入换行符,调用 flush() 方法把内存中的内容写入到文件中并输出提示信息,关键代码如下
import java.io.*; public class LineWriterData { public static void main(String[] args) { //定义文件地址 String filePath = "Solution\\File.txt"; File file = new File(filePath); try { //创建文件字符输出流 FileWriter fw = new FileWriter(file); //使用缓冲数据流封装输出流 BufferedWriter bw = new BufferedWriter(fw); //写入数据到输出流 bw.write("CSDN".toCharArray()); //写入换行符 bw.newLine(); bw.write("好好学习"); bw.newLine(); bw.write("天天向上"); bw.newLine(); //刷新缓冲区 bw.flush(); System.out.println("数据已经写入File.txt文件中"); } catch (Exception e) { e.printStackTrace(); } } }

? 运行本实例,控制台将输出 “数据已经写入 File.txt 文件中” 的提示信息,同时在本实例的当前路径下会创建 File.txt 文件,其内容是分行写入的数据文件
Java从入门到入土|[Java] 神秘的IO流 (下)
文章图片

【Java从入门到入土|[Java] 神秘的IO流 (下)】
这次的分享就到这里啦,继续加油哦
?下期预告:Java多线程
有出错的地方欢迎在评论区指出来,共同进步,谢谢啦

    推荐阅读