Javaファイルの比較
実は、この書き方には少し問題があります。複数のスレッドを読み取るために 1 つのスレッドを比較するというアイデアがあり、その結果、1 つのスレッドを読み取り、比較するために 1 つのスレッドを作成することになります。結局のところ、これは書き方のアイデアです
。
コントローラ
package com.taiyusoft.tydms.controller;
import com.alibaba.fastjson.JSONObject;
import com.taiyusoft.tydms.entity.ResponseForm;
import com.taiyusoft.tydms.service.FileComparesService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.File;
/***
* @Author
* @Param
* @return
**/
@RestController
@RequestMapping("/fileComparesimple")
public class FileCompareController {
private Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private FileComparesService fileComparesService;
@RequestMapping("/selectfileComparesimple")
public void fileComparesimple(String firstpath, String secondpath) {
long time1 = System.currentTimeMillis();
File file = new File(firstpath);
if (file.isFile() || file.isDirectory()) {
JSONObject list = fileComparesService.fileComparesimple(firstpath, secondpath);
}
long time2 = System.currentTimeMillis();
int time = (int) ((time2 - time1) / 1000);
System.out.println("执行了:" + time + "秒!");
}
/**
* 进度条初始化 直接调用文件对比
*
* @return
*/
@RequestMapping("/fileComparesinit")
public ResponseForm fileComparesinit(String firstpath, String secondpath) {
ResponseForm responseForm = new ResponseForm();
Integer sum = 0;
try {
sum = fileComparesService.initPercentage(firstpath, secondpath);
if (sum != 0) {
File file1 = new File(firstpath);
File file2 = new File(secondpath);
if (file1.isFile() || file1.isDirectory() && file2.isFile() || file2.isDirectory()) {
JSONObject list = fileComparesService.fileComparesimple(firstpath, secondpath);
responseForm.setData(list);
responseForm.setCode("200");
responseForm.setMessage(ResponseForm.message.SUCCESS);
}
}
} catch (Exception e) {
e.printStackTrace();
responseForm.setCode("400");
responseForm.setMessage(ResponseForm.message.FAIL);
}
return responseForm;
}
/**
* 文件对比时间过长时,出现该当前文件进度条百分比
*/
@RequestMapping("/fileComparesimplePercentage")
public ResponseForm fileComparesimplePercentage() {
ResponseForm responseForm = new ResponseForm();
JSONObject jsonObject;
try {
jsonObject = fileComparesService.fileComparesimplePercentage();
responseForm.setData(jsonObject);
responseForm.setCode("200");
responseForm.setMessage(ResponseForm.message.SUCCESS);
} catch (Exception e) {
responseForm.setCode("400");
responseForm.setMessage(ResponseForm.message.FAIL);
}
return responseForm;
}
/**
* 文件处理时间过长时,专门获取文件对比结果
*
* @return
*/
@RequestMapping("/getfileCompares")
public ResponseForm getfileCompares() {
ResponseForm responseForm = new ResponseForm();
JSONObject jsonObject;
try {
jsonObject = fileComparesService.getfileCompares();
responseForm.setData(jsonObject);
responseForm.setCode("200");
responseForm.setMessage(ResponseForm.message.SUCCESS);
} catch (Exception e) {
responseForm.setCode("400");
responseForm.setMessage(ResponseForm.message.FAIL);
}
return responseForm;
}
}
サービス
package com.taiyusoft.tydms.service;
import com.alibaba.fastjson.JSONObject;
public interface FileComparesService {
JSONObject fileComparesimple(String firstpath, String secondpath);
Integer initPercentage(String firstpath, String secondpath);
JSONObject fileComparesimplePercentage();
JSONObject getfileCompares();
}
サービス概要
package com.taiyusoft.tydms.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.taiyusoft.tydms.base.util.CompareThreadUtil;
import com.taiyusoft.tydms.base.util.ReadFile2;
import com.taiyusoft.tydms.entity.Fc;
import com.taiyusoft.tydms.service.FileComparesService;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@Service
public class FileComparesServiceImpl implements FileComparesService {
private static final Logger logger = Logger.getLogger(FileComparesServiceImpl.class);
public static String syncCurrentName1 = null; // 进度条name
public static String percentage1 ; // 进度条百分比
public static Integer percentagesum1 = null; // 文件总数
public static int countfile;//当前文件个数
public static final ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>();//全局静态变量
private List listoneNot1 = new ArrayList<Fc>(); //存放数据一缺失的数据
private List listoneNot2 = new ArrayList<Fc>(); //存放数据二缺失的数据
private List listoneNot3 = new ArrayList<Fc>(); //存放数据二缺失的数据
public static boolean flag;
private Boolean[] scanStop = new Boolean[1]; // 检测停止标识
@Override
public JSONObject fileComparesimple(String firstpath, String secondpath) {
long startTime = System.currentTimeMillis();
int cpuCount = 4;
// String dirName1 = "C:\\Users\\taiyu\\Desktop\\file2\\10w";
String dirName1 = firstpath;
File root1 = new File(dirName1);
String dirName2 = secondpath;
File root2 = new File(dirName2);
listoneNot1 = new ArrayList<Fc>();
listoneNot2 = new ArrayList<Fc>();
listoneNot3 = new ArrayList<Fc>();
scanStop[0] = true;
List list = new ArrayList();
list.add(dirName1);
list.add(dirName2);
logger.info("分配线程开始...");
CountDownLatch latchs = new CountDownLatch(cpuCount + 1);
ExecutorService exec = Executors.newCachedThreadPool();
// 读取文件线程
final ReadFile2 trFile1 = new ReadFile2(
latchs, null, list,
dirName1, dirName2,scanStop);
logger.info("读取文件线程启动...");
exec.execute(new Thread() {
@Override
public void run() {
trFile1.readFile();
}
});
final CompareThreadUtil thDao = new CompareThreadUtil(
latchs, null, list, listoneNot1,
listoneNot2, listoneNot3, root1,
root2, dirName1, dirName2, trFile1,scanStop);
for (int i = 0; i < cpuCount; i++) {
System.out.println("检测线程" + i + " 启动...");
final int currentID = i;
exec.execute(new Thread() {
@Override
public void run() {
thDao.addFileLevelAfter(currentID,percentagesum1,countfile);
}
});
}
try {
exec.shutdown();
latchs.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
//结束时间
long endTime1 = System.currentTimeMillis();
//打印
System.out.println("对比运行时间:" + (double) (endTime1 - startTime) / 1000 + "s");
//打印数据1缺失数据
if (listoneNot1.size() > 0) {
logger.info("数据1删除的文件如下");
for (int i = 0; i < listoneNot1.size(); i++) {
logger.info(((Fc) listoneNot1.get(0)).getPath());
}
} else {
logger.info("数据1无删除的文件...");
}
//打印数据2缺失数据
if (listoneNot2.size() > 0) {
logger.info("数据2删除的文件如下");
for (int i = 0; i < listoneNot2.size(); i++) {
logger.info(((Fc) listoneNot2.get(i)).getPath());
}
} else {
logger.info("数据2无删除文件");
}
//打印数据3缺失数据
if (listoneNot3.size() > 0) {
logger.info("两数据源之间发生修改的文件如下");
for (int i = 0; i < listoneNot3.size(); i++) {
logger.info(((Fc) listoneNot3.get(i)).getPath());
}
} else {
logger.info("两数据源之间无发生修改的文件");
}
//结束时间
long endTime = System.currentTimeMillis();
//打印
System.out.println("程序运行时间:" + (double) (endTime - startTime) / 1000 + "s");
JSONObject jsonObject = new JSONObject();
jsonObject.put("数据源1发生删除的文件",listoneNot1);
jsonObject.put("数据源2发生删除的文件",listoneNot2);
jsonObject.put("两数据源对比发生修改的文件",listoneNot3);
flag=true;
jsonObject.put("flag",flag);
return jsonObject;
}
@Override
public Integer initPercentage(String firstpath, String secondpath) {
flag=false;
percentagesum1=0;
percentage1="";
syncCurrentName1="";
readFileInfo(new File(firstpath));
readFileInfo(new File(secondpath));
return percentagesum1;
}
@Override
public JSONObject fileComparesimplePercentage() {
JSONObject jsonObject = new JSONObject();
jsonObject.put("百分比",percentage1);
jsonObject.put("当前进行到的文件",syncCurrentName1);
jsonObject.put("flag",flag);//为true时可以取结果
return jsonObject;
}
@Override
public JSONObject getfileCompares() {
JSONObject jsonObject = new JSONObject();
jsonObject.put("数据源1发生删除的文件",listoneNot1);
jsonObject.put("数据源2发生删除的文件",listoneNot2);
jsonObject.put("两数据源对比发生修改的文件",listoneNot3);
return jsonObject;
}
private void readFileInfo(File root) {
if (root.exists()) {
if (root.isDirectory()) {
File[] files = root.listFiles();
if (files != null) {
for (int i = 0; i < files.length; i++) {
if (files[i].isFile()) {
percentagesum1++;
} else if (files[i].isDirectory()) {
readFileInfo(files[i]);
}
files[i] = null;
}
}
files = null;
} else if (root.isFile()) {
percentagesum1++;
}
}
}
}
ファイル読み取りマルチスレッド ツール クラス
package com.taiyusoft.tydms.base.util;
import java.io.File;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ReadFile2 {
// private static final Logger logger = Logger.getLogger(ReadFile.class);
private CountDownLatch latch;
private CyclicBarrier barrier;
private LinkedList<File> linkedList = new LinkedList();//总
private Lock lock = new ReentrantLock();
private Object numberLock = new Object();
private boolean lockboo = false;
private List<String> list;
private File root1;
private File root2;
private String dirName1;
private String dirName2;
private Boolean[] StopIt;
public ReadFile2(CountDownLatch latch, CyclicBarrier barrier,
List list,
String dirName1, String dirName2,
Boolean[] stop
) {
this.latch = latch;
this.barrier = barrier;
this.list = list;
this.dirName1 = dirName1;
this.dirName2 = dirName2;
this.StopIt = stop;
}
// 读取文件信息
public void readFile() {
try {
readFileInfo(new File(list.get(0)));
readFileInfo(new File(list.get(1)));
// logger.info("读取文件线程正常停止!");
System.out.println("读取文件线程正常停止!");
} catch (Exception e) {
System.out.println("错误信息!" + e);
} finally {
StopIt[0] = false;
latch.countDown();
}
}
private void readFileInfo(File root) {
if (root.exists()) {
if (root.isDirectory()) {
File[] files = root.listFiles();
if (files != null) {
for (int i = 0; i < files.length; i++) {
if (files[i].isFile()) {
addFile(files[i]);
} else if (files[i].isDirectory()) {
readFileInfo(files[i]);
}
files[i] = null;
}
}
files = null;
} else if (root.isFile()) {
addFile(root);
}
}
}
private void addFile(File file) {
lock.lock();
try {
linkedList.addLast(file);
} catch (Exception e) {
System.out.println("添加文件出错:" + e);
} finally {
lock.unlock();
// try {
// if (linkedList.size() >= 10000) {
// synchronized (numberLock) {
// lockboo = true;
// numberLock.wait();
// }
// }
// } catch (Exception e2) {
logger.error("锁出错:", e2);
// System.out.println("锁出错" + e2);
// }
}
}
public void getFileInfo(File[] file) {
lock.lock();
try {
file[0] = linkedList.pollFirst();
if (lockboo && linkedList.size() <= 1000) {
synchronized (numberLock) {
lockboo = false;
numberLock.notify();
}
}
} catch (Exception e) {
// logger.error("获取文件出错:", e);
System.out.println("获取文件出错:" + e);
} finally {
lock.unlock();
}
}
}
ファイルマルチスレッドツールの比較
package com.taiyusoft.tydms.base.util;
import com.taiyusoft.tydms.entity.Fc;
import com.taiyusoft.tydms.service.impl.FileComparesServiceImpl;
import java.io.File;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class CompareThreadUtil {
private CountDownLatch latch;
private CyclicBarrier barrier;
private LinkedList linkedList = new LinkedList();//总
private LinkedList<Fc> linkedList1 = new LinkedList<Fc>();//读取路径1中的所有的文件
private LinkedList<Fc> linkedList2 = new LinkedList<Fc>();//读取路径2中的所有的文件
private Lock lock = new ReentrantLock();
private List listoneNot1 = new ArrayList<Fc>(); //存放数据一缺失的数据
private List listoneNot2 = new ArrayList<Fc>(); //存放数据二缺失的数据
private List listoneNot3 = new ArrayList<Fc>(); //存放数据二缺失的数据
private Object numberLock = new Object();
private boolean lockboo = false;
private List<String> list;
private File root1;
private File root2;
private String dirName1;
private String dirName2;
private ReadFile2 trFile1;
private Boolean[] StopIt;
public CompareThreadUtil(CountDownLatch latch, CyclicBarrier barrier,
List list,
List<Fc> listoneNot1, List<Fc> listoneNot2,
List<Fc> listoneNot3, File root1, File root2,
String dirName1, String dirName2, ReadFile2 trFile1, Boolean[] stop
) {
this.latch = latch;
this.barrier = barrier;
this.list = list;
this.listoneNot1 = listoneNot1;
this.listoneNot2 = listoneNot2;
this.listoneNot3 = listoneNot3;
this.root1 = root1;
this.root2 = root2;
this.dirName1 = dirName1;
this.dirName2 = dirName2;
this.trFile1 = trFile1;
this.StopIt = stop;
}
public void addFileLevelAfter(int currentID, Integer percentagesum1, int i) {
File[] file = new File[1];
File f0File = null;
lock.lock();
try {
while (true) {
trFile1.getFileInfo(file);
f0File = file[0];
if (!StopIt[0] && f0File == null) {
System.out.println("线程" + currentID + " 突然停止!");
break;
}
if (f0File != null) {
i++;
NumberFormat numberFormat = NumberFormat.getNumberInstance();
numberFormat.setMaximumFractionDigits(2);
String result = numberFormat.format((float) i / (float) percentagesum1 * 100);
FileComparesServiceImpl.percentage1 = result + "%";
FileComparesServiceImpl.syncCurrentName1 = f0File.getName();
System.out.println("当前为检测线程" + currentID + "读取的文件为第" + i + "个文件" + "文件名为" + f0File + " 文件总数为" + percentagesum1);
System.out.println("此时百分比为" + FileComparesServiceImpl.percentage1);
if (String.valueOf(f0File).startsWith(dirName1)) {
File file1 = new File(f0File.toString().replace(dirName1, dirName2));
if (file1.exists()) {
if (f0File.lastModified() != file1.lastModified()) {
Fc fc1 = new Fc();
fc1.setPath(f0File.getPath());
fc1.setLastmodified(String.valueOf(f0File.lastModified()));
fc1.setMd5(Md5.getMD5File(f0File));
listoneNot3.add(fc1);
}
} else {
Fc fc = new Fc();
fc.setPath(f0File.getPath());
fc.setLastmodified(String.valueOf(f0File.lastModified()));
fc.setMd5(Md5.getMD5File(f0File));
listoneNot1.add(fc);
}
} else {
File file2 = new File(f0File.toString().replace(dirName2, dirName1));
if (file2.exists()) {
if (f0File.lastModified() != file2.lastModified()) {
Fc fc1 = new Fc();
fc1.setPath(f0File.getPath());
fc1.setLastmodified(String.valueOf(f0File.lastModified()));
fc1.setMd5(Md5.getMD5File(f0File));
listoneNot3.add(fc1);
}
} else {
Fc fc = new Fc();
fc.setPath(f0File.getPath());
fc.setLastmodified(String.valueOf(f0File.lastModified()));
fc.setMd5(Md5.getMD5File(f0File));
listoneNot2.add(fc);
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
System.out.println("线程" + currentID + " 正常停止!");
} finally {
lock.unlock();
latch.countDown();
}
}
}
コンソールの結果
検出スレッドは特定のファイルと比較される必要があります (ただし無害です)
結果を返す
プログレスバーの結果
個人的なまとめ
このファイル比較の機能は半月以上かけて書いており、
ステップ数は約
0です。まず要件を伝え、要件の難易度を軽減できるかどうかを確認します(非常に重要です)(たとえば、最初のアイデアファイル比較とは、アイデア コントラストに似たファイルを作成することですが、アイデアのファイル比較の規模は何桁ですか? どの桁が必要かわかりませんか?) 1. 最初に書くアイデアを持ち
、人に聞いても、自分で考えても、どこかのブログで読んでも、大事なのは実現するという発想です。
2. デモを作成し、アイデアを試して、それが機能するかどうかを確認します。
3. 最適化の考え方は基本的に、マルチスレッドを実装し、マルチスレッドを調整することです。
4. 関数の実行時間が満足できるかどうかを確認し、満足できない場合は 1、2、3 を繰り返します (ファイル比較の列から、元の解決策である 5 ~ 6 つの異なる解決策を書いていることもわかります) 1k ファイルと md5 値の直接比較には 100 秒かかり、20w ファイル比較の最終結果は 15 秒です (通常のノートブック))
5. 最後に、プロジェクト