1 package org
.argeo
.cms
.security
;
3 import java
.io
.IOException
;
4 import java
.math
.BigInteger
;
5 import java
.nio
.MappedByteBuffer
;
6 import java
.nio
.channels
.FileChannel
;
7 import java
.nio
.file
.FileVisitResult
;
8 import java
.nio
.file
.Files
;
9 import java
.nio
.file
.Path
;
10 import java
.nio
.file
.Paths
;
11 import java
.nio
.file
.SimpleFileVisitor
;
12 import java
.nio
.file
.attribute
.BasicFileAttributes
;
13 import java
.security
.MessageDigest
;
14 import java
.util
.Base64
;
15 import java
.util
.zip
.Checksum
;
17 import org
.argeo
.cms
.CmsException
;
19 /** Allows to fine tune how files are read. */
20 public class ChecksumFactory
{
21 private int regionSize
= 10 * 1024 * 1024;
23 public byte[] digest(Path path
, final String algo
) {
25 final MessageDigest md
= MessageDigest
.getInstance(algo
);
26 if (Files
.isDirectory(path
)) {
27 long begin
= System
.currentTimeMillis();
28 Files
.walkFileTree(path
, new SimpleFileVisitor
<Path
>() {
31 public FileVisitResult
visitFile(Path file
, BasicFileAttributes attrs
) throws IOException
{
32 if (!Files
.isDirectory(file
)) {
33 byte[] digest
= digest(file
, algo
);
36 return FileVisitResult
.CONTINUE
;
40 byte[] digest
= md
.digest();
41 long duration
= System
.currentTimeMillis() - begin
;
42 System
.out
.println(printBase64Binary(digest
) + " " + path
+ " (" + duration
/ 1000 + "s)");
45 long begin
= System
.nanoTime();
47 try (FileChannel channel
= (FileChannel
) Files
.newByteChannel(path
);) {
48 length
= channel
.size();
50 while (cursor
< length
) {
51 long effectiveSize
= Math
.min(regionSize
, length
- cursor
);
52 MappedByteBuffer mb
= channel
.map(FileChannel
.MapMode
.READ_ONLY
, cursor
, effectiveSize
);
54 byte[] buffer
= new byte[1024];
55 while (mb
.hasRemaining()) {
62 // MessageDigest subMd =
63 // MessageDigest.getInstance(algo);
65 // byte[] subDigest = subMd.digest();
66 // System.out.println(" -> " + cursor);
67 // System.out.println(IOUtils.encodeHexString(subDigest));
68 // System.out.println(new BigInteger(1,
69 // subDigest).toString(16));
70 // System.out.println(new BigInteger(1, subDigest)
71 // .toString(Character.MAX_RADIX));
72 // System.out.println(printBase64Binary(subDigest));
74 cursor
= cursor
+ regionSize
;
76 byte[] digest
= md
.digest();
77 long duration
= System
.nanoTime() - begin
;
78 System
.out
.println(printBase64Binary(digest
) + " " + path
.getFileName() + " (" + duration
/ 1000000
79 + "ms, " + (length
/ 1024) + "kB, " + (length
/ (duration
/ 1000000)) * 1000 / (1024 * 1024)
84 } catch (Exception e
) {
85 throw new CmsException("Cannot digest " + path
, e
);
89 /** Whether the file should be mapped. */
90 protected boolean mapFile(FileChannel fileChannel
) throws IOException
{
91 long size
= fileChannel
.size();
92 if (size
> (regionSize
/ 10))
97 public long checksum(Path path
, Checksum crc
) {
98 final int bufferSize
= 2 * 1024 * 1024;
99 long begin
= System
.currentTimeMillis();
100 try (FileChannel channel
= (FileChannel
) Files
.newByteChannel(path
);) {
101 byte[] bytes
= new byte[bufferSize
];
102 long length
= channel
.size();
104 while (cursor
< length
) {
105 long effectiveSize
= Math
.min(regionSize
, length
- cursor
);
106 MappedByteBuffer mb
= channel
.map(FileChannel
.MapMode
.READ_ONLY
, cursor
, effectiveSize
);
108 while (mb
.hasRemaining()) {
109 nGet
= Math
.min(mb
.remaining(), bufferSize
);
110 mb
.get(bytes
, 0, nGet
);
111 crc
.update(bytes
, 0, nGet
);
113 cursor
= cursor
+ regionSize
;
115 return crc
.getValue();
116 } catch (Exception e
) {
117 throw new CmsException("Cannot checksum " + path
, e
);
119 long duration
= System
.currentTimeMillis() - begin
;
120 System
.out
.println(duration
/ 1000 + "s");
124 public static void main(String
... args
) {
125 ChecksumFactory cf
= new ChecksumFactory();
127 // Paths.get("/home/mbaudier/apache-maven-3.2.3-bin.tar.gz");
129 if (args
.length
> 0) {
130 path
= Paths
.get(args
[0]);
132 path
= Paths
.get("/home/mbaudier/Downloads/torrents/CentOS-7-x86_64-DVD-1503-01/"
133 + "CentOS-7-x86_64-DVD-1503-01.iso");
135 // long adler = cf.checksum(path, new Adler32());
136 // System.out.format("Adler=%d%n", adler);
137 // long crc = cf.checksum(path, new CRC32());
138 // System.out.format("CRC=%d%n", crc);
139 String algo
= "SHA1";
140 byte[] digest
= cf
.digest(path
, algo
);
141 System
.out
.println(algo
+ " " + printBase64Binary(digest
));
142 System
.out
.println(algo
+ " " + new BigInteger(1, digest
).toString(16));
143 // String sha1 = printBase64Binary(cf.digest(path, "SHA1"));
144 // System.out.format("SHA1=%s%n", sha1);
147 private static String
printBase64Binary(byte[] arr
) {
148 return Base64
.getEncoder().encodeToString(arr
);