22using System ;
33using System . Collections . Generic ;
44using System . IO ;
5+ using System . IO . Compression ;
56using System . Linq ;
67using System . Security . Cryptography ;
78using System . Text ;
@@ -370,9 +371,8 @@ public void Extract(string outputFilePath, NefsProgressInfo p)
370371 public void Inject ( string inputFilePath , NefsProgressInfo p )
371372 {
372373 float taskWeightPrep = 0.05f ;
373- float taskWeightSplit = 0.15f ;
374- float taskWeightCompress = 0.6f ;
375- float taskWeightJoin = 0.15f ;
374+ float taskWeightCompress = 0.85f ;
375+ float taskWeightUpdateMetadata = 0.05f ;
376376 float taskWeightCleanup = 0.05f ;
377377
378378 p . BeginTask ( taskWeightPrep , "Preparing file injection..." ) ;
@@ -390,156 +390,94 @@ public void Inject(string inputFilePath, NefsProgressInfo p)
390390 /* Temp working directory */
391391 var workDir = Path . Combine ( FilePathHelper . TempDirectory , _archive . FilePathHash , FilePathInArchiveHash ) ;
392392
393- /* Dir for uncompressed chunks */
394- var u_chunks_dir = Path . Combine ( workDir , "u_chunks" ) ;
395-
396- /* Dir for compressed chunks */
397- var c_chunks_dir = Path . Combine ( workDir , "c_chunks" ) ;
398-
399393 /* Delete the working directory if exists and recreate it */
400394 if ( Directory . Exists ( workDir ) )
401395 {
402396 Directory . Delete ( workDir , true ) ;
403397 }
404398
405399 Directory . CreateDirectory ( workDir ) ;
406- Directory . CreateDirectory ( u_chunks_dir ) ;
407- Directory . CreateDirectory ( c_chunks_dir ) ;
408400
409401 p . EndTask ( ) ;
410402
411403 /*
412- * SPLIT INPUT FILE INTO CHUNKS
404+ * SPLIT INPUT FILE INTO CHUNKS AND COMPRESS THEM
413405 */
414- p . BeginTask ( taskWeightSplit , "Splitting input file into chunks ..." ) ;
406+ p . BeginTask ( taskWeightCompress , "Compressing file..." ) ;
415407
408+ int compressedSizeDiff = 0 ;
409+ int currentChunk = 0 ;
410+ var destFilePath = Path . Combine ( workDir , "inject.dat" ) ;
416411 int numChunks = 0 ;
417- int fileNum = 0 ;
412+ int numChunksDiff = 0 ;
413+ int oldNumChunks = ChunkSizes . Count ( ) ;
418414
419415 /* Open the input file */
420416 using ( var inputFile = new FileStream ( inputFilePath , FileMode . Open ) )
421417 {
418+ inputFile . Seek ( 0 , SeekOrigin . Begin ) ;
419+
422420 /* Determine how many chunks to split file into */
423421 numChunks = ( int ) Math . Ceiling ( inputFile . Length / ( double ) CHUNK_SIZE ) ;
424422 _extractedSize = ( UInt32 ) inputFile . Length ;
425423
426- /* Read in each chunk and write to the uncompressed dir */
427- var temp = new byte [ CHUNK_SIZE ] ;
424+ /* Clear out chunk sizes list so we can rebuild it */
425+ ChunkSizes . Clear ( ) ;
426+
428427 int lastBytesRead = 0 ;
429428 int totalBytesRead = 0 ;
429+ int lastChunkSize = 0 ;
430+ int totalChunkSize = 0 ;
430431
431- do
432+ using ( var outputFile = new FileStream ( destFilePath , FileMode . Create ) )
432433 {
433- p . BeginTask ( 1.0f / ( float ) numChunks , String . Format ( "Creating chunk {0}/{1}..." , fileNum + 1 , numChunks ) ) ;
434+ do
435+ {
436+ p . BeginTask ( 1.0f / ( float ) numChunks , String . Format ( "Compressing chunk {0}/{1}..." , currentChunk + 1 , numChunks ) ) ;
434437
435- /* Read the chunk from input file */
436- inputFile . Seek ( totalBytesRead , SeekOrigin . Begin ) ;
437- lastBytesRead = inputFile . Read ( temp , 0 , CHUNK_SIZE ) ;
438+ /* Compress this chunk and write it to the output file */
439+ lastBytesRead = DeflateHelper . DeflateToFile ( inputFile , CHUNK_SIZE , outputFile , out lastChunkSize ) ;
438440
439- /* Write chunk to its own output file. It is important
440- * that chunks are named alphabetically so that later
441- * they are read in order. */
442- var uChunkFilePath = Path . Combine ( u_chunks_dir , "u_" + fileNum . ToString ( "00000000" ) + ".dat" ) ;
441+ totalBytesRead += lastBytesRead ;
442+ totalChunkSize += lastChunkSize ;
443+ currentChunk ++ ;
443444
444- var outBytes = new byte [ lastBytesRead ] ;
445- Array . Copy ( temp , outBytes , lastBytesRead ) ;
446- File . WriteAllBytes ( uChunkFilePath , outBytes ) ;
445+ /* Record the total compressed size after this chunk */
446+ ChunkSizes . Add ( ( uint ) totalChunkSize ) ;
447447
448- fileNum ++ ;
449- totalBytesRead += lastBytesRead ;
448+ p . EndTask ( ) ;
450449
451- p . EndTask ( ) ;
450+ } while ( lastBytesRead == CHUNK_SIZE ) ;
452451
453- } while ( lastBytesRead == CHUNK_SIZE ) ;
454- }
452+ /* Get difference in number of chunks compared to item we replaced */
453+ numChunksDiff = numChunks - oldNumChunks ;
455454
456- /* Quick sanity check */
457- if ( fileNum != numChunks )
458- {
459- throw new Exception ( "Did not create the expected number of uncompressed chunks." ) ;
460- }
455+ /* Get the difference in compressed size */
456+ compressedSizeDiff = ( int ) outputFile . Length - ( int ) _compressedSize ;
461457
462- p . EndTask ( ) ;
458+ /* Update new compressed size */
459+ _compressedSize = ( uint ) outputFile . Length ;
463460
464- /*
465- * COMPRESS EACH CHUNK WITH PACKZIP
466- */
467- p . BeginTask ( taskWeightCompress , "Compressing chunks..." ) ;
461+ /* Quick sanity check */
462+ if ( _compressedSize != totalChunkSize )
463+ {
464+ log . Error ( "Compressed file size different than what was expected." ) ;
465+ }
466+ }
467+ }
468468
469- for ( int i = 0 ; i < fileNum ; i ++ )
469+ /* Quick sanity check */
470+ if ( currentChunk != numChunks )
470471 {
471- p . BeginTask ( 1.0f / ( float ) fileNum , String . Format ( "Compressing chunk {0}/{1}..." , i + 1 , fileNum ) ) ;
472-
473- var inf = Path . Combine ( u_chunks_dir , "u_" + i . ToString ( "00000000" ) + ".dat" ) ;
474- var outf = Path . Combine ( c_chunks_dir , "c_" + i . ToString ( "00000000" ) + ".dat" ) ;
475- var args = String . Format ( "-o 0x0 -w -15 \" {0}\" \" {1}\" " , inf , outf ) ;
476-
477- /* Spawn a packzip.exe process to do the compression */
478- ProcessHelper . Run ( FilePathHelper . PackzipPath , args ) ;
479-
480- p . EndTask ( ) ;
472+ log . Error ( "Did not create the expected number of chunks." ) ;
481473 }
482474
483475 p . EndTask ( ) ;
484476
485477 /*
486- * COMBINE COMPRESSED CHUNKS AND UPDATE CHUNK SIZE LIST
478+ * UPDATE METADATA FOR ITEMS AFTER THIS ONE
487479 */
488- p . BeginTask ( taskWeightJoin , "Combining compressed chunks..." ) ;
489-
490- int compressedSizeDiff = 0 ;
491- int numChunksDiff = 0 ;
492- int oldNumChunks = ChunkSizes . Count ( ) ;
493- var destFilePath = Path . Combine ( workDir , "inject.dat" ) ;
494-
495- using ( var destFile = new FileStream ( destFilePath , FileMode . Create ) )
496- {
497- var lastChunkSize = 0 ;
498- ChunkSizes . Clear ( ) ;
499-
500- /* Get the list of compressed chunks - files should be in order alphabetically */
501- string [ ] chunkFiles = Directory . GetFiles ( c_chunks_dir ) ;
502-
503- /* Quick sanity check */
504- if ( chunkFiles . Length != numChunks )
505- {
506- throw new Exception ( "Did not find expected number of compressed chunks." ) ;
507- }
508-
509- /* Read in each compressed chunk and add it to the output file */
510- for ( int i = 0 ; i < numChunks ; i ++ )
511- {
512- p . BeginTask ( 1.0f / ( float ) numChunks , String . Format ( "Combining chunk {0}/{1}..." , i + 1 , numChunks ) ) ;
513-
514- /* Open the chunk file */
515- using ( var chunk = new FileStream ( chunkFiles [ i ] , FileMode . Open ) )
516- {
517- /* Get the chunk size */
518- int chunkSize = ( int ) chunk . Length ;
519-
520- /* Read in the chunk */
521- var chunkBytes = new byte [ chunkSize ] ;
522- chunk . Seek ( 0 , SeekOrigin . Begin ) ;
523- chunk . Read ( chunkBytes , 0 , chunkSize ) ;
524-
525- /* Write chunk to output injection file */
526- destFile . Write ( chunkBytes , 0 , chunkSize ) ;
527-
528- /* Update our list of chunk sizes (remember they are cumulative) */
529- lastChunkSize += chunkSize ;
530- ChunkSizes . Add ( ( uint ) lastChunkSize ) ;
531- }
532-
533- p . EndTask ( ) ;
534- }
535-
536- /* Get different in number of chunks compared to item we replaced */
537- numChunksDiff = numChunks - oldNumChunks ;
538-
539- /* Get the difference in compressed size */
540- compressedSizeDiff = ( int ) destFile . Length - ( int ) _compressedSize ;
541- _compressedSize = ( uint ) destFile . Length ;
542- }
480+ p . BeginTask ( taskWeightUpdateMetadata , "Updating archive metadata..." ) ;
543481
544482 /* Update data offsets for each item AFTER this one */
545483 for ( int i = ( int ) Id + 1 ; i < Archive . Items . Count ; i ++ )
@@ -601,18 +539,12 @@ public void Inject(string inputFilePath, NefsProgressInfo p)
601539 */
602540 p . BeginTask ( taskWeightCleanup , "Cleaning up..." ) ;
603541
604- Directory . Delete ( u_chunks_dir , true ) ;
605- Directory . Delete ( c_chunks_dir , true ) ;
606-
607542 /* Whenever the archive is saved, this data will be injected */
608543 _pendingInjection = true ;
609544 _fileToInject = destFilePath ;
610545 _archive . Modified = true ;
611546
612547 p . EndTask ( ) ;
613-
614- // TODO : HANDLE CASES WHEN # OF CHUNKS CHANGED!!!!!!!!!!!!!!!
615-
616548 }
617549
618550 /// <summary>
0 commit comments