checksumsMap) {
26 | this.checksumsMap = checksumsMap;
27 | }
28 |
29 | @Override
30 | public MsgType getType() {
31 | return MsgType.CHECK_SUM;
32 | }
33 |
34 |
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/src/main/java/com/laz/filesync/server/msg/FileInfo.java:
--------------------------------------------------------------------------------
1 | package com.laz.filesync.server.msg;
2 |
3 | public class FileInfo {
4 | private String filename;
5 | private long length;
6 |
7 | public void setFilename(String filename) {
8 | this.filename = filename;
9 | }
10 |
11 | public String getFilename() {
12 | return filename;
13 | }
14 | public void setLength(long length) {
15 | this.length = length;
16 | }
17 |
18 | public long getLength() {
19 | return length;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/com/laz/filesync/util/Coder.java:
--------------------------------------------------------------------------------
1 | package com.laz.filesync.util;
2 |
3 |
4 | import java.security.MessageDigest;
5 |
6 | import javax.crypto.KeyGenerator;
7 | import javax.crypto.Mac;
8 | import javax.crypto.SecretKey;
9 | import javax.crypto.spec.SecretKeySpec;
10 |
11 | import org.apache.commons.codec.binary.Base64;
12 |
13 | public abstract class Coder {
14 | public static final String KEY_SHA = "SHA";
15 | public static final String KEY_MD5 = "MD5";
16 |
17 | /**
18 | * MAC算法可选以下多种算法
19 | *
20 | *
21 | *
22 | * HmacMD5
23 | * HmacSHA1
24 | * HmacSHA256
25 | * HmacSHA384
26 | * HmacSHA512
27 | *
28 | */
29 | public static final String KEY_MAC = "HmacMD5";
30 |
31 | /**
32 | * BASE64解密
33 | *
34 | * @param key
35 | * @return
36 | * @throws Exception
37 | */
38 | public static byte[] decryptBASE64(String key) throws Exception {
39 | return Base64.decodeBase64(key);
40 | }
41 |
42 | /**
43 | * BASE64加密
44 | *
45 | * @param key
46 | * @return
47 | * @throws Exception
48 | */
49 | public static String encryptBASE64(byte[] key) throws Exception {
50 | return Base64.encodeBase64String(key);
51 | }
52 |
53 | /**
54 | * MD5加密
55 | *
56 | * @param data
57 | * @return
58 | * @throws Exception
59 | */
60 | public static byte[] encryptMD5(byte[] data) throws Exception {
61 |
62 | MessageDigest md5 = MessageDigest.getInstance(KEY_MD5);
63 | md5.update(data);
64 |
65 | return md5.digest();
66 |
67 | }
68 |
69 | /**
70 | * SHA加密
71 | *
72 | * @param data
73 | * @return
74 | * @throws Exception
75 | */
76 | public static byte[] encryptSHA(byte[] data) throws Exception {
77 |
78 | MessageDigest sha = MessageDigest.getInstance(KEY_SHA);
79 | sha.update(data);
80 |
81 | return sha.digest();
82 |
83 | }
84 |
85 | /**
86 | * 初始化HMAC密钥
87 | *
88 | * @return
89 | * @throws Exception
90 | */
91 | public static String initMacKey() throws Exception {
92 | KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_MAC);
93 |
94 | SecretKey secretKey = keyGenerator.generateKey();
95 | return encryptBASE64(secretKey.getEncoded());
96 | }
97 |
98 | /**
99 | * HMAC加密
100 | *
101 | * @param data
102 | * @param key
103 | * @return
104 | * @throws Exception
105 | */
106 | public static byte[] encryptHMAC(byte[] data, String key) throws Exception {
107 |
108 | SecretKey secretKey = new SecretKeySpec(decryptBASE64(key), KEY_MAC);
109 | Mac mac = Mac.getInstance(secretKey.getAlgorithm());
110 | mac.init(secretKey);
111 |
112 | return mac.doFinal(data);
113 |
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/src/main/java/com/laz/filesync/util/Constants.java:
--------------------------------------------------------------------------------
1 | package com.laz.filesync.util;
2 |
3 | public class Constants {
4 | public final static String SERVER_MODE = "server";
5 | public final static String CLIENT_MODE = "client";
6 | public final static String TEMP_PREFIX = "diff";
7 | public final static int OBJECT_SIZE_LIMIT = 1024*1024*20;
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/java/com/laz/filesync/util/FileSyncUtil.java:
--------------------------------------------------------------------------------
1 | package com.laz.filesync.util;
2 |
3 | import java.io.File;
4 | import java.io.FileInputStream;
5 | import java.io.IOException;
6 | import java.security.MessageDigest;
7 | import java.security.NoSuchAlgorithmException;
8 | import java.text.DecimalFormat;
9 | import java.time.LocalDate;
10 | import java.time.LocalTime;
11 | import java.util.ArrayList;
12 | import java.util.List;
13 | import java.util.Map;
14 |
15 | import com.laz.filesync.rysnc.checksums.FileChecksums;
16 | import com.laz.filesync.rysnc.util.RsyncException;
17 |
18 | public class FileSyncUtil {
19 | public static int STAERT_FLAG = 0x12345;
20 | public static String NEW_FILE_FLAG = "_new_rsync_file" + STAERT_FLAG;
21 |
22 | public static void getFileCheck(File root, File f, Map map,boolean blockCheck) {
23 | if (f.isDirectory()) {
24 | for (File file : f.listFiles()) {
25 | getFileCheck(root, file, map,blockCheck);
26 | }
27 | } else {
28 | FileChecksums checksums = new FileChecksums(f,blockCheck);
29 | String rootPath = root.getAbsolutePath();
30 | String path = FileUtil.getRelativePath(f, rootPath);
31 | map.put(FileUtil.convertPath(path), checksums);
32 | }
33 | }
34 | public static void getFileCheckSums(File root, File f, Map map) {
35 | getFileCheck(root, f, map, false);
36 | }
37 | public static void getFileCheckSumsAndBlockSums(File root, File f, Map map) {
38 | getFileCheck(root, f, map, true);
39 | }
40 | public static synchronized List getServerTempFolder() {
41 | String tempPath = System.getProperty("java.io.tmpdir");
42 | File tempFolder = new File(tempPath);
43 | List list = new ArrayList();
44 | for (File f:tempFolder.listFiles()) {
45 | if (f.getName().startsWith(Constants.TEMP_PREFIX)) {
46 | LocalDate d = LocalDate.now();
47 | int year = d.getYear();
48 | if (f.getName().contains(year+"") || f.getName().contains((year+1)+"") || f.getName().contains((year-1)+"")) {
49 | list.add(f);
50 | }
51 | }
52 | }
53 | return list;
54 | }
55 | public static synchronized File getServerTempFile(String initName) {
56 | String tempPath = System.getProperty("java.io.tmpdir");
57 | File tempFolder = new File(tempPath);
58 | if (!tempFolder.exists()) {
59 | tempFolder.mkdirs();
60 | }
61 | // 生成本次需同步的差异文件存放目录
62 | String serverTempName = initName.replace(".zip", "_server.zip");
63 | File diffZip = new File(tempFolder + File.separator + serverTempName);
64 | return diffZip;
65 | }
66 |
67 | public static byte[] generateFileDigest(File file) {
68 | FileInputStream fis = null;
69 | try {
70 | MessageDigest sha = MessageDigest.getInstance(com.laz.filesync.rysnc.util.Constants.MD5);
71 | fis = new FileInputStream(file);
72 | byte[] buf = new byte[com.laz.filesync.rysnc.util.Constants.BLOCK_SIZE];
73 | int read = 0;
74 | while ((read = fis.read(buf)) > 0) {
75 | sha.update(buf, 0, read);
76 | }
77 | return sha.digest();
78 | } catch (IOException e) {
79 | throw new RsyncException(e);
80 | } catch (NoSuchAlgorithmException e) {
81 | throw new RsyncException(e);
82 | } finally {
83 | if (fis != null) {
84 | try {
85 | fis.close();
86 | } catch (IOException e) {
87 | throw new RsyncException(e);
88 | }
89 | }
90 | }
91 | }
92 |
93 | /**
94 | * 获取时间字符串
95 | *
96 | * @return
97 | */
98 | public static String getTimeStr() {
99 | LocalDate d = LocalDate.now();
100 | int year = d.getYear();
101 | int month = d.getMonthValue();
102 | int date = d.getDayOfMonth();
103 |
104 | LocalTime time = LocalTime.now();
105 | int hour = time.getHour();
106 | int minute = time.getMinute();
107 | int secord = time.getSecond();
108 | return year + "-" + month + "-" + date + "-" + hour + "-" + minute + "-" + secord;
109 | }
110 |
111 | public static void main(String[] args) {
112 | System.out.println(getTimeStr());
113 | }
114 |
115 | private static ThreadLocal threadLocal = new ThreadLocal() {
116 | protected DecimalFormat initialValue() {
117 | DecimalFormat df = new DecimalFormat("######0.00");
118 | return df;
119 | }
120 | };
121 |
122 | public static String getDoubleValue(Double d) {
123 | DecimalFormat df = threadLocal.get();
124 | return df.format(d);
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/src/main/java/com/laz/filesync/util/FileUtil.java:
--------------------------------------------------------------------------------
1 | package com.laz.filesync.util;
2 |
3 | import java.io.File;
4 | import java.io.IOException;
5 | import java.util.HashMap;
6 | import java.util.Map;
7 | import java.util.concurrent.CountDownLatch;
8 |
9 | public class FileUtil {
10 | public static boolean createFile(File file) throws IOException {
11 | if (file.exists()) {
12 | return true;
13 | }
14 | File folder = file.getParentFile();
15 | if (!folder.exists()) {
16 | folder.mkdirs();
17 | }
18 | return file.createNewFile();
19 | }
20 | public static Map counts= new HashMap();
21 | public static synchronized void countDown(String key) {
22 | CountDownLatch latch = counts.get(key);
23 | if (latch!=null) {
24 | latch.countDown();
25 | } else {
26 | CountDownLatch l = new CountDownLatch(1);
27 | counts.put(key, l);
28 | }
29 | }
30 | public static synchronized CountDownLatch newCount(String key) {
31 | if (counts.get(key)==null) {
32 | CountDownLatch latch = new CountDownLatch(1);
33 | counts.put(key, latch);
34 | return latch;
35 | } else {
36 | //说明先完成的文件上传,不需要等待
37 | return null;
38 | }
39 | }
40 | /**
41 | * linux系统获取的路径是/ window获取的路径是\,为了统一,统一转换成/
42 | * @param path
43 | * @return
44 | */
45 | public static String convertPath(String path) {
46 | if (path !=null) {
47 | path = path.replace("\\", "/");
48 | }
49 | return path;
50 | }
51 |
52 | /**
53 | * 获取相对路径
54 | * @param f 文件
55 | * @param relative 相对路径
56 | * @return 文件绝对路径减去relative后的路径
57 | */
58 | public static String getRelativePath(File f, String relative) {
59 | String fPath = f.getAbsolutePath();
60 | String rp = new File(relative).getAbsolutePath();
61 | int index = fPath.indexOf(rp) + rp.length();
62 | String relativepath = index>fPath.length()-1?"":fPath.substring(index+1);
63 | return relativepath;
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/main/java/com/laz/filesync/util/JsonUtil.java:
--------------------------------------------------------------------------------
1 | package com.laz.filesync.util;
2 |
3 | import com.alibaba.fastjson.JSON;
4 | import com.alibaba.fastjson.TypeReference;
5 |
6 | import io.netty.buffer.ByteBuf;
7 | import io.netty.handler.codec.http.FullHttpRequest;
8 | import io.netty.handler.codec.json.JsonObjectDecoder;
9 | import io.netty.util.CharsetUtil;
10 |
11 | public class JsonUtil {
12 | private JsonUtil() {
13 |
14 | }
15 |
16 | public static String toJson(Object o) {
17 | return JSON.toJSONString(o);
18 | }
19 |
20 | public static T fromJson(FullHttpRequest request, Class c) {
21 | ByteBuf jsonBuf = request.content();
22 | String jsonStr = jsonBuf.toString(CharsetUtil.UTF_8);
23 | return JSON.parseObject(jsonStr, new TypeReference() {});
24 | }
25 |
26 | public static T fromJson(String json, Class c) {
27 | return JSON.parseObject(json, new TypeReference() {});
28 | }
29 |
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/com/laz/filesync/util/PathMap.java:
--------------------------------------------------------------------------------
1 | package com.laz.filesync.util;
2 |
3 | import java.util.HashMap;
4 |
5 | /**
6 | * 路径map,统一路径分隔符识别为/
7 | *
8 | * @author laz
9 | *
10 | */
11 | public class PathMap extends HashMap {
12 | @Override
13 | public V get(Object key) {
14 | if (key instanceof String) {
15 | String path = (String)key;
16 | key = (K) FileUtil.convertPath(path);
17 | }
18 | return super.get(key);
19 | }
20 |
21 | @Override
22 | public V put(K key, V value) {
23 | if (key instanceof String) {
24 | String path = (String)key;
25 | key = (K) FileUtil.convertPath(path);
26 | }
27 | return super.put(key, value);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/com/laz/filesync/util/ZipUtils.java:
--------------------------------------------------------------------------------
1 | package com.laz.filesync.util;
2 |
3 | import java.io.File;
4 | import java.io.FileInputStream;
5 | import java.io.FileOutputStream;
6 | import java.io.IOException;
7 | import java.io.InputStream;
8 | import java.io.OutputStream;
9 | import java.util.ArrayList;
10 | import java.util.Enumeration;
11 | import java.util.List;
12 | import java.util.zip.ZipEntry;
13 | import java.util.zip.ZipFile;
14 | import java.util.zip.ZipOutputStream;
15 |
16 | public class ZipUtils {
17 | private static final int BUFFER_SIZE = 2 * 1024;
18 |
19 | /**
20 | *
21 | * 压缩成ZIP 方法1
22 | *
23 | * @param srcDir 压缩文件夹路径
24 | *
25 | * @param out 压缩文件输出流
26 | *
27 | * @param KeepDirStructure 是否保留原来的目录结构,true:保留目录结构;
28 | *
29 | * false:所有文件跑到压缩包根目录下(注意:不保留目录结构可能会出现同名文件,会压缩失败)
30 | *
31 | * @throws RuntimeException 压缩失败会抛出运行时异常
32 | *
33 | */
34 |
35 | public static void toZip(String srcDir, OutputStream out, boolean KeepDirStructure)
36 |
37 | throws RuntimeException {
38 |
39 | long start = System.currentTimeMillis();
40 |
41 | ZipOutputStream zos = null;
42 |
43 | try {
44 |
45 | zos = new ZipOutputStream(out);
46 |
47 | File sourceFile = new File(srcDir);
48 |
49 | compress(sourceFile, zos, sourceFile.getName(), KeepDirStructure);
50 |
51 | long end = System.currentTimeMillis();
52 |
53 | System.out.println("压缩完成,耗时:" + (end - start) + " ms");
54 |
55 | } catch (Exception e) {
56 |
57 | throw new RuntimeException("zip error from ZipUtils", e);
58 |
59 | } finally {
60 |
61 | if (zos != null) {
62 |
63 | try {
64 |
65 | zos.close();
66 |
67 | } catch (IOException e) {
68 |
69 | e.printStackTrace();
70 |
71 | }
72 |
73 | }
74 |
75 | }
76 |
77 | }
78 |
79 | /**
80 | *
81 | * 压缩成ZIP 方法2
82 | *
83 | * @param srcFiles 需要压缩的文件列表
84 | *
85 | * @param out 压缩文件输出流
86 | *
87 | * @throws RuntimeException 压缩失败会抛出运行时异常
88 | *
89 | */
90 |
91 | public static void toZip(List srcFiles, OutputStream out) throws RuntimeException {
92 |
93 | long start = System.currentTimeMillis();
94 |
95 | ZipOutputStream zos = null;
96 |
97 | try {
98 |
99 | zos = new ZipOutputStream(out);
100 |
101 | for (File srcFile : srcFiles) {
102 |
103 | byte[] buf = new byte[BUFFER_SIZE];
104 |
105 | zos.putNextEntry(new ZipEntry(srcFile.getName()));
106 |
107 | int len;
108 |
109 | FileInputStream in = new FileInputStream(srcFile);
110 |
111 | while ((len = in.read(buf)) != -1) {
112 |
113 | zos.write(buf, 0, len);
114 |
115 | }
116 |
117 | zos.closeEntry();
118 |
119 | in.close();
120 |
121 | }
122 |
123 | long end = System.currentTimeMillis();
124 |
125 | System.out.println("压缩完成,耗时:" + (end - start) + " ms");
126 |
127 | } catch (Exception e) {
128 |
129 | throw new RuntimeException("zip error from ZipUtils", e);
130 |
131 | } finally {
132 |
133 | if (zos != null) {
134 |
135 | try {
136 |
137 | zos.close();
138 |
139 | } catch (IOException e) {
140 |
141 | e.printStackTrace();
142 |
143 | }
144 |
145 | }
146 |
147 | }
148 |
149 | }
150 |
151 | /**
152 | *
153 | * 递归压缩方法
154 | *
155 | * @param sourceFile 源文件
156 | *
157 | * @param zos zip输出流
158 | *
159 | * @param name 压缩后的名称
160 | *
161 | * @param KeepDirStructure 是否保留原来的目录结构,true:保留目录结构;
162 | *
163 | * false:所有文件跑到压缩包根目录下(注意:不保留目录结构可能会出现同名文件,会压缩失败)
164 | *
165 | * @throws Exception
166 | *
167 | */
168 |
169 | private static void compress(File sourceFile, ZipOutputStream zos, String name,
170 |
171 | boolean KeepDirStructure) throws Exception {
172 |
173 | byte[] buf = new byte[BUFFER_SIZE];
174 |
175 | if (sourceFile.isFile()) {
176 |
177 | // 向zip输出流中添加一个zip实体,构造器中name为zip实体的文件的名字
178 |
179 | zos.putNextEntry(new ZipEntry(name));
180 |
181 | // copy文件到zip输出流中
182 |
183 | int len;
184 |
185 | FileInputStream in = new FileInputStream(sourceFile);
186 |
187 | while ((len = in.read(buf)) != -1) {
188 |
189 | zos.write(buf, 0, len);
190 |
191 | }
192 |
193 | // Complete the entry
194 |
195 | zos.closeEntry();
196 |
197 | in.close();
198 |
199 | } else {
200 |
201 | File[] listFiles = sourceFile.listFiles();
202 |
203 | if (listFiles == null || listFiles.length == 0) {
204 |
205 | // 需要保留原来的文件结构时,需要对空文件夹进行处理
206 |
207 | if (KeepDirStructure) {
208 |
209 | // 空文件夹的处理
210 |
211 | zos.putNextEntry(new ZipEntry(name + "/"));
212 |
213 | // 没有文件,不需要文件的copy
214 |
215 | zos.closeEntry();
216 |
217 | }
218 |
219 | } else {
220 |
221 | for (File file : listFiles) {
222 |
223 | // 判断是否需要保留原来的文件结构
224 |
225 | if (KeepDirStructure) {
226 |
227 | // 注意:file.getName()前面需要带上父文件夹的名字加一斜杠,
228 |
229 | // 不然最后压缩包中就不能保留原来的文件结构,即:所有文件都跑到压缩包根目录下了
230 |
231 | compress(file, zos, name + "/" + file.getName(), KeepDirStructure);
232 |
233 | } else {
234 |
235 | compress(file, zos, file.getName(), KeepDirStructure);
236 |
237 | }
238 |
239 | }
240 |
241 | }
242 |
243 | }
244 |
245 | }
246 |
247 | /**
248 | *
249 | * zip解压
250 | *
251 | * @param srcFile zip源文件
252 | *
253 | * @param destDirPath 解压后的目标文件夹
254 | *
255 | * @throws RuntimeException 解压失败会抛出运行时异常
256 | *
257 | */
258 | public static void unzipFile(File srcFile, String destDirPath) {
259 | // 判断源文件是否存在
260 | if (!srcFile.exists()) {
261 | throw new RuntimeException(srcFile.getPath() + "所指文件不存在");
262 | }
263 | // 开始解压
264 | ZipFile zipFile = null;
265 | try {
266 | zipFile = new ZipFile(srcFile);
267 | Enumeration> entries = zipFile.entries();
268 | while (entries.hasMoreElements()) {
269 | ZipEntry entry = (ZipEntry) entries.nextElement();
270 | // 如果是文件夹,就创建个文件夹
271 | if (entry.isDirectory()) {
272 | String dirPath = destDirPath + File.separator + entry.getName();
273 | File dir = new File(dirPath);
274 | dir.mkdirs();
275 | } else {
276 | // 如果是文件,就先创建一个文件,然后用io流把内容copy过去
277 | File targetFile = new File(destDirPath + File.separator + entry.getName());
278 | // 保证这个文件的父文件夹必须要存在
279 | if (!targetFile.getParentFile().exists()) {
280 | targetFile.getParentFile().mkdirs();
281 | }
282 | targetFile.createNewFile();
283 | // 将压缩文件内容写入到这个文件中
284 | InputStream is = zipFile.getInputStream(entry);
285 | FileOutputStream fos = new FileOutputStream(targetFile);
286 | int len;
287 | byte[] buf = new byte[BUFFER_SIZE];
288 | while ((len = is.read(buf)) != -1) {
289 | fos.write(buf, 0, len);
290 | }
291 | // 关流顺序,先打开的后关闭
292 | fos.close();
293 | is.close();
294 | }
295 | }
296 |
297 | } catch (Exception e) {
298 |
299 | throw new RuntimeException("unzip error from ZipUtils", e);
300 |
301 | } finally {
302 |
303 | if (zipFile != null) {
304 |
305 | try {
306 |
307 | zipFile.close();
308 |
309 | } catch (IOException e) {
310 |
311 | e.printStackTrace();
312 |
313 | }
314 |
315 | }
316 |
317 | }
318 | }
319 |
320 | private static void BufferedInputStream(FileInputStream fileInputStream) {
321 | // TODO Auto-generated method stub
322 |
323 | }
324 |
325 | public static void main(String[] args) throws Exception {
326 |
327 | /** 测试压缩方法1 */
328 |
329 | FileOutputStream fos1 = new FileOutputStream(new File("c:/mytest01.zip"));
330 |
331 | ZipUtils.toZip("D:/log", fos1, true);
332 |
333 | /** 测试压缩方法2 */
334 |
335 | List fileList = new ArrayList<>();
336 |
337 | fileList.add(new File("D:/Java/jdk1.7.0_45_64bit/bin/jar.exe"));
338 |
339 | fileList.add(new File("D:/Java/jdk1.7.0_45_64bit/bin/java.exe"));
340 |
341 | FileOutputStream fos2 = new FileOutputStream(new File("c:/mytest02.zip"));
342 |
343 | ZipUtils.toZip(fileList, fos2);
344 |
345 | }
346 | }
347 |
--------------------------------------------------------------------------------
/src/main/resources/log4j.properties:
--------------------------------------------------------------------------------
1 | log4j.rootLogger = info,stdout,D,E
2 |
3 | ### 输出信息到控制抬 ###
4 | log4j.appender.stdout = org.apache.log4j.ConsoleAppender
5 | log4j.appender.stdout.Target = System.out
6 | log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
7 | log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l %m%n
8 |
9 | ### 输出DEBUG 级别以上的日志到=logs/log.log ###
10 | ### 按日期org.apache.log4j.DailyRollingFileAppender
11 | ### 按文件大小org.apache.log4j.DailyRollingFileAppender
12 | log4j.appender.D =org.apache.log4j.DailyRollingFileAppender
13 | log4j.appender.D.File = logs/log.log
14 | ### log4j.appender.D.MaxFileSize=1KB
15 | log4j.appender.D.Append = true
16 | log4j.appender.D.Threshold = DEBUG
17 | log4j.appender.D.layout = org.apache.log4j.PatternLayout
18 | log4j.appender.D.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
19 |
20 | ### 输出ERROR 级别以上的日志到=logs/error.log ###
21 | log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
22 | log4j.appender.E.File =logs/error.log
23 | ### log4j.appender.E.MaxFileSize=1KB
24 | log4j.appender.E.Append = true
25 | log4j.appender.E.Threshold = ERROR
26 | log4j.appender.E.layout = org.apache.log4j.PatternLayout
27 | log4j.appender.E.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
--------------------------------------------------------------------------------
/src/main/resources/small_client.txt:
--------------------------------------------------------------------------------
1 | 0123++++.0456789ab0cdef++0123*cdef
--------------------------------------------------------------------------------
/src/main/resources/small_server.txt:
--------------------------------------------------------------------------------
1 | 0123++++456789abcdef
--------------------------------------------------------------------------------
/src/test/java/com/laz/filesync/test/TestSync.java:
--------------------------------------------------------------------------------
1 | package com.laz.filesync.test;
2 |
3 | import java.io.File;
4 | import java.util.ArrayList;
5 | import java.util.List;
6 |
7 | import org.junit.Test;
8 |
9 | import com.laz.filesync.rysnc.checksums.DiffCheckItem;
10 | import com.laz.filesync.rysnc.checksums.FileChecksums;
11 | import com.laz.filesync.rysnc.checksums.RollingChecksum;
12 | import com.laz.filesync.rysnc.util.Constants;
13 | import com.laz.filesync.rysnc.util.QuickMD5;
14 | import com.laz.filesync.rysnc.util.RsyncFileUtils;
15 |
16 | public class TestSync {
17 | @Test
18 | public void testCheckSum() throws Exception {
19 | File srcFile = new File("C:\\Users\\lz578\\Desktop\\worldwind.jar");
20 | File updateFile = new File("D:\\server\\apache-tomcat-8.0.36-2\\webapps\\SMS\\com\\sunsheen\\jfids\\demo\\worldwind\\worldwind.jar");
21 | System.out.println(QuickMD5.getFileMD5Buffer(srcFile));
22 | System.out.println(RsyncFileUtils.checkFileSame(updateFile, srcFile));
23 | }
24 | @Test
25 | public void testRolling() throws Exception {
26 |
27 | File srcFile = new File("C:\\Users\\lz578\\Desktop\\worldwind.jar");
28 | File updateFile = new File("D:\\server\\apache-tomcat-8.0.36-2\\webapps\\SMS\\com\\sunsheen\\jfids\\demo\\worldwind\\worldwind.jar");
29 | File tmp = new File("D:\\filesync\\server\\1.txt_tmp");
30 | File newFile = new File("D:\\filesync\\server\\1.txt_new");
31 | long t1 = System.currentTimeMillis();
32 | if (!tmp.exists()) {
33 | tmp.createNewFile();
34 | }
35 | List dciList = roll(srcFile, updateFile);
36 |
37 | long t2 = System.currentTimeMillis();
38 |
39 | System.out.println("滚动计算: spend time :" + (long) (t2 - t1) + "ms");
40 | RsyncFileUtils.createRsyncFile(dciList, tmp, Constants.BLOCK_SIZE);
41 |
42 | System.out.println("实际需要传输的大小 :" + tmp.length() + " byte ");
43 |
44 | long t3 = System.currentTimeMillis();
45 |
46 | System.out.println("生成临时文件,耗时 :" + (long) (t3 - t2) + "ms");
47 |
48 | RsyncFileUtils.combineRsyncFile(srcFile, newFile, tmp);
49 |
50 | long t4 = System.currentTimeMillis();
51 |
52 | System.out.println("合并文件 耗时:" + (long) (t4 - t3) + "ms");
53 |
54 | System.out.println("all spend time :" + (long) (t4 - t1) + "ms");
55 |
56 | System.out.println(RsyncFileUtils.checkFileSame(updateFile, newFile));
57 | }
58 |
59 | private List roll(File srcFile, File updateFile) {
60 |
61 | FileChecksums fc = new FileChecksums(srcFile);
62 |
63 | List diffList = new ArrayList();
64 |
65 | RollingChecksum rck = new RollingChecksum(fc, updateFile, diffList);
66 |
67 | rck.rolling();
68 |
69 | return diffList;
70 | }
71 |
72 | }
73 |
--------------------------------------------------------------------------------
/src/test/resources/diff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lazlaz/filesync/06d860bb43ddde04041858ce4132caa715d31de3/src/test/resources/diff
--------------------------------------------------------------------------------
/src/test/resources/lorem:
--------------------------------------------------------------------------------
1 |
2 |
! " # $ % &