JAVA——把一批压缩文件中存放的部分数据进行处理(替换)

news/2025/1/12 11:59:23/

JAVA——把一批压缩文件中存放的部分数据进行处理(替换)

  • 一、需求
  • 二、分析
  • 三、具体实现
    • 1.解压压缩文件
    • 2.读取解压后的文件并且按照一定逻辑处理
    • 3.把文件压缩存储
    • 4.方法的调用
    • 5.需要添加的依赖
  • 四、执行结果
  • 五、用到的工具类
  • 六、可以改进的地方
    • 1.文件处理完成后,删除临时文件和文件夹会出现删除失败的问题
    • 2.调用方法时所有操作(解压-修改数据-压缩-保存)可以分文件夹完成

一、需求

有一批已经压缩存档的数据文件(压缩文件格式为.tar.gz,解压后为.txt文件),现在需要把每个文件中符合需要的字段数据进行更改替换,因为文件量大,需要替换的字段数据有明确共同点(数据在文件每一行中所处同一个位置),因此写个脚本来处理是比较省时的做法。

  • 样例数据如图所示:
  • 比如说,这个表里存的是用户信息,其中用户名是敏感数据,需要把所有用户名替换成******
    在这里插入图片描述
    在这里插入图片描述

二、分析

以上需求可以分解为三个步骤:
1.解压压缩文件
2.读取解压后的文件并且按照一定逻辑处理
3.把文件压缩存储

三、具体实现

1.解压压缩文件

  • 解压文件方法如下:
/*** 批量解压文件夹下的所有.tar.gz文件** @param sourcePath 要解压的文件夹* @param targetPath 解压到目标路径* @return*/public static DataEntity<Void> batchDecompressTarGzip(String sourcePath, String targetPath) throws IOException {log.info("{} 开始批量解压文件 ...", sourcePath);deleteDirAfterNSeconds(new File(targetPath),0);File dir = new File(sourcePath);//遍历文件夹,获取文件完整路径File[] files = dir.listFiles();assert files != null;for (File f : files) {String filePath = sourcePath + File.separator + f.getName();//把所有文件解压到目标文件夹deCompressTarGzip(filePath, targetPath + File.separator + dir.getName());}log.info("{} 文件批量解压完成。", sourcePath);return DataUtils.success();}
/*** 解压.tar.gz文件** @param sourcePath 要解压的文件路径加文件名* @param targetPath 解压到目标路径* @return* @throws IOException*/public static DataEntity<Void> deCompressTarGzip(String sourcePath, String targetPath) throws IOException {
//        //解压文件
//        Path source = Paths.get("/home/test/output" + TARGZ);
//        //解压到哪
//        Path target = Paths.get("/home/test2");//解压文件Path source = Paths.get(sourcePath);//解压到哪Path target = Paths.get(targetPath);if (Files.notExists(source)) {return DataUtils.fail("您要解压的文件不存在: " + source.toAbsolutePath());}//InputStream输入流,以下四个流将tar.gz读取到内存并操作//BufferedInputStream缓冲输入流//GzipCompressorInputStream解压输入流//TarArchiveInputStream解tar包输入流try (InputStream fi = Files.newInputStream(source);BufferedInputStream bi = new BufferedInputStream(fi);GzipCompressorInputStream gzi = new GzipCompressorInputStream(bi);TarArchiveInputStream ti = new TarArchiveInputStream(gzi)) {ArchiveEntry entry;while ((entry = ti.getNextEntry()) != null) {//获取解压文件目录,并判断文件是否损坏DataEntity<Path> res = zipSlipProtect(entry, target);if (!res.isOk()) {return DataUtils.fail(res.getMessage());}Path newPath = res.getData();if (entry.isDirectory()) {//创建解压文件目录Files.createDirectories(newPath);} else {//再次校验解压文件目录是否存在Path parent = newPath.getParent();if (parent != null) {if (Files.notExists(parent)) {Files.createDirectories(parent);}}// 将解压文件输入到TarArchiveInputStream,输出到磁盘newPath目录Files.copy(ti, newPath, StandardCopyOption.REPLACE_EXISTING);}}}return DataUtils.success();}//判断压缩文件是否被损坏,并返回该文件的解压目录private static DataEntity<Path> zipSlipProtect(ArchiveEntry entry, Path targetDir) {Path targetDirResolved = targetDir.resolve(entry.getName());Path normalizePath = targetDirResolved.normalize();if (!normalizePath.startsWith(targetDir)) {log.error("压缩文件已被损坏: {}", entry.getName());return DataUtils.fail("压缩文件已被损坏" + entry.getName());}return DataUtils.entityData(normalizePath);}

2.读取解压后的文件并且按照一定逻辑处理

  • 读取和替换文件如下:
/*** 批量读取和替换txt文件:把经纬度数据替换成0** @param sourcePath 存放.txt文件的目录* @return*/public static DataEntity<Void> readAndReplaceTxt(String sourcePath, String targetPath) throws IOException {log.info("开始批量替换敏感数据");deleteDirAfterNSeconds(new File(targetPath),0);File dir = new File(sourcePath);File fileDir = dir.listFiles()[0];File[] files = fileDir.listFiles();//遍历文件assert files != null;for (File file : files) {String newFileName = file.getName();String newFileDir = targetPath + File.separator + fileDir.getName();Files.createDirectories(Paths.get(newFileDir));String newFilePath = newFileDir + File.separator + newFileName;try (BufferedReader bufferedReader = new BufferedReader(new FileReader(file))) {//构造一个BufferedReader类来读取文件String lineTxt = null;//result用来存储文件内容
//                    StringBuilder result = new StringBuilder();//按使用readLine方法,一次读一行while ((lineTxt = bufferedReader.readLine()) != null) {//替换int i = StringUtils.ordinalIndexOf(lineTxt, "\t", 2);int j = StringUtils.ordinalIndexOf(lineTxt, "\t", 4);String newContent = lineTxt.replace(lineTxt.substring(i, j), "\t0\t0");//替换
//                        result.append(newContent);File newFile = new File(newFilePath);PrintStream ps = new PrintStream(new FileOutputStream(newFile, true));ps.println(newContent);// 往.txt文件里写入字符串}log.info("文件 {} 中敏感数据替换执行完毕", newFilePath);} catch (Exception e) {log.error("读取文件 {} 内容出错", newFilePath);return DataUtils.fail(e.getMessage());}}log.info("敏感数据批量替换完成。");return DataUtils.success();}

3.把文件压缩存储

  • 压缩文件如下
/*** 压缩.txt文件为.tar.gz文件(压缩后文件名不变,仅后缀发生变化)** @param resourceFile 要压缩的文件* @param targetDir    要存放的路径* @return* @throws IOException*/public static DataEntity<Void> fileTarGzip(File resourceFile, String targetDir) throws IOException {//获取输出后的文件名String oldName = resourceFile.getName();int i = oldName.indexOf(TXT);String newName = oldName.substring(0, i) + TARGZ;String outPath = targetDir + File.separator + newName;Path path = Paths.get(outPath + TMP);try (FileOutputStream fileOutputStream = new FileOutputStream(outPath + TMP);BufferedOutputStream bufferedOutput = new BufferedOutputStream(fileOutputStream);TarOutputStream tarOutputStream = new TarOutputStream(bufferedOutput);FileInputStream fileInputStream = new FileInputStream(resourceFile);BufferedInputStream bufferedInput = new BufferedInputStream(fileInputStream);) {TarEntry entry = new TarEntry(new File(oldName));entry.setSize(resourceFile.length());tarOutputStream.putNextEntry(entry);IOUtils.copy(bufferedInput, tarOutputStream);tarOutputStream.closeEntry();} catch (Exception e) {Files.delete(path);log.error("文件压缩至 {} 执行异常,嵌套异常!", outPath, e);}// 读取打包好的 tar 临时文件,使用 GZIP 方式压缩try (FileInputStream fin = new FileInputStream(outPath + TMP);BufferedInputStream bin = new BufferedInputStream(fin);FileOutputStream fout = new FileOutputStream(outPath);GZIPOutputStream gout = new GZIPOutputStream(fout);BufferedOutputStream bout = new BufferedOutputStream(gout);) {byte[] cache = new byte[1024];for (int index = bin.read(cache); index != -1; index = bin.read(cache)) {bout.write(cache, 0, index);}log.info("文件 {} 压缩执行完毕", outPath);} catch (Exception e) {log.error("文件压缩至 {} 执行异常,嵌套异常!", outPath, e);} finally {Files.delete(path);}return DataUtils.success();}/*** 批量压缩.txt文件为.tar.gz文件(压缩后文件名不变,仅后缀发生变化)** @param sourceDir 要压缩的文件存放的目录* @param targetDir 要存放的路径* @return* @throws IOException*/public static DataEntity<Void> filesTarGzip(String sourceDir, String targetDir) throws IOException {log.info("{} 开始批量执行压缩文件...", targetDir);File dir = new File(sourceDir);//获取目标文件夹下的所有文件夹File fileDir = dir.listFiles()[0];File[] files = fileDir.listFiles();assert files != null;for (File f : files) {fileTarGzip(f, targetDir);}log.info("{} 文件批量压缩完成。", targetDir);return DataUtils.success();}

4.方法的调用

FileOperateService.java

@Slf4j
@Service
public class FileOperateService {/*** 批量处理文件:把压缩文件解压、将解压后的文件经纬度数据替换成0,重新把文件压缩回原来的目录* @param source    文件夹路径:存放要处理的文件* @param temp      文件夹路径:任意临时文件夹* @param temp2     文件夹路径:任意临时文件夹* @return* @throws IOException*/public DataEntity<Void> operate(String source, String temp, String temp2) throws IOException {//把source目录下的.tar.gz文件批量解压成.txt文件到临时temp目录下DataEntity<Void> decompressFiles = FileUpdateUtils.batchDecompressTarGzip(source, temp);if (decompressFiles.isOk()) {//把临时temp目录下的.txt文件批量替换掉经纬度数据后,存到临时temp2目录下DataEntity<File[]> readAndReplaceData = FileUpdateUtils.readAndReplaceTxt(temp, temp2);//如果经纬度替换成功,就删除临时目录tempFileUpdateUtils.deleteTempDir(temp);if (readAndReplaceData.isOk()) {//把临时temp2目录下的.txt文件压缩成.tar.gz文件,存放到source目录下DataEntity<Void> compressFiles = FileUpdateUtils.filesTarGzip(temp2, source);//如果压缩成功,就删除临时目录temp2FileUpdateUtils.deleteTempDir(temp2);return compressFiles;} else {return DataUtils.fail(readAndReplaceData.getMessage());}}return decompressFiles;}}

FileUpdateResource.java

@RestController
@RequestMapping("/api")
public class FileUpdateResource {private final Logger log = LoggerFactory.getLogger(FileUpdateResource.class);private final FileOperateService fileOperateService;public FileUpdateResource(FileOperateService fileOperateService) {this.fileOperateService = fileOperateService;}/*** 批量处理文件:把压缩文件内的经纬度数据替换成0* @param source    文件夹路径:存放要处理的文件* @param temp      文件夹路径:任意临时文件夹* @param temp2     文件夹路径:任意临时文件夹* @return* @throws IOException*/@PostMapping("/file/operate")public DataEntity<Void> operateFile(@RequestParam("source") String source,@RequestParam("temp") String temp,@RequestParam("temp2") String temp2) throws IOException {log.debug("REST request operate File");return fileOperateService.operate(source,temp,temp2);}
}

5.需要添加的依赖

        <dependency><groupId>org.apache.ant</groupId><artifactId>ant</artifactId><version>1.8.1</version></dependency><dependency><groupId>com.github.junrar</groupId><artifactId>junrar</artifactId><version>0.7</version></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId></dependency>

四、执行结果

如图所示:

在这里插入图片描述

五、用到的工具类

import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
import org.apache.commons.compress.utils.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.tools.tar.TarEntry;
import org.apache.tools.tar.TarOutputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.zip.GZIPOutputStream;public class FileUpdateUtils {public static final String TARGZ = ".tar.gz";private static final String TXT = ".txt";private static final String TMP = ".tmp";private static final Logger log = LoggerFactory.getLogger(TarGzUtils.class);// 文件删除任务的线程池private static ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);/*** 批量解压文件夹下的所有.tar.gz文件** @param sourcePath 要解压的文件夹* @param targetPath 解压到目标路径* @return*/public static DataEntity<Void> batchDecompressTarGzip(String sourcePath, String targetPath) throws IOException {log.info("{} 开始批量解压文件 ...", sourcePath);deleteDirAfterNSeconds(new File(targetPath),0);File dir = new File(sourcePath);//遍历文件夹,获取文件完整路径File[] files = dir.listFiles();assert files != null;for (File f : files) {String filePath = sourcePath + File.separator + f.getName();//把所有文件解压到目标文件夹deCompressTarGzip(filePath, targetPath + File.separator + dir.getName());}log.info("{} 文件批量解压完成。", sourcePath);return DataUtils.success();}/*** 解压.tar.gz文件** @param sourcePath 要解压的文件路径加文件名* @param targetPath 解压到目标路径* @return* @throws IOException*/public static DataEntity<Void> deCompressTarGzip(String sourcePath, String targetPath) throws IOException {
//        //解压文件
//        Path source = Paths.get("/home/test/output" + TARGZ);
//        //解压到哪
//        Path target = Paths.get("/home/test2");//解压文件Path source = Paths.get(sourcePath);//解压到哪Path target = Paths.get(targetPath);if (Files.notExists(source)) {return DataUtils.fail("您要解压的文件不存在: " + source.toAbsolutePath());}//InputStream输入流,以下四个流将tar.gz读取到内存并操作//BufferedInputStream缓冲输入流//GzipCompressorInputStream解压输入流//TarArchiveInputStream解tar包输入流try (InputStream fi = Files.newInputStream(source);BufferedInputStream bi = new BufferedInputStream(fi);GzipCompressorInputStream gzi = new GzipCompressorInputStream(bi);TarArchiveInputStream ti = new TarArchiveInputStream(gzi)) {ArchiveEntry entry;while ((entry = ti.getNextEntry()) != null) {//获取解压文件目录,并判断文件是否损坏DataEntity<Path> res = zipSlipProtect(entry, target);if (!res.isOk()) {return DataUtils.fail(res.getMessage());}Path newPath = res.getData();if (entry.isDirectory()) {//创建解压文件目录Files.createDirectories(newPath);} else {//再次校验解压文件目录是否存在Path parent = newPath.getParent();if (parent != null) {if (Files.notExists(parent)) {Files.createDirectories(parent);}}// 将解压文件输入到TarArchiveInputStream,输出到磁盘newPath目录Files.copy(ti, newPath, StandardCopyOption.REPLACE_EXISTING);}}}return DataUtils.success();}/*** 批量读取和替换txt文件:把经纬度数据替换成0** @param sourcePath 存放.txt文件的目录* @return*/public static DataEntity<Void> readAndReplaceTxt(String sourcePath, String targetPath) throws IOException {log.info("开始批量替换敏感数据");deleteDirAfterNSeconds(new File(targetPath),0);File dir = new File(sourcePath);File fileDir = dir.listFiles()[0];File[] files = fileDir.listFiles();//遍历文件assert files != null;for (File file : files) {String newFileName = file.getName();String newFileDir = targetPath + File.separator + fileDir.getName();Files.createDirectories(Paths.get(newFileDir));String newFilePath = newFileDir + File.separator + newFileName;try (BufferedReader bufferedReader = new BufferedReader(new FileReader(file))) {//构造一个BufferedReader类来读取文件String lineTxt = null;//result用来存储文件内容
//                    StringBuilder result = new StringBuilder();//按使用readLine方法,一次读一行while ((lineTxt = bufferedReader.readLine()) != null) {//替换int i = StringUtils.ordinalIndexOf(lineTxt, "\t", 2);int j = StringUtils.ordinalIndexOf(lineTxt, "\t", 4);String newContent = lineTxt.replace(lineTxt.substring(i, j), "\t0\t0");//替换
//                        result.append(newContent);File newFile = new File(newFilePath);PrintStream ps = new PrintStream(new FileOutputStream(newFile, true));ps.println(newContent);// 往.txt文件里写入字符串}log.info("文件 {} 中敏感数据替换执行完毕", newFilePath);} catch (Exception e) {log.error("读取文件 {} 内容出错", newFilePath);return DataUtils.fail(e.getMessage());}}log.info("敏感数据批量替换完成。");return DataUtils.success();}//判断压缩文件是否被损坏,并返回该文件的解压目录private static DataEntity<Path> zipSlipProtect(ArchiveEntry entry, Path targetDir) {Path targetDirResolved = targetDir.resolve(entry.getName());Path normalizePath = targetDirResolved.normalize();if (!normalizePath.startsWith(targetDir)) {log.error("压缩文件已被损坏: {}", entry.getName());return DataUtils.fail("压缩文件已被损坏" + entry.getName());}return DataUtils.entityData(normalizePath);}/*** 压缩.txt文件为.tar.gz文件(压缩后文件名不变,仅后缀发生变化)** @param resourceFile 要压缩的文件* @param targetDir    要存放的路径* @return* @throws IOException*/public static DataEntity<Void> fileTarGzip(File resourceFile, String targetDir) throws IOException {//获取输出后的文件名String oldName = resourceFile.getName();int i = oldName.indexOf(TXT);String newName = oldName.substring(0, i) + TARGZ;String outPath = targetDir + File.separator + newName;Path path = Paths.get(outPath + TMP);try (FileOutputStream fileOutputStream = new FileOutputStream(outPath + TMP);BufferedOutputStream bufferedOutput = new BufferedOutputStream(fileOutputStream);TarOutputStream tarOutputStream = new TarOutputStream(bufferedOutput);FileInputStream fileInputStream = new FileInputStream(resourceFile);BufferedInputStream bufferedInput = new BufferedInputStream(fileInputStream);) {TarEntry entry = new TarEntry(new File(oldName));entry.setSize(resourceFile.length());tarOutputStream.putNextEntry(entry);IOUtils.copy(bufferedInput, tarOutputStream);tarOutputStream.closeEntry();} catch (Exception e) {Files.delete(path);log.error("文件压缩至 {} 执行异常,嵌套异常!", outPath, e);}// 读取打包好的 tar 临时文件,使用 GZIP 方式压缩try (FileInputStream fin = new FileInputStream(outPath + TMP);BufferedInputStream bin = new BufferedInputStream(fin);FileOutputStream fout = new FileOutputStream(outPath);GZIPOutputStream gout = new GZIPOutputStream(fout);BufferedOutputStream bout = new BufferedOutputStream(gout);) {byte[] cache = new byte[1024];for (int index = bin.read(cache); index != -1; index = bin.read(cache)) {bout.write(cache, 0, index);}log.info("文件 {} 压缩执行完毕", outPath);} catch (Exception e) {log.error("文件压缩至 {} 执行异常,嵌套异常!", outPath, e);} finally {Files.delete(path);}return DataUtils.success();}/*** 批量压缩.txt文件为.tar.gz文件(压缩后文件名不变,仅后缀发生变化)** @param sourceDir 要压缩的文件存放的目录* @param targetDir 要存放的路径* @return* @throws IOException*/public static DataEntity<Void> filesTarGzip(String sourceDir, String targetDir) throws IOException {log.info("{} 开始批量执行压缩文件...", targetDir);File dir = new File(sourceDir);//获取目标文件夹下的所有文件夹File fileDir = dir.listFiles()[0];File[] files = fileDir.listFiles();assert files != null;for (File f : files) {fileTarGzip(f, targetDir);}log.info("{} 文件批量压缩完成。", targetDir);return DataUtils.success();}/*** 删除一个文件夹和里面的文件** @param dirPath 文件夹路径* @return*/public static DataEntity<Void> deleteTempDir(String dirPath) {System.gc();File file = new File(dirPath);deleteFile(file);
//        if (deleteFile(file).isOk()) {
//            log.info(dirPath + "目录下文件删除成功!");
//        }return DataUtils.success();}public static DataEntity<Void> deleteFile(File file) {//判断文件不为null或文件目录存在if (file == null || !file.exists()) {return DataUtils.fail("文件删除失败,请检查文件是否存在以及文件路径是否正确");}//获取目录下子文件File[] files = file.listFiles();//遍历该目录下的文件对象assert files != null;for (File f : files) {//判断子目录是否存在子目录,如果是文件则删除if (f.isDirectory()) {//递归删除目录下的文件deleteFile(f);} else {//文件删除f.delete();}}//文件夹删除file.delete();return DataUtils.success();}/*** 延迟若干秒后执行删除操作* @param file* @param seconds*/public static void deleteDirAfterNSeconds(File file, int seconds) {scheduledThreadPool.schedule(new Runnable() {public void run() {try {if (file.exists()) {// 两种删除方式都用上deleteDir(file);deleteDirByCmd(file);}} catch (Throwable e) {e.printStackTrace();}}}, seconds, TimeUnit.SECONDS);}/*** 通过调用系统命令删除一个文件夹及下面的所有文件*/public static void deleteDirByCmd(File file) {// 文件不存在直接返回if (null == file || !file.exists()) {return;}// 文件存在时执行删除操作Runtime rt = Runtime.getRuntime();try {String cmd = null;if (file.isFile()) {cmd = "cmd.exe /c del /q/a/f/s " + file.getAbsolutePath();} else {cmd = "cmd.exe /c rd /s/q " + file.getAbsolutePath();}rt.exec(cmd);} catch (Exception e) {e.printStackTrace();}}/*** 递归删除目录下的所有文件及子目录下所有文件* @param dir 将要删除的文件目录|文件*/public static boolean deleteDir(File dir) {if (dir.isDirectory()) {String[] children = dir.list();for (int i = 0; i < children.length; i++) {boolean success = deleteDir(new File(dir, children[i]));if (!success) {return false;}}}return dir.delete();}}

六、可以改进的地方

1.文件处理完成后,删除临时文件和文件夹会出现删除失败的问题

问题背景:

通过IO流操作过文件后,最后想删除过程中产生的临时文件,有部分文件未被删除,也不报错。
已经检查过所有的流都关闭了。

问题原因:

临时文件对象在java虚拟机(jvm)中还未被解除引用,虽然看似没有变量指向这个临时文件对象了,但还没来得急被垃圾收集器自动回收解除引用。

解决:

方案一:执行删除操作前手动把垃圾回收一下

/*** 删除一个文件夹和里面的文件** @param dirPath 文件夹路径* @return*/
public static DataEntity<Void> deleteTempDir(String dirPath) {System.gc();File file = new File(dirPath);deleteFile(file);if (deleteFile(file).isOk()) {log.info(dirPath + "目录下文件删除成功!");}return DataUtils.success();
}public static DataEntity<Void> deleteFile(File file) {//判断文件不为null或文件目录存在if (file == null || !file.exists()) {return DataUtils.fail("文件删除失败,请检查文件是否存在以及文件路径是否正确");}//获取目录下子文件File[] files = file.listFiles();//遍历该目录下的文件对象assert files != null;for (File f : files) {//判断子目录是否存在子目录,如果是文件则删除if (f.isDirectory()) {//递归删除目录下的文件deleteFile(f);} else {//文件删除f.delete();}}//文件夹删除file.delete();return DataUtils.success();
}

方案二:延时若干秒后对文件进行删除

import java.io.File;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;/*** 文件删除工具类*/
public class FileDeleteUtil {// 文件删除任务的线程池private static ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);/*** 延迟若干秒后执行删除操作* @param file* @param seconds*/public static void deleteDirAfterNSeconds(File file, int seconds) {scheduledThreadPool.schedule(new Runnable() {public void run() {try {if (file.exists()) {// 两种删除方式都用上deleteDir(file);deleteDirByCmd(file);}} catch (Throwable e) {e.printStackTrace();}}}, seconds, TimeUnit.SECONDS);}/*** 通过调用系统命令删除一个文件夹及下面的所有文件*/public static void deleteDirByCmd(File file) {// 文件不存在直接返回if (null == file || !file.exists()) {return;}// 文件存在时执行删除操作Runtime rt = Runtime.getRuntime();try {String cmd = null;if (file.isFile()) {cmd = "cmd.exe /c del /q/a/f/s " + file.getAbsolutePath();} else {cmd = "cmd.exe /c rd /s/q " + file.getAbsolutePath();}rt.exec(cmd);} catch (Exception e) {e.printStackTrace();}}/*** 递归删除目录下的所有文件及子目录下所有文件* @param dir 将要删除的文件目录|文件*/public static boolean deleteDir(File dir) {if (dir.isDirectory()) {String[] children = dir.list();for (int i = 0; i < children.length; i++) {boolean success = deleteDir(new File(dir, children[i]));if (!success) {return false;}}}return dir.delete();}
}

2.调用方法时所有操作(解压-修改数据-压缩-保存)可以分文件夹完成

全量数据都一次性操作完成的话,在数据量大的情况下,就会非常占用内存空间,可以采用所有操作分目录进行(解压-修改数据-压缩-保存)的方式来,修改调用代码如下:
(同时把方法调用的参数写到了配置文件里,因为本操作只需要执行一次,所以不需要写成接口。)

/*** 批量处理文件:把压缩文件解压、将解压后的文件经纬度数据替换成0,重新把文件压缩回原来的目录* @return* @throws IOException*/public DataEntity<Void> operate() throws IOException {String source = conf.getSource();String temp = conf.getTemp();String temp2 = conf.getTemp2();Integer start = conf.getStart();Integer end = conf.getEnd();File dirs = new File(source);for (File dir : dirs.listFiles()) {String dirName = dir.getName();Integer date = getDate(dirName);//遍历日期文件夹,处理日期范围内的文件夹内的压缩文件if (start <= date && date <= end) {//把source\日期目录下的.tar.gz文件批量解压成.txt文件到临时temp目录下DataEntity<Void> decompressFiles = FileUpdateUtils.batchDecompressTarGzip(source+File.separator+dirName, temp);if (decompressFiles.isOk()) {//把临时temp目录下的.txt文件批量替换掉经纬度数据后,存到临时temp2目录下DataEntity<Void> readAndReplaceData = FileUpdateUtils.readAndReplaceTxt(temp, temp2);if (readAndReplaceData.isOk()) {//把临时temp2目录下的.txt文件压缩成.tar.gz文件,存放到source目录下DataEntity<Void> compressFiles = FileUpdateUtils.filesTarGzip(temp2, source+File.separator+dirName);}}//删除临时目录和其中的临时文件FileUpdateUtils.deleteTempDir(temp);FileUpdateUtils.deleteTempDir(temp2);log.info("{} 敏感数据已经完成替换。", date);}}//再次删除临时目录和其中的临时文件FileUpdateUtils.deleteDirAfterNSeconds(new File(temp),3);FileUpdateUtils.deleteDirAfterNSeconds(new File(temp2),3);return DataUtils.success();}private Integer getDate(String dirName) {return Integer.parseInt(dirName.substring(0, 8));}

http://www.ppmy.cn/news/6876.html

相关文章

一文清晰带你弄清楚Spring IOC 循环依赖问题是如何解决的

什么是循环依赖 循环依赖又被成为循环引用,即两个或者多个bean相互之间的持有对方,比如A 引用B,B引用C,C 又引用A,则它们最终反映为一个环,如下图所示: 循环依赖是对象之间的相互依赖关系,循环依赖就是一个死循环,除非有终结条件,否则就是死循环,最终导致内存溢出错误. 解决…

Java多线程之线程安全问题

文章目录一. 线程安全概述1. 什么是线程安全问题2. 一个存在线程安全问题的程序二. 线程不安全的原因和线程加锁1. 案例分析2. 线程加锁2.1 理解加锁2.2 synchronized的使用2.3 再次分析案例3. 线程不安全的原因三. 线程安全的标准类一. 线程安全概述 1. 什么是线程安全问题 …

SpringBoot 整合 Shiro 实现动态权限加载更新+ Session 共享 + 单点登录

一.说明 二.项目环境 二.编写项目基础类 三.编写Shiro核心类 四.实现权限控制 五.POSTMAN测试 六.项目源码 一.说明 Shiro是一个安全框架,项目中主要用它做认证,授权,加密,以及用户的会话管理,虽然Shiro没有SpringSecurity功能更丰富,但是它轻量,简单,在项目中通常业务…

国内内网穿透市场现状及头部厂商发展路线分析

疫情三年&#xff0c;居家办公是常态&#xff0c;我们不得不远程访问公司内网部署的OA、ERP、CRM、数据库等应用系统&#xff0c;才能顺利完成工作&#xff0c;这一场景把内网穿透这一专业化技术推到普罗大众面前。 内网穿透也叫NAT穿透&#xff0c;又被称为端口映射或内网映射…

html表格-FineReport 配置Oracle外接数据库(1)

1. 概述 1.1 版本 报表服务器版本 功能变更 11.0 - 11.0.3 1&#xff09;首次配置外接数据库时&#xff0c;支持自行选择是否「迁移数据至要启用的数据库」2&#xff09;迁移外接数据库的过程提示细化&#xff0c;方便用户了解迁移进度 1.2 功能简介 报表系统配置外接数…

前端食堂技术周刊第 64 期:Node.js 19、Interop 2022、SvelteKit 1.0、2022 Web 性能回顾、最流行的 Node.js

美味值&#xff1a;&#x1f31f;&#x1f31f;&#x1f31f;&#x1f31f;&#x1f31f; 口味&#xff1a;冰糖雪梨 食堂技术周刊仓库地址&#xff1a;https://github.com/Geekhyt/weekly 本期摘要 Node.js 19 的新特性Interop 2022 年终更新SvelteKit 1.02022 Web 性能回…

医疗产品设计的新趋势

随着个人健康和医疗数据技术的发展&#xff0c;消费者可以选择更多的方法来跟踪和管理他们的健康状况&#xff0c;因此医疗产品开始转向更多的健康预防领域。医疗器械设计公司认为&#xff0c;随着医疗产品设计从医疗产品转向家庭&#xff0c;医疗产品的设计需要考虑更多的新问…

力扣(LeetCode)1759. 统计同构子字符串的数目(C++)

题目描述 双指针数学 根据同构字符串的定义&#xff0c;还有示例&#xff0c;发现同构子字符串的数量&#xff0c;只和字母相同的区间有关。如abbcccaa&#xff0c;有 444 个影响答案的区间&#xff0c;直观切分为a bb ccc aa&#xff0c;用空格划分区间。遍历的任务就是维护这…