2023-10-09 22:15:31 +08:00

314 lines
10 KiB
Java

package org.jcnc.jnotepad.util;
import javafx.scene.Node;
import org.jcnc.jnotepad.controller.event.handler.menuitem.OpenFile;
import org.jcnc.jnotepad.controller.exception.AppException;
import org.jcnc.jnotepad.model.entity.DirFileModel;
import org.kordamp.ikonli.javafx.FontIcon;
import java.awt.*;
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Set;
import static org.kordamp.ikonli.antdesignicons.AntDesignIconsFilled.*;
/**
* 文件工具
*
* @author gewuyou
*/
public class FileUtil {
private static final MessageDigest MESSAGE_DIGEST_SHA_256;
private static final int BUFFER_SIZE = 8192;
static {
try {
MESSAGE_DIGEST_SHA_256 = MessageDigest.getInstance("SHA-256");
} catch (NoSuchAlgorithmException e) {
throw new AppException(e);
}
}
private FileUtil() {
}
/**
* 将字节数组转换为String类型哈希值
*
* @param bytes 字节数组
* @return 哈希值
*/
private static String bytes2HashCode(byte[] bytes) {
StringBuilder hashString = new StringBuilder();
for (byte b : bytes) {
hashString.append(String.format("%02x", b));
}
return hashString.toString();
}
/**
* 获取本地文件Sha256哈希值字符串
*
* @param file 本地文件
* @return 本地文件Sha256哈希值
*/
public static String getLocalFileSha256HashString(File file) {
try (
// 获取文件输入流
FileInputStream fileInputStream = new FileInputStream(file);
// 获取字节流通道
FileChannel channel = fileInputStream.getChannel()
) {
// 设置8k缓冲区
ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);
while (channel.read(buffer) != -1) {
buffer.flip();
MESSAGE_DIGEST_SHA_256.update(buffer);
buffer.clear();
}
} catch (IOException e) {
throw new AppException(e);
}
return bytes2HashCode(MESSAGE_DIGEST_SHA_256.digest());
}
/**
* 获取本地文件Sha256哈希值字符串
*
* @param pathStr 本地文件路径字符串
* @return 本地文件Sha256哈希值
*/
public static String getLocalFileSha256HashString(String pathStr) {
return getLocalFileSha256HashString(new File(pathStr));
}
/**
* 获取本地文件Sha256哈希值字符串
*
* @param path 本地文件路径
* @return 本地文件Sha256哈希值
*/
public static String getLocalFileSha256HashString(Path path) {
return getLocalFileSha256HashString(path.toFile());
}
/**
* 获取文件中的文本内容。
*
* @param file 文件对象
* @return 文本内容
*/
public static String getFileText(File file) {
return getFileText(file, EncodingDetector.detectEncodingCharset(file));
}
/**
* 获取文件中的文本内容。
*
* @param file 文件对象
* @param encoding 文件编码
* @return 文本内容
*/
public static String getFileText(File file, Charset encoding) {
StringBuilder stringBuilder = new StringBuilder();
try (BufferedReader reader = new BufferedReader(new FileReader(file, encoding))) {
String line;
while ((line = reader.readLine()) != null) {
if (!stringBuilder.isEmpty()) {
stringBuilder.append("\n");
}
stringBuilder.append(line);
}
} catch (IOException ignored) {
LogUtil.getLogger(OpenFile.class).info("已忽视IO异常!");
}
return stringBuilder.toString();
}
/**
* 将文件夹转为DirFileModel
*
* @param file 文件
* @return DirFileModel 存储文件夹与文件关系的实体类
*/
public static DirFileModel getDirFileModel(File file) {
if (!file.exists()) {
return null;
}
DirFileModel dirFileModel = new DirFileModel(file.getAbsolutePath(), file.getName(), new ArrayList<>(), new FontIcon(FOLDER), new FontIcon(FOLDER_OPEN));
File[] files = file.listFiles();
if (files != null) {
for (File f : files) {
if (f.isDirectory()) {
DirFileModel childDirFileModel = getDirFileModel(f);
dirFileModel.getChildFile().add(childDirFileModel);
} else {
// todo 在此监测文件后缀,设置对应的图标
dirFileModel.getChildFile().add(new DirFileModel(f.getAbsolutePath(), f.getName(), null, new FontIcon(FILE), new FontIcon(FILE)));
}
}
}
return dirFileModel;
}
/**
* 文件夹迁移
*
* @param sourceFolder 源文件夹
* @param targetFolder 目标文件夹
* @since 2023/10/5 12:18
*/
public static void migrateFolder(File sourceFolder, File targetFolder) {
// 创建目标文件夹
targetFolder.mkdirs();
// 获取源文件夹中的所有文件和文件夹
File[] files = sourceFolder.listFiles();
if (files != null) {
// 遍历源文件夹中的每个文件和文件夹
for (File file : files) {
if (file.isDirectory()) {
// 如果是文件夹,递归调用自身进行迁移
migrateFolder(file, new File(targetFolder, file.getName()));
} else {
// 如果是文件,将文件复制到目标文件夹中
Path sourceFilePath = file.toPath();
Path targetFilePath = new File(targetFolder, file.getName()).toPath();
try {
Files.copy(sourceFilePath, targetFilePath, StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
throw new AppException(e);
}
}
}
}
}
/**
* 迁移文件夹
*
* @param sourceFolder 源文件夹
* @param targetFolder 目标文件夹
* @param ignoredFolders 忽略的文件夹集合
* @param ignoredFiles 忽略的文件集合
* @since 2023/10/5 13:58
*/
public static void migrateFolder(File sourceFolder, File targetFolder, Set<File> ignoredFolders, Set<File> ignoredFiles) {
// 创建目标文件夹
targetFolder.mkdir();
// 获取源文件夹中的所有文件和文件夹
File[] files = sourceFolder.listFiles();
if (files != null) {
// 遍历源文件夹中的每个文件和文件夹
for (File file : files) {
// 如果是文件夹且不是忽略的文件夹,递归调用自身进行迁移
if (file.isDirectory() && !ignoredFolders.contains(file)) {
migrateFolder(targetFolder, ignoredFolders, ignoredFiles, file);
continue;
}
// 如果是文件且不是忽略的文件,将文件复制到目标文件夹中
if (!file.isDirectory() && !ignoredFiles.contains(file)) {
migrateFile(targetFolder, file);
}
}
}
}
/**
* 迁移文件
*
* @param targetFolder 目标文件夹
* @param file 文件
*/
public static void migrateFile(File targetFolder, File file) {
Path sourceFilePath = file.toPath();
Path targetFilePath = new File(targetFolder, file.getName()).toPath();
try {
Files.copy(sourceFilePath, targetFilePath, StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
throw new AppException(e);
}
// 删除源文件
try {
Files.delete(file.toPath());
} catch (IOException e) {
throw new AppException(e);
}
}
/**
* 迁移文件夹
*
* @param targetFolder 目标文件夹
* @param ignoredFolders 忽略的文件夹集合
* @param ignoredFiles 忽略的文件集合
* @param file 文件
*/
private static void migrateFolder(File targetFolder, Set<File> ignoredFolders, Set<File> ignoredFiles, File file) {
migrateFolder(file, new File(targetFolder, file.getName()), ignoredFolders, ignoredFiles);
// 调用完毕删除当前目录
try {
Files.deleteIfExists(file.toPath());
} catch (IOException e) {
throw new AppException(e);
}
}
/**
* Opens the file explorer to the specified file or its parent directory.
*
* @param file the file or directory to open in the file explorer
*/
public static void openExplorer(File file) {
try { // 判断传入的是文件还是文件夹
if (file.isDirectory()) {
Desktop.getDesktop().open(file);
}
// 如果是文件则打开所在文件夹
else {
Desktop.getDesktop().open(file.getParentFile());
}
} catch (IOException e) {
throw new AppException(e);
}
}
/**
* Retrieves the icon corresponding to the given file name.
*
* @param tabTitle the title of the tab
* @return the icon node corresponding to the file name
*/
public static Node getIconCorrespondingToFileName(String tabTitle) {
// todo 在此根据文件缀名获取对应的图标
String fileExtension = tabTitle.substring(tabTitle.lastIndexOf(".") + 1);
return switch (fileExtension.toLowerCase()) {
case "txt" -> FontIcon.of(FILE_TEXT);
case "doc" -> FontIcon.of(FILE_WORD);
case "pdf" -> FontIcon.of(FILE_PDF);
case "ppt" -> FontIcon.of(FILE_PPT);
case "xls" -> FontIcon.of(FILE_EXCEL);
case "md" -> FontIcon.of(FILE_MARKDOWN);
default -> FontIcon.of(FILE_UNKNOWN);
};
}
}