11package main ;
22
3- import java .io .BufferedInputStream ;
4- import java .io .BufferedOutputStream ;
53import java .io .BufferedReader ;
64import java .io .InputStream ;
75import java .io .InputStreamReader ;
@@ -47,8 +45,7 @@ public class Main
4745 private static final MessageDigest OUT_DIGEST = DIGEST_SUPPLIER .get ();
4846 private static final MessageDigest IN_DIGEST = DIGEST_SUPPLIER .get ();
4947 static final short KB = 1024 ;
50- static final int MB = KB * 1024 ;
51- static final int GB = MB * 1024 ;
48+ static final int MB = KB * 1024 , GB = MB * 1024 , MAX_BUFFER = MB * 20 ;
5249 static
5350 {
5451 final OptionGroup group = new OptionGroup ();
@@ -63,6 +60,7 @@ public class Main
6360 public static void main (String [] args )
6461 {
6562 final BufferedReader reader = new BufferedReader (new InputStreamReader (System .in ));
63+ final long startTime ;
6664 try
6765 {
6866 final CommandLine commandLine = PARSER .parse (OPTIONS , args );
@@ -79,6 +77,7 @@ public static void main(String[] args)
7977 if (Boolean .parseBoolean (reader .readLine ()))
8078 {
8179 System .out .println ("Beginning operation..." );
80+ startTime = System .currentTimeMillis ();
8281 final ObjectInputStream objectInputStream = new ObjectInputStream (Files .newInputStream (inputPath ));
8382 final String outputFilename = (String ) objectInputStream .readObject ();
8483 final long totalSize = objectInputStream .readLong (), chunkSize = objectInputStream .readLong ();
@@ -89,12 +88,12 @@ public static void main(String[] args)
8988 System .out .println ("Thus there should be " + calculatedChunks + " chunks." );
9089 if (calculatedChunks != listedChunks )
9190 System .err .println ("WARNING! Expected " + calculatedChunks + " chunks but got " + listedChunks + " listed chunks!" );
92- try (final OutputStream outputStream = new DigestOutputStream (new BufferedOutputStream ( Files .newOutputStream (Paths .get (outputPath .toString (), outputFilename ) )), OUT_DIGEST ))
91+ try (final OutputStream outputStream = new DigestOutputStream (Files .newOutputStream (Paths .get (outputPath .toString (), outputFilename )), OUT_DIGEST ))
9392 {
9493 for (int i = 1 ; i < listedChunks + 1 ; i ++)
9594 {
9695 System .out .println ("Reading chunk #" + i + '/' + listedChunks + "..." );
97- final Path currentPath = Paths .get (inputPath .getParent ().toString (), outputFilename + '.' + ( i - 1 ) + ".part" );
96+ final Path currentPath = Paths .get (inputPath .getParent ().toString (), outputFilename + '.' + i + ".part" );
9897 final long currentChunkSize = Files .size (currentPath ), desiredSize = i < listedChunks + 1 ? chunkSize : totalSize - chunkSize * i ;
9998 if (desiredSize != chunkSize )
10099 {
@@ -103,10 +102,17 @@ public static void main(String[] args)
103102 if (!Boolean .parseBoolean (reader .readLine ()))
104103 System .exit (0 );
105104 }
106- try (final InputStream inputStream = new DigestInputStream (new BufferedInputStream ( Files .newInputStream (currentPath ) ), IN_DIGEST ))
105+ try (final InputStream inputStream = new DigestInputStream (Files .newInputStream (currentPath ), IN_DIGEST ))
107106 {
108- while (inputStream .available () > 0 )
109- outputStream .write (inputStream .read ());
107+ long size = Files .size (currentPath );
108+ while (size > 0 )
109+ {
110+ final int bufferSize = (int ) Math .min (MAX_BUFFER , size );
111+ final byte [] buffer = new byte [bufferSize ];
112+ inputStream .read (buffer );
113+ outputStream .write (buffer );
114+ size -= bufferSize ;
115+ }
110116 outputStream .flush ();
111117 }
112118 final String realChecksum = bytesToHex (IN_DIGEST .digest ()), savedChecksum = (String ) objectInputStream .readObject ();
@@ -124,6 +130,7 @@ public static void main(String[] args)
124130 System .err .println ("WARNING! Final file checksum does not match! Expected " + expectedChecksum + " but got " + realChecksum + '!' );
125131 }
126132 System .out .println ("Done!" );
133+ System .out .println (timeFromMillis (System .currentTimeMillis () - startTime ));
127134 }
128135 else
129136 cancel ();
@@ -142,36 +149,45 @@ public static void main(String[] args)
142149 if (Boolean .parseBoolean (reader .readLine ()))
143150 {
144151 System .out .println ("Beginning operation..." );
152+ startTime = System .currentTimeMillis ();
145153 final ObjectOutputStream objectOutputStream = new ObjectOutputStream (Files .newOutputStream (Paths .get (outputPath .toString (), inputPath .getFileName () + ".sum" )));
146154 long processed = 0 ;
147155 objectOutputStream .writeObject (inputPath .getFileName ().toString ());
148156 objectOutputStream .writeLong (totalSize );
149157 objectOutputStream .writeLong (chunkSize );
150158 objectOutputStream .writeInt (totalChunks );
151- try (final InputStream inputStream = new DigestInputStream (new BufferedInputStream ( Files .newInputStream (inputPath ) ), IN_DIGEST ))
159+ try (final InputStream inputStream = new DigestInputStream (Files .newInputStream (inputPath ), IN_DIGEST ))
152160 {
153- int chunkIndex = 0 ;
161+ int chunkIndex = 1 ;
154162 while (inputStream .available () > 0 )
155163 {
156164 final Path currentChunkPath = Paths .get (outputPath .toString (), inputPath .getFileName ().toString () + '.' + chunkIndex + ".part" );
157- try (final OutputStream outputStream = new DigestOutputStream (new BufferedOutputStream ( Files .newOutputStream (currentChunkPath ) ), OUT_DIGEST ))
165+ try (final OutputStream outputStream = new DigestOutputStream (Files .newOutputStream (currentChunkPath ), OUT_DIGEST ))
158166 {
159167 final long maxAlloc = Math .min (chunkSize , totalSize - processed );
160- for (long i = 0 ; i < maxAlloc ; i ++)
161- outputStream .write (inputStream .read ());
168+ long written = 0 ;
169+ while (written < maxAlloc )
170+ {
171+ final int bufferSize = (int ) Math .min (MAX_BUFFER , maxAlloc );
172+ final byte [] buffer = new byte [bufferSize ];
173+ inputStream .read (buffer );
174+ outputStream .write (buffer );
175+ written += bufferSize ;
176+ }
162177
163178 outputStream .flush ();
164179 processed += maxAlloc ;
165180 objectOutputStream .writeObject (bytesToHex (IN_DIGEST .digest ()));
166181 objectOutputStream .flush ();
167- System .out .println (" Wrote: " + currentChunkPath + " at " + maxAlloc + " bytes." );
182+ System .out .println (String . format ( "(#%s/%s) Wrote: %s at %s bytes." , chunkIndex , totalChunks , currentChunkPath , maxAlloc ) );
168183 }
169184 chunkIndex ++;
170185 }
171186 objectOutputStream .writeObject (bytesToHex (OUT_DIGEST .digest ()));
172187 objectOutputStream .flush ();
173188 }
174189 System .out .println ("Done!" );
190+ System .out .println (timeFromMillis (System .currentTimeMillis () - startTime ));
175191 }
176192 else
177193 cancel ();
@@ -216,6 +232,26 @@ private static int magnitudeFromName(String name)
216232 }
217233 }
218234
235+ private static String timeFromMillis (long timeIn )
236+ {
237+ final StringBuilder builder = new StringBuilder ("Operation took: " );
238+ final long secondMillis = 1000 , minuteMillis = 60 * secondMillis , hourMillis = 60 * minuteMillis ;
239+ long time = timeIn ;
240+ if (time >= hourMillis )
241+ {
242+ builder .append (Math .floorDiv (time , hourMillis )).append (" hour(s) " );
243+ time %= hourMillis ;
244+ }
245+ if (time >= minuteMillis )
246+ {
247+ builder .append (Math .floorDiv (time , minuteMillis )).append (" minute(s) " );
248+ time %= minuteMillis ;
249+ }
250+ if (time >= secondMillis )
251+ builder .append ((double ) time / secondMillis ).append (" second(s)" );
252+ return builder .append ('.' ).toString ();
253+ }
254+
219255 private static void cancel ()
220256 {
221257 System .out .println ("Cancelling execution..." );
0 commit comments