]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.util/src/org/argeo/util/security/ChecksumFactory.java
b57db2c986ff1e80d6fab154d69a2a4a94b01cbc
[lgpl/argeo-commons.git] / org.argeo.util / src / org / argeo / util / security / ChecksumFactory.java
1 package org.argeo.util.security;
2
3 import static javax.xml.bind.DatatypeConverter.printBase64Binary;
4
5 import java.io.IOException;
6 import java.math.BigInteger;
7 import java.nio.MappedByteBuffer;
8 import java.nio.channels.FileChannel;
9 import java.nio.file.FileVisitResult;
10 import java.nio.file.Files;
11 import java.nio.file.Path;
12 import java.nio.file.Paths;
13 import java.nio.file.SimpleFileVisitor;
14 import java.nio.file.attribute.BasicFileAttributes;
15 import java.security.MessageDigest;
16 import java.util.zip.Checksum;
17
18 import org.argeo.util.internal.UtilsException;
19
20 /** Allows to fine tune how files are read. */
21 public class ChecksumFactory {
22 private int regionSize = 10 * 1024 * 1024;
23
24 public byte[] digest(Path path, final String algo) {
25 try {
26 final MessageDigest md = MessageDigest.getInstance(algo);
27 if (Files.isDirectory(path)) {
28 long begin = System.currentTimeMillis();
29 Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
30
31 @Override
32 public FileVisitResult visitFile(Path file,
33 BasicFileAttributes attrs) throws IOException {
34 if (!Files.isDirectory(file)) {
35 byte[] digest = digest(file, algo);
36 md.update(digest);
37 }
38 return FileVisitResult.CONTINUE;
39 }
40
41 });
42 byte[] digest = md.digest();
43 long duration = System.currentTimeMillis() - begin;
44 System.out.println(printBase64Binary(digest) + " " + path
45 + " (" + duration / 1000 + "s)");
46 return digest;
47 } else {
48 long begin = System.nanoTime();
49 long length = -1;
50 try (FileChannel channel = (FileChannel) Files
51 .newByteChannel(path);) {
52 length = channel.size();
53 long cursor = 0;
54 while (cursor < length) {
55 long effectiveSize = Math.min(regionSize, length
56 - cursor);
57 MappedByteBuffer mb = channel.map(
58 FileChannel.MapMode.READ_ONLY, cursor,
59 effectiveSize);
60 // md.update(mb);
61 byte[] buffer = new byte[1024];
62 while (mb.hasRemaining()){
63 mb.get(buffer);
64 md.update(buffer);
65 }
66
67 // sub digest
68 // mb.flip();
69 // MessageDigest subMd =
70 // MessageDigest.getInstance(algo);
71 // subMd.update(mb);
72 // byte[] subDigest = subMd.digest();
73 // System.out.println(" -> " + cursor);
74 // System.out.println(StreamUtils.encodeHexString(subDigest));
75 // System.out.println(new BigInteger(1,
76 // subDigest).toString(16));
77 // System.out.println(new BigInteger(1, subDigest)
78 // .toString(Character.MAX_RADIX));
79 // System.out.println(printBase64Binary(subDigest));
80
81 cursor = cursor + regionSize;
82 }
83 byte[] digest = md.digest();
84 long duration = System.nanoTime() - begin;
85 System.out.println(printBase64Binary(digest) + " "
86 + path.getFileName() + " (" + duration / 1000000
87 + "ms, " + (length / 1024) + "kB, "
88 + (length / (duration / 1000000)) * 1000
89 / (1024 * 1024) + " MB/s)");
90 return digest;
91 }
92 }
93 } catch (Exception e) {
94 throw new UtilsException("Cannot digest " + path, e);
95 }
96 }
97
98 /** Whether the file should be mapped. */
99 protected boolean mapFile(FileChannel fileChannel) throws IOException {
100 long size = fileChannel.size();
101 if (size > (regionSize / 10))
102 return true;
103 return false;
104 }
105
106 public long checksum(Path path, Checksum crc) {
107 final int bufferSize = 2 * 1024 * 1024;
108 long begin = System.currentTimeMillis();
109 try (FileChannel channel = (FileChannel) Files.newByteChannel(path);) {
110 byte[] bytes = new byte[bufferSize];
111 long length = channel.size();
112 long cursor = 0;
113 while (cursor < length) {
114 long effectiveSize = Math.min(regionSize, length - cursor);
115 MappedByteBuffer mb = channel.map(
116 FileChannel.MapMode.READ_ONLY, cursor, effectiveSize);
117 int nGet;
118 while (mb.hasRemaining()) {
119 nGet = Math.min(mb.remaining(), bufferSize);
120 mb.get(bytes, 0, nGet);
121 crc.update(bytes, 0, nGet);
122 }
123 cursor = cursor + regionSize;
124 }
125 return crc.getValue();
126 } catch (Exception e) {
127 throw new UtilsException("Cannot checksum " + path, e);
128 } finally {
129 long duration = System.currentTimeMillis() - begin;
130 System.out.println(duration / 1000 + "s");
131 }
132 }
133
134 public static void main(String... args) {
135 ChecksumFactory cf = new ChecksumFactory();
136 // Path path =
137 // Paths.get("/home/mbaudier/apache-maven-3.2.3-bin.tar.gz");
138 Path path;
139 if (args.length > 0) {
140 path = Paths.get(args[0]);
141 } else {
142 path = Paths
143 .get("/home/mbaudier/Downloads/torrents/CentOS-7-x86_64-DVD-1503-01/"
144 + "CentOS-7-x86_64-DVD-1503-01.iso");
145 }
146 // long adler = cf.checksum(path, new Adler32());
147 // System.out.format("Adler=%d%n", adler);
148 // long crc = cf.checksum(path, new CRC32());
149 // System.out.format("CRC=%d%n", crc);
150 String algo = "SHA1";
151 byte[] digest = cf.digest(path, algo);
152 System.out.println(algo + " " + printBase64Binary(digest));
153 System.out.println(algo + " " + new BigInteger(1, digest).toString(16));
154 // String sha1 = printBase64Binary(cf.digest(path, "SHA1"));
155 // System.out.format("SHA1=%s%n", sha1);
156 }
157 }