示例#1
0
 private static void CompressWorkThread(object param) {
     CompressWork cw = (CompressWork)param;
     CompressEntry ce;
     while (cw.Input.TryTake(out ce)) {
         ce.DataRec = GetData(ce.ACE.GetData(), ce.ACE.Filename, cw.Compress);
         cw.Compressed.Add(ce);
     }
 }
示例#2
0
        public static void Create(System.IO.Stream output, IEnumerable<ArchiveCreateEntry> files, ArchiveFlags flags, CompressType compress, Action<double, string> onProgress) {
            if (!files.Any())
                throw new IrosArcException("Can't create an archive that contains no files");
            var sw = new System.Diagnostics.Stopwatch();
            sw.Start();
            double total = files.Count() + 2;
            int count = 0;

            onProgress(count / total, "");
            ArcHeader h = new ArcHeader() { Flags = flags, Version = MAX_VERSION, Directory = 16 };
            List<DirectoryEntry> entries = files.Select(f => new DirectoryEntry() {
                Filename = f.Filename, Flags = 0, 
            }).ToList();
            int dsize = entries.Select(e => (int)e.GetSize()).Sum();
            h.Save(output);
            output.WriteInt(entries.Count);
            long position = h.Directory + dsize + 4;
            onProgress(++count / total, "Wrote header");
            int index = 0;
            var combined = entries.Zip(files, (d,e) => new { Dir = d, ACE = e }).ToList();

            var cw = new CompressWork() {
                Input = new System.Collections.Concurrent.ConcurrentBag<CompressEntry>(),
                Compressed = new System.Collections.Concurrent.BlockingCollection<CompressEntry>(8),
                Compress = compress
            };
            
            foreach (var comb in combined) {
                cw.Input.Add(new CompressEntry() { ACE = comb.ACE, Dir = comb.Dir });
            }
            foreach (int _ in Enumerable.Range(0, 8)) System.Threading.ThreadPool.QueueUserWorkItem(CompressWorkThread, cw);

            int filesDone = 0;

            while (filesDone < combined.Count) {
                var entry = cw.Compressed.Take();
                entry.Dir.Offset = position;
                var data = entry.DataRec.Data;
                if (entry.DataRec.Compressed) entry.Dir.Flags |= FileFlags.CompressLZMA;
                entry.Dir.Length = data.Length;

                output.Position = position;
                output.Write(data, 0, data.Length);

                position += entry.Dir.Length;
                onProgress(++count / total, "Written " + entry.ACE.Filename);
                index++;
                filesDone++;
            }

            output.Position = h.Directory + 4;
            foreach (var entry in entries) {
                entry.Save(output);
            }
            sw.Stop();
            onProgress(++count / total, String.Format("Complete: {0} files, {1:0.0}MB in {2} seconds", entries.Count, output.Length / (1024f*1024f), sw.Elapsed.TotalSeconds));
        }