diff --git a/SabreTools.Helper/Tools/ArchiveTools.cs b/SabreTools.Helper/Tools/ArchiveTools.cs index a70c26cc..8a8d06cc 100644 --- a/SabreTools.Helper/Tools/ArchiveTools.cs +++ b/SabreTools.Helper/Tools/ArchiveTools.cs @@ -27,8 +27,9 @@ namespace SabreTools.Helper public static bool CopyFileBetweenArchives(string inputArchive, string outDir, string sourceEntryName, Rom destEntry, Logger logger) { - string tempfile = ExtractSingleItemFromArchive(inputArchive, sourceEntryName, Path.GetTempPath(), logger); - return WriteToArchive(tempfile, outDir, destEntry); + string realName = ""; + Stream ms = ExtractSingleStreamFromArchive(inputArchive, sourceEntryName, out realName, logger); + return WriteToArchive(ms, outDir, destEntry); } #endregion @@ -166,21 +167,56 @@ namespace SabreTools.Helper /// Attempt to extract a file from an archive /// /// Name of the archive to be extracted - /// Name of the entry to be extracted + /// Name of the entry to be extracted /// Temporary directory for archive extraction /// Logger object for file and console output /// Name of the extracted file, null on error - public static string ExtractSingleItemFromArchive(string input, string entryname, string tempDir, Logger logger) + public static string ExtractSingleItemFromArchive(string input, string entryName, string tempDir, Logger logger) { string outfile = null; + string realEntry = ""; + Stream ms = ExtractSingleStreamFromArchive(input, entryName, out realEntry, logger); + + realEntry = Path.GetFullPath(Path.Combine(tempDir, realEntry)); + if (!Directory.Exists(Path.GetDirectoryName(outfile))) + { + Directory.CreateDirectory(Path.GetDirectoryName(outfile)); + } + + FileStream fs = File.Open(realEntry, FileMode.Create, FileAccess.Write); + ms.CopyTo(fs); + fs.Flush(); + + // Dispose of the streams + ms.Dispose(); + fs.Dispose(); + + return outfile; + } + + /// + /// Attempt to extract a file from an archive + /// + /// Name of the archive to be extracted + /// Name of the entry to be extracted + /// Logger object for file and console output + /// Name of the extracted file, null on error + public static Stream ExtractSingleStreamFromArchive(string input, string entryName, out string realEntry, Logger logger) + { + // Set the real entry name + realEntry = ""; + + // Get a writable stream to return + Stream st = new MemoryStream(); + // First get the archive type ArchiveType? at = GetCurrentArchiveType(input, logger); // If we got back null, then it's not an archive, so we we return if (at == null) { - return outfile; + return st; } IReader reader = null; @@ -188,48 +224,40 @@ namespace SabreTools.Helper { if (at == ArchiveType.Zip || at == ArchiveType.SevenZip || at == ArchiveType.Rar) { - // Create the temp directory - Directory.CreateDirectory(tempDir); - reader = ReaderFactory.Open(File.OpenRead(input)); while (reader.MoveToNextEntry()) { logger.Verbose("Current entry name: '" + reader.Entry.Key + "'"); - if (reader.Entry != null && reader.Entry.Key.Contains(entryname)) + if (reader.Entry != null && reader.Entry.Key.Contains(entryName)) { - outfile = Path.GetFullPath(Path.Combine(tempDir, reader.Entry.Key)); - if (!Directory.Exists(Path.GetDirectoryName(outfile))) - { - Directory.CreateDirectory(Path.GetDirectoryName(outfile)); - } - reader.WriteEntryToFile(outfile, ExtractOptions.Overwrite); + realEntry = reader.Entry.Key; + reader.WriteEntryTo(st); } } } else if (at == ArchiveType.GZip) { // Decompress the input stream - FileStream outstream = File.Create(Path.Combine(tempDir, Path.GetFileNameWithoutExtension(input))); + realEntry = Path.GetFileNameWithoutExtension(input); GZipStream gzstream = new GZipStream(File.OpenRead(input), CompressionMode.Decompress); - gzstream.CopyTo(outstream); - outfile = Path.GetFullPath(Path.Combine(tempDir, Path.GetFileNameWithoutExtension(input))); + gzstream.CopyTo(st); // Dispose of the streams - outstream.Dispose(); + st.Dispose(); gzstream.Dispose(); } } catch (Exception ex) { logger.Error(ex.ToString()); - outfile = null; + st = null; } finally { reader?.Dispose(); } - return outfile; + return st; } #endregion @@ -536,10 +564,27 @@ namespace SabreTools.Helper /// RomData representing the new information /// True if the archive was written properly, false otherwise public static bool WriteToArchive(string inputFile, string outDir, Rom rom) + { + // Get the stream from the input file + Stream fs = File.OpenRead(inputFile); + bool success = WriteToArchive(fs, outDir, rom); + fs.Dispose(); + + return success; + } + + /// + /// Copy a stream to an output archive + /// + /// Input stream to be written + /// Output directory to build to + /// RomData representing the new information + /// True if the archive was written properly, false otherwise + public static bool WriteToArchive(Stream inputStream, string outDir, Rom rom) { // Wrap the individual inputs into lists - List inputFiles = new List(); - inputFiles.Add(inputFile); + List inputFiles = new List(); + inputFiles.Add(inputStream); List roms = new List(); roms.Add(rom); @@ -572,6 +617,41 @@ namespace SabreTools.Helper } } + // Get the streams from the input files + List inputStreams = new List(); + foreach (string inputFile in inputFiles) + { + inputStreams.Add(File.OpenRead(inputFile)); + } + + success = WriteToArchive(inputStreams, outDir, roms); + + // Now close all of the streams + foreach (Stream inputStream in inputStreams) + { + inputStream.Dispose(); + } + + return success; + } + + /// + /// Copy a set of streams to an output archive (assuming the same output archive name) + /// + /// Input streams to be moved + /// Output directory to build to + /// List of Rom representing the new information + /// True if the archive was written properly, false otherwise + public static bool WriteToArchive(List inputStreams, string outDir, List roms) + { + bool success = false; + + // If the number of inputs is less than the number of available roms, return + if (inputStreams.Count < roms.Count) + { + return success; + } + // Get the output archive name from the first rebuild rom string archiveFileName = Path.Combine(outDir, roms[0].MachineName + ".zip"); @@ -596,15 +676,18 @@ namespace SabreTools.Helper outarchive = System.IO.Compression.ZipFile.Open(archiveFileName, ZipArchiveMode.Update); // Now loop through and add all files - for (int i = 0; i < inputFiles.Count; i++) + for (int i = 0; i < inputStreams.Count; i++) { - string inputFile = inputFiles[i]; Rom rom = roms[i]; // If the archive doesn't already contain the entry, add it if (outarchive.GetEntry(rom.Name) == null) { - outarchive.CreateEntryFromFile(inputFile, rom.Name, CompressionLevel.Optimal); + ZipArchiveEntry ae = outarchive.CreateEntry(rom.Name, CompressionLevel.Optimal); + Stream outputStream = ae.Open(); + inputStreams[i].CopyTo(outputStream); + outputStream.Flush(); + outputStream.Dispose(); } // If there's a Date attached to the rom, change the entry to that Date