[ArchiveTools] Add writing to archive from stream

This commit is contained in:
Matt Nadareski
2016-09-29 13:01:06 -07:00
parent 7df5660b0a
commit 765d6ce743

View File

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