1,拷贝文件
拷贝文件首先要判断原文件是否存在,若不存在则失败;然后使用Files.copy复制文件,如果其父目录不存在存在,会出现java.nio.file.NoSuchFileException异常,如下图所示:
则需要先判断父母录是否存在,若不存在需要先创建父目录。实现代码如下所示:(其传参均为绝对路径,即带文件名。
public static boolean copyFile(String oldPath, String newPath) {
try {
File file = new File(oldPath);
if (!file.exists()) {
return false;
}
File newFile = new File(newPath);
if (!newFile.getParentFile().exists()) {
//创建上级目录
newFile.getParentFile().mkdirs();
}
Files.copy((new File(oldPath)).toPath(), new FileOutputStream(newPath));
} catch (IOException ioException) {
ioException.printStackTrace();
return false;
}
return true;
}
若新路径只想传所拷贝的路径,不带文件名,则实现方式如下所示:
可用StandardCopyOption指的拷贝类型:REPLACE_EXISTING(存在替换)、COPY_ATTRIBUTES(拷贝属性)、ATOMIC_MOVE(移动操作)。
public static boolean copyFile(String oldPath, String newPath) {
try {
File file = new File(oldPath);
if (!file.exists()) {
return false;
}
String fileName = file.getName();
newPath = newPath + fileName;
File newFile = new File(newPath);
if (!newFile.getParentFile().exists()) {
//创建上级目录
newFile.getParentFile().mkdirs();
}
Files.copy((new File(oldPath)).toPath(), (new File(newPath)).toPath(), StandardCopyOption.REPLACE_EXISTING);
} catch (IOException ioException) {
ioException.printStackTrace();
return false;
}
return true;
}
2, 文件名大小写问题
由于windows系统对文件名的大小写问题不敏感,不区分文件名大小写,即在windows系统某个路径下不能同时存在文件名为HELLO.txt 和文件名为hello.txt的两个文件。
则由上面实现代码来拷贝文件的话则会改变复制后的文件名,如想要把源路径D:\Test\下的testCsv.csv文件拷贝到D:\Test\test2\目录下,但是所传递的参数所带文件名都是TESTCSV.csv,其能够在原路径中找到文件,也能实现拷贝操作,但是拷贝后的文件名是TESTCSV.csv。
解决方法:
通过file.getCanonicalFile().getName()去获取原路径的真实名称,获取到的是本地目录下真实大小写的文件名,其实现代码如下所示:
public static boolean copyFile(String oldPath, String newPath) {
try {
File file = new File(oldPath);
if (!file.exists()) {
return false;
}
// String fileName = file.getName();
String fileName = file.getCanonicalFile().getName();
newPath = newPath + fileName;
File newFile = new File(newPath);
if (!newFile.getParentFile().exists()) {
//创建上级目录
newFile.getParentFile().mkdirs();
}
Files.copy((new File(oldPath)).toPath(), (new File(newPath)).toPath(), StandardCopyOption.REPLACE_EXISTING);
} catch (IOException ioException) {
ioException.printStackTrace();
return false;
}
return true;
}
3,文件名增加时间戳
public static boolean copyFile(String oldPath, String newPath) {
try {
File file = new File(oldPath);
if (!file.exists()) {
return false;
}
// String fileName = file.getName();
String fileName = file.getCanonicalFile().getName();
// 给文件名后追加时间戳
if(fileName.lastIndexOf(".")==-1){
// 考虑没有文件名后缀的情况
fileName = fileName + "_" + new SimpleDateFormat("yyyyMMDDHHmmss".format(new Date());
} else {
fileName = fileName.substring(0, fileName.lastIndexOf(".")) + "_" +
new SimpleDateFormat("yyyyMMDDHHmmss".format(new Date()) +
fileName.substring(fileName.lastIndexOf("."));
}
newPath = newPath + fileName;
File newFile = new File(newPath);
if (!newFile.getParentFile().exists()) {
//创建上级目录
newFile.getParentFile().mkdirs();
}
Files.copy((new File(oldPath)).toPath(), (new File(newPath)).toPath(), StandardCopyOption.REPLACE_EXISTING);
} catch (IOException ioException) {
ioException.printStackTrace();
return false;
}
return true;
}
4,删除文件夹
若存在需求需要删除某个文件夹下10天之前的所有文件及文件夹(只保留7天之内的),如一般日志所放的文件夹一般需要给予一定的时间进行清理。Java删除文件夹,若该文件夹下有文件,这不能将这个文件夹删除,及需要将文件夹下的所有文件删除才能将此文件夹删除。
/**
* 删除文件或文件夹及文件夹下的所有文件 (递归删除文件夹,若文件被占用则不能被删除,直接跳过)
*
* @param file 文件对象
* @return 删除文件是否成功
*/
public static boolean deleteDirFile (File file) {
if(file.isDirectory()) {
File[] files = file.listFiles();
if(files == null) {
return file.delete();
}
for(File fi : files) {
deleteDirFile(fi);
}
}
return file.delete();
}
// 清空文件夹下day天以前的文件
public static boolean deleteTimeOutDir(String dirPath, long day) {
File file = new File(dirPath);
if(!file.exist()) {
System.out.println("this dirPath does not exist.");
return true;
}
if(!file.isDirectory()) {
System.out.println("this dirPath is not a directory.");
return false;
}
// 得到目录下的所有文件及文件夹
File[] files = file.listFiles();
if(files == null) {
System.out.println("no other files exist in this directory.");
return true;
}
// 获取当前时间
long currentTime = System.currentTimeMillis();
// 文件保留的时间差 day为int时,此处day需强转,否则得到的是负数(溢出)
long dayTime = day * (24 * 60 * 60 * 1000);
for(File f : files) {
// 得到文件或文件夹的绝对路径
File absFile = f.getAbsoluteFile();
System.out.println(absFile);
// 文件的最近修改时间
System.out.println(f.getName() + " 最近修改时间:" + f.lastModified() + " 最近修改时间:" + absFile.lastModified() );
// 根据文件的绝对路径获取path
Path path = Paths.get(absFile.getAbsolutePath());
// 根据path获取文件的基本属性类
BasicFileAttributes attributes;
try {
attributes = File.readAttributes(path, BasicFileAttributes.class);
} catch (IOException exception) {
System.out.println("get file attributes error: " + exception);
return false;
}
// 从基本属性中获取文件创建时间
FileTime fileTime = attributes.creationTime();
// 将时间转换为毫秒
long millis = fileTime.toMillis();
System.out.println(f.getName() + " 创建时间:" + new SimpleDateFormat("yyyyMMDDHHmmss".format(new Date(millis));
if(currentTime - millis > dayTime) {
System.out.println("删除:" + deleteDirFile(f));
// FileUtils.cleanDirectory(f);
}
}
}
5,压缩文件
如图所示,想用Java实现将该目录下的文件压缩在一起成为一个zip文件:
代码实现:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/**
* @Author jingshuiliushen
* @Date 2023/3/11 0:29
*/
public class ZipFile {
public static void main(String[] args) {
List<String> srcFiles = new ArrayList<>();
srcFiles.add("D:\\练习题\\练习题\\练习题1.docx");
srcFiles.add("D:\\练习题\\练习题\\练习题2.docx");
srcFiles.add("D:\\练习题\\练习题\\练习题3.docx");
srcFiles.add("D:\\练习题\\练习题\\练习题4.docx");
srcFiles.add("D:\\练习题\\练习题\\练习题5.docx");
srcFiles.add("D:\\练习题\\练习题\\练习题6.docx");
System.out.println(zipFiles(srcFiles, "D:\\练习题\\练习题\\练习题.zip"));
}
public static boolean zipFiles(List<String> srcFiles, String zipFileName) {
if (srcFiles == null || srcFiles.isEmpty()) {
System.out.println("文件不存在");
return false;
}
File zipFile = new File(zipFileName);
try(FileOutputStream fileOutputStream = new FileOutputStream(zipFile);
ZipOutputStream zipOutputStream = new ZipOutputStream(fileOutputStream)) {
FileInputStream fileInputStream;
for(String srcFile : srcFiles) {
File file = new File(srcFile);
// 单个文件不存在跳过
if (!file.exists()) {
System.out.println(srcFile + "不存在");
continue;
}
fileInputStream = new FileInputStream(file);
ZipEntry zipEntry = new ZipEntry(file.getName());
zipOutputStream.putNextEntry(zipEntry);
int len;
byte[] buffer = new byte[1024];
while ((len = fileInputStream.read(buffer)) > 0) {
zipOutputStream.write(buffer, 0, len);
}
fileInputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
return true;
}
public static void zipFiles(File[] srcFiles, String zipFileName) {
File zipFile = new File(zipFileName);
try(FileOutputStream fileOutputStream = new FileOutputStream(zipFile);
ZipOutputStream zipOutputStream = new ZipOutputStream(fileOutputStream)) {
FileInputStream fileInputStream;
for (File file : srcFiles) {
fileInputStream = new FileInputStream(file);
ZipEntry zipEntry = new ZipEntry(file.getName());
zipOutputStream.putNextEntry(zipEntry);
int len;
byte[] buffer = new byte[1024];
while ((len = fileInputStream.read(buffer)) > 0) {
zipOutputStream.write(buffer, 0, len);
}
fileInputStream.close();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
}
运行结果:
代码可进行完善,结合删除可实现压缩后将原有文件删除,或者如果压缩的文件不存在就不要continue了,之间返回并提示某个文件不存在。
5,解压文件
// 解压zip
public static boolean unzipFile(String zipPath, String descDir) {
if (!zipPath.contains("zip")) {
System.out.println("file is not zip format");
}
File zipFile = new File(zipPath);
if (!zipFile.exists()) {
System.out.println("zipPath is not exist");
return false;
}
// 解压到指定目录descDir为空字符,则默认解压到当前目录下
if ("".equals(descDir)) {
descDir = zipFile.getParent();
}
File pathFile = new File(descDir);
if (!pathFile.exists()) {
pathFile.mkdirs();
}
try (FileInputStream fileInputStream = new FileInputStream(zipPath);
ZipInputStream zipInputStream = new ZipInputStream(fileInputStream)) {
ZipEntry zipEntry;
while ((zipEntry = zipInputStream.getNextEntry()) != null) {
String zipEntryName = zipEntry.getName();
String outPath = descDir + zipEntryName;
File outFile = new File(outPath);
if (zipEntry.isDirectory() && !outFile.exists()) {
outFile.mkdirs();
}
if (new File(outPath).isDirectory()) {
continue;
}
if (!writeZipToFile(zipInputStream, outPath)) {
return false;
}
}
} catch (IOException ioException) {
System.out.println("write file to zip error");
return false;
}
return true;
}
private static boolean writeZipToFile(ZipInputStream zipInputStream, String filePath) {
try (FileOutputStream fileOutputStream = new FileOutputStream(filePath)){
byte[] bytes = new byte[1024];
int len;
while ((len = zipInputStream.read(bytes)) > 0) {
fileOutputStream.write(bytes, 0, len);
}
} catch (IOException ioException) {
System.out.println("write zip to file error");
return false;
}
return true;
}
如果出现java.lang.IllegalArgumentException: MALFORMED 异常,其原因是zip文件里含有中文名称的文件,windows 环境下,默认字符集为GBK,ZipFile 默认使用 UTF-8 字符集,当文件名存在中文时,处理时就会报错。解决办法为创建 ZipFile 时,设置字符集为GBK.
ZipInputStream zipInputStream = new ZipInputStream(fileInputStream, Charset.forName("GBK"))