package org.example.test_filebasestudy;
import java.io.*;
import java.util.UUID;
public class TryTraverseDemo03 {
public static void main(String args[]) {
// 以文件路径为C:\Users\zhang\Javatest,指定文件对象file
File files = new File("C:\\Users\\zhang\\Javatest" );
// 调用方法,进行文件的遍历和读取,参数为文件对象 file
fileTraverse(files);
}
// 进行文件的遍历和读取的方法,参数为文件对象 files
public static void fileTraverse(File files) {
// 创建文件数组
File[] arrFile = files.listFiles();
// 遍历文件数组(增强for循环)
for (File file : arrFile) {
// 进行判断,判断遍历出的文件是否为文件目录
if (file.isDirectory()) {
// 打印出文件的绝对路径
System.out.println("这是目录:" + file.getAbsolutePath());
// 调用文件遍历的方法,再次遍历此文件目录下的文件
fileTraverse(file);
} else {
// 打印所有文件
System.out.println("这是文件:" + file.getAbsolutePath());
// 调用文件读取的方法
fileRead(file);
}
}
}
// 读取文件,只读取符合后缀名类型的文件
public static void fileRead(File file) {
/*判断为文件后,进行文件类型的判断(判断出自己所需的文件)*/
// String 类型 变量,用于存放文件的后缀
String suffix = "";
// 获取文件名,类型为String
String fileName = file.getName();
// 用于存放最后一次出现 . 位置索引的变量
int index = fileName.lastIndexOf("." );
// 得到文件后缀名,index存放的是“.”的位置,往后+1 得到的就是文件后缀名
suffix = fileName.substring(index + 1);
// 获取文件绝对路径
File fileRoad = file.getAbsoluteFile();
//进行判断是否为自己需要的文件
if (suffix.equalsIgnoreCase("txt" )) {
/* 判断是txt 文件后,进行读取和写入操作*/
try {
// 创建文件字节输入流,通过文件的路径
InputStream in = new FileInputStream(fileRoad);
int readOne = 0;
//判断是否读到文件末尾,若readOne = in.read()) = -1 表示已经读到文件最后了
while ((readOne = in.read()) != -1) {
System.out.print(readOne);
}
// 如果已经读到文件最后,就换行
if ((readOne = in.read()) == -1) {
System.out.println();
}
in.close();
// 写入新的文件夹操作
fileWrite(fileRoad);
} catch (IOException e) {
e.printStackTrace();
}
}
}
/*
将文件写入另一个文件
思路: 先读取一个文件,读到文件内容之后,将该文件内容存到另一个文件中。
*/
public static void fileWrite(File fileRoad) {// 传入需要写入的文件路径
try {
// 通过传进来的fileRoad文件路径创建一个输入流对象
FileInputStream readFile = new FileInputStream(fileRoad);
// 创建一个存放写入文件的文件目录对象
File path = new File("C:\\Users\\zhang\\Javatest\\writeTest");
System.out.println(path.exists());
// 获取String类型的文件目录,用于创建写入的文件名
String pathName = path.getAbsolutePath();
//获取到写入文件的名称.getName() 获得写入文件名
String fileName = fileRoad.getName();
//把文件的名称设置为唯一的值,uuid
String uuid = UUID.randomUUID().toString().replace("-", "");
fileName = uuid + "_" + fileName;
//
File fielWriteName = new File(pathName,fileName);
FileOutputStream writeFile = new FileOutputStream(fielWriteName);
// 记录文件读取的位置,用于判断是否读到文件最后
int readFlag = 0;
while((readFlag = readFile.read()) != -1) {
// 将读到的内容写入文件writeFile中
writeFile.write(readFlag);
}
readFile.close();
writeFile.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/*
* FileOutputStream流是指文件字节输出流,
* 专用于输出原始字节流如图像数据等,其继承OutputStream类,拥有输出流的基本特性
*****一、下面是它的四个构造方法的概述:
* 1、 FileOutputStream(File file)
* 创建FileOutputStream流以写入数据到File对象所代表的文件,
* 同时创建一个新的FileDescriptor对象来表示与该文件的关联(源码中会new一个该对象)
*
* 2、public FileOutputStream(File file,boolean append)
* 创建FileOutputStream流以写入数据到File对象表示的文件。
* 若第二个参数为真,则意味着会写入字节到文件的末尾,意味着追加内容,
* 若为假,则是写入字节到文件的开头,意味着是覆盖,
* 创建一个新的FileDescriptor对象来表示此文件连接。
*
* 3、 FileOutputStream(String name)
* 创建FileOutputStream流以写入数据到指定路径所代表的文件,
* 同时创建一个新的FileDescriptor对象来表示与该文件的关联(源码中会new一个该对象)
*
* 4、FileOutputStream(String name,boolean append)
* 创建FileOutputStream流以写入数据到指定路径所代表的文件,
* 同时创建一个新的FileDescriptor对象来表示与该文件的关联(源码中会new一个该对象),
* 如果第二个参数为true,则字节将写入文件的末尾而不是开头
* (此方法同 2 )
*
* 总结:
* 因此虽然有4个构造方法,
* 但是究其本质发现都是调用了下面这个构造方法,
* 因此后续使用FileOutputStream流时,直接使用该构造方法即可
*
*****二、FileOutputStream流构造方法的特殊之处
* FileOutputStream流的构造方法可以用于生成系统文件
* FileIntputStream流创建时若文件不存在就会报FileNotFoundException异常,
* 但是我们发现FileOutputStream流中的构造方法说明提到的是不存在且无法创建才会报FileNotFoundException异常。
* 也就是意味着若不存在但可创建的情况下是不会有异常产生的
*
******三、FileOutputStream流常用的API:
* 1、write(int b) :将指定的一个字节写入文件的输出流中,所以是一次写入一个字节
* write(int n)方法实例:需要先将要写入的内容转成字节数组然后再进行循环多次写入才可以
*
* 2、write(byte[] b) : 将指定字节数组中的b.length个字节写入到输出流中
* write(byte[] b)方法实例:本质是调用其他方法执行的,
* 注意参数append是构造函数中的第二个参数,默认为false
*
* 3、write(byte[] b,int off,int len): 将从偏移量off开始的指定字节数组中的len个字节写入输出流中
* 参数b代表着含有要写入数据的字节数组,参数off代表着从数组下标off开始,参数len表示最终写入的字节个数
* 如write(bytes,0,5)则意味着从字节数组bytes中下标0开始读5个字节到输出流中.
*
* 关于write方法小总结:
* write(byte b[], int off, int len)方法的本质等于多次调用write(int n)方法
* 而根据上面的write(byte b[])方法本质是调用writeBytes(b, 0, b.length, append)方法
* write(byte b[], int off, int len)方法实例 : 相比write(byte b[])方法等于是灵活控制了要输入的内容
*
* 三种write方法的对比:
* 1、通过上述实例代码其实可以发现使用write(int n)是需要传递单字节作为参数,
* 但是一般情况我们都是接收的字节数组,与其使用字节数组进行循环调用还不如使用write(byte[] b)方法,
* 直接把内容转化成字节数组作为参数调用即可
*
* 2、 三者之间写数据的效率,根据源代码可以看出,
* 虽然具体的实现方法是native修饰无法查看,
* 但是根据父类方法对比发现三者实质都是通过for循环进行的单字节写入,
* 所以认定三者写数据的效率差不多一样
* 3、因此使用FileOutputStream流写数据时一般使用第二种和第三种write方法即可
* 4、close()关闭输出流并释放与此流关联的所有系统资源。输出流可能不再用于写入字节。
*
引用知识点详述的原文链接:https://blog.csdn.net/ai_bao_zi/article/details/81110405
*/