Update FileUtils.java
增加部分自动打包解压之类的方法
This commit is contained in:
parent
15819c7260
commit
cde711f1d5
@ -1,23 +1,25 @@
|
||||
package com.jsc.dsp.utils;
|
||||
|
||||
import org.apache.commons.compress.archivers.ArchiveEntry;
|
||||
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
|
||||
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
|
||||
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.logging.Logger;
|
||||
import java.nio.file.*;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class FileUtils {
|
||||
private final Logger logger = Logger.getLogger(this.getClass().getName());
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass().getName());
|
||||
|
||||
public FileUtils() {
|
||||
}
|
||||
@ -79,7 +81,7 @@ public class FileUtils {
|
||||
public int downloadFromUrl(String urlStr, String savePath) {
|
||||
try {
|
||||
if (downloadedFileSet.contains(urlStr)) {
|
||||
logger.warning("File exist from " + urlStr);
|
||||
logger.warn("File exist from " + urlStr);
|
||||
return 2;
|
||||
}
|
||||
String[] urlCascade = urlStr.split("/");
|
||||
@ -183,6 +185,180 @@ public class FileUtils {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 解压tar.gz文件到指定目录
|
||||
*/
|
||||
/**
|
||||
* 解压tar.gz文件到指定目录,返回解压的文件数量(不包含目录)
|
||||
*
|
||||
* @return 解压的普通文件数量
|
||||
*/
|
||||
public static int extractTarGz(File tarFile, File destDir) throws IOException {
|
||||
if (!destDir.exists() && !destDir.mkdirs()) {
|
||||
throw new IOException("无法创建目标目录: " + destDir.getAbsolutePath());
|
||||
}
|
||||
|
||||
int fileCount = 0;
|
||||
|
||||
try (FileInputStream fis = new FileInputStream(tarFile);
|
||||
BufferedInputStream bis = new BufferedInputStream(fis);
|
||||
GzipCompressorInputStream gzIn = new GzipCompressorInputStream(bis);
|
||||
TarArchiveInputStream tarIn = new TarArchiveInputStream(gzIn)) {
|
||||
|
||||
TarArchiveEntry entry;
|
||||
|
||||
while ((entry = tarIn.getNextTarEntry()) != null) {
|
||||
// 跳过空条目、符号链接、特殊设备文件
|
||||
if (entry.getName().trim().isEmpty()
|
||||
|| entry.isSymbolicLink()
|
||||
|| entry.isCharacterDevice()
|
||||
|| entry.isBlockDevice()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 安全校验:防止路径遍历攻击
|
||||
Path entryPath = destDir.toPath().resolve(entry.getName()).normalize();
|
||||
if (!entryPath.startsWith(destDir.toPath().normalize())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 创建目录结构(为后续文件写入做准备)
|
||||
if (entry.isDirectory()) {
|
||||
Files.createDirectories(entryPath);
|
||||
} else {
|
||||
Files.createDirectories(entryPath.getParent());
|
||||
Files.copy(tarIn, entryPath, StandardCopyOption.REPLACE_EXISTING);
|
||||
fileCount++;
|
||||
}
|
||||
}
|
||||
return fileCount;
|
||||
|
||||
} catch (IOException e) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归删除目录(含子目录和文件)
|
||||
*/
|
||||
public static void deleteDirectory(Path path) throws IOException {
|
||||
if (!Files.exists(path)) return;
|
||||
|
||||
Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
|
||||
@Override
|
||||
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
|
||||
Files.delete(file);
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
|
||||
Files.delete(dir);
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void moveAllFilesRecursively(Path sourceDir, Path targetDir) throws IOException {
|
||||
if (!Files.exists(sourceDir) || !Files.isDirectory(sourceDir)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 使用Files.walk递归遍历所有文件
|
||||
try (Stream<Path> walkStream = Files.walk(sourceDir)) {
|
||||
walkStream
|
||||
.filter(path -> !Files.isDirectory(path)) // 只处理文件
|
||||
.sorted() // 确保先创建父目录再移动文件
|
||||
.forEach(file -> {
|
||||
try {
|
||||
// 计算相对路径(相对于sourceDir)
|
||||
Path relativePath = sourceDir.relativize(file);
|
||||
|
||||
// 构建目标文件路径
|
||||
Path targetFile = targetDir.resolve(relativePath);
|
||||
|
||||
// 确保目标父目录存在
|
||||
Files.createDirectories(targetFile.getParent());
|
||||
|
||||
// 移动文件(覆盖同名文件)
|
||||
Files.move(file, targetFile,
|
||||
StandardCopyOption.REPLACE_EXISTING,
|
||||
StandardCopyOption.COPY_ATTRIBUTES);
|
||||
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e); // 便于Stream中抛出
|
||||
}
|
||||
});
|
||||
} catch (UncheckedIOException e) {
|
||||
throw e.getCause() instanceof IOException ? (IOException) e.getCause() : new IOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归遍历源目录,将所有文件平铺移动到目标目录(不保留目录结构,同名覆盖)
|
||||
*
|
||||
* @param sourceDir 源目录(临时解压目录)
|
||||
* @param targetDir 目标目录(如 D:/output/twitter/videos)
|
||||
* @return 成功移动的文件数量
|
||||
*/
|
||||
public static int flattenAndMoveFiles(Path sourceDir, Path targetDir) throws Exception {
|
||||
if (!Files.exists(sourceDir) || !Files.isDirectory(sourceDir)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
AtomicInteger movedCount = new AtomicInteger(0);
|
||||
Map<String, Path> duplicateFiles = new HashMap<>(); // 记录被覆盖的文件
|
||||
|
||||
try (Stream<Path> walkStream = Files.walk(sourceDir)) {
|
||||
walkStream
|
||||
.filter(path -> Files.isRegularFile(path)) // 只处理普通文件
|
||||
.forEach(file -> {
|
||||
try {
|
||||
String fileName = file.getFileName().toString();
|
||||
Path targetFile = targetDir.resolve(fileName);
|
||||
|
||||
// 检测同名文件覆盖(用于日志记录)
|
||||
boolean willOverwrite = Files.exists(targetFile);
|
||||
if (willOverwrite) {
|
||||
duplicateFiles.put(fileName, file);
|
||||
}
|
||||
|
||||
// 移动文件(覆盖同名文件)
|
||||
Files.move(file, targetFile);
|
||||
|
||||
movedCount.incrementAndGet();
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
} catch (UncheckedIOException e) {
|
||||
throw e.getCause() instanceof IOException ? (IOException) e.getCause() : new IOException(e);
|
||||
}
|
||||
|
||||
return movedCount.get();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 清空目录内容(保留目录本身)
|
||||
*/
|
||||
public static void cleanDirectory(Path dir) throws IOException {
|
||||
if (!Files.exists(dir)) return;
|
||||
|
||||
try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
|
||||
for (Path entry : stream) {
|
||||
if (Files.isDirectory(entry)) {
|
||||
deleteDirectory(entry);
|
||||
} else {
|
||||
Files.delete(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
saveStringToFile("{\"aaa\":\"测试测试testtest\"}", "E:/yuxin/test.json");
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user