diff --git a/SabreTools.DatTools/Rebuilder.cs b/SabreTools.DatTools/Rebuilder.cs index e252d153..8a4a874d 100644 --- a/SabreTools.DatTools/Rebuilder.cs +++ b/SabreTools.DatTools/Rebuilder.cs @@ -749,7 +749,6 @@ namespace SabreTools.DatTools try { // TODO: Write entry to a temporary file to avoid over-large in-memory streams - // TODO: Once entry is written, replace GetEntryStream implementations // TODO: Only write to file if there are multiple dupes ItemType itemType = datItem.GetStringFieldValue(Models.Metadata.DatItem.TypeKey).AsEnumValue(); (stream, _) = archive.GetEntryStream(datItem.GetName() ?? itemType.AsStringValue() ?? string.Empty); diff --git a/SabreTools.FileTypes/Archives/GZipArchive.cs b/SabreTools.FileTypes/Archives/GZipArchive.cs index 36187600..b310304c 100644 --- a/SabreTools.FileTypes/Archives/GZipArchive.cs +++ b/SabreTools.FileTypes/Archives/GZipArchive.cs @@ -172,42 +172,26 @@ namespace SabreTools.FileTypes.Archives /// public override (Stream?, string?) GetEntryStream(string entryName) { - var ms = new MemoryStream(); - string? realEntry; - // If we have an invalid file if (this.Filename == null) return (null, null); try { - // Decompress the _filename stream - realEntry = Path.GetFileNameWithoutExtension(this.Filename); + // Open the entry stream + string realEntry = Path.GetFileNameWithoutExtension(this.Filename); var gz = new gZip(); ZipReturn ret = gz.ZipFileOpen(this.Filename); - ret = gz.ZipFileOpenReadStream(0, out Stream? gzstream, out ulong streamSize); + ret = gz.ZipFileOpenReadStream(0, out Stream? stream, out ulong streamSize); - // Write the file out - byte[] gbuffer = new byte[_bufferSize]; - int glen; - while ((glen = gzstream!.Read(gbuffer, 0, _bufferSize)) > 0) - { - - ms.Write(gbuffer, 0, glen); - ms.Flush(); - } - - // Dispose of the streams - gzstream.Dispose(); + // Return the stream + return (stream, realEntry); } catch (Exception ex) { logger.Error(ex); - ms = null; - realEntry = null; + return (null, null); } - - return (ms, realEntry); } #endregion diff --git a/SabreTools.FileTypes/Archives/RarArchive.cs b/SabreTools.FileTypes/Archives/RarArchive.cs index f32656b3..ea53f0a1 100644 --- a/SabreTools.FileTypes/Archives/RarArchive.cs +++ b/SabreTools.FileTypes/Archives/RarArchive.cs @@ -137,35 +137,44 @@ namespace SabreTools.FileTypes.Archives public override (Stream?, string?) GetEntryStream(string entryName) { #if NET462_OR_GREATER || NETCOREAPP - var ms = new MemoryStream(); - string? realEntry = null; - // If we have an invalid file if (this.Filename == null) return (null, null); try { - SharpCompress.Archives.Rar.RarArchive ra = SharpCompress.Archives.Rar.RarArchive.Open(this.Filename, new ReaderOptions { LeaveStreamOpen = false, }); + Stream? stream = null; + string? realEntry = null; + + var ra = SharpCompress.Archives.Rar.RarArchive.Open(this.Filename, new ReaderOptions { LeaveStreamOpen = false, }); foreach (RarArchiveEntry entry in ra.Entries) { - if (entry?.Key != null && !entry.IsDirectory && entry.Key.Contains(entryName)) - { - // Write the file out - realEntry = entry.Key; - entry.WriteTo(ms); - } + // Skip invalid entries + if (entry?.Key == null || !entry.IsComplete) + continue; + + // Skip directory entries + if (entry.IsDirectory) + continue; + + // Skip non-matching keys + if (!entry.Key.Contains(entryName)) + continue; + + // Open the entry stream + realEntry = entry.Key; + stream = entry.OpenEntryStream(); + break; } + ra.Dispose(); + return (stream, realEntry); } catch (Exception ex) { logger.Error(ex); - ms = null; - realEntry = null; + return (null, null); } - - return (ms, realEntry); #else // TODO: Support RAR archives in old .NET return (null, null); diff --git a/SabreTools.FileTypes/Archives/SevenZipArchive.cs b/SabreTools.FileTypes/Archives/SevenZipArchive.cs index 3ade8fcb..a6cd908b 100644 --- a/SabreTools.FileTypes/Archives/SevenZipArchive.cs +++ b/SabreTools.FileTypes/Archives/SevenZipArchive.cs @@ -223,70 +223,51 @@ namespace SabreTools.FileTypes.Archives /// public override (Stream?, string?) GetEntryStream(string entryName) { - var ms = new MemoryStream(); - string? realEntry = null; - // If we have an invalid file if (this.Filename == null) return (null, null); try { - SevenZ zf = new(); + Stream? stream = null; + string? realEntry = null; + + var zf = new SevenZ(); ZipReturn zr = zf.ZipFileOpen(this.Filename, -1, true); if (zr != ZipReturn.ZipGood) - { throw new Exception(CompressUtils.ZipErrorMessageText(zr)); - } for (int i = 0; i < zf.LocalFilesCount() && zr == ZipReturn.ZipGood; i++) { - if (zf.GetLocalFile(i).Filename!.Contains(entryName)) - { - // Open the read stream - realEntry = zf.GetLocalFile(i).Filename; - zr = zf.ZipFileOpenReadStream(i, out Stream? readStream, out ulong streamsize); + // Get the entry + var entry = zf.GetLocalFile(i); - // If the stream is smaller than the buffer, just run one loop through to avoid issues - if (streamsize < _bufferSize) - { - byte[] ibuffer = new byte[streamsize]; - int ilen = readStream!.Read(ibuffer, 0, (int)streamsize); - ms.Write(ibuffer, 0, ilen); - ms.Flush(); - } - // Otherwise, we do the normal loop - else - { - byte[] ibuffer = new byte[_bufferSize]; - int ilen; - while (streamsize > _bufferSize) - { - ilen = readStream!.Read(ibuffer, 0, _bufferSize); - ms.Write(ibuffer, 0, ilen); - ms.Flush(); - streamsize -= _bufferSize; - } + // Skip invalid entries + if (entry.Filename == null) + continue; - ilen = readStream!.Read(ibuffer, 0, (int)streamsize); - ms.Write(ibuffer, 0, ilen); - ms.Flush(); - } + // Skip directory entries + if (entry.IsDirectory) + continue; - zr = zf.ZipFileCloseReadStream(); - } + // Skip non-matching keys + if (!entry.Filename.Contains(entryName)) + continue; + + // Open the entry stream + realEntry = entry.Filename; + zr = zf.ZipFileOpenReadStream(i, out stream, out ulong streamsize); + break; } zf.ZipFileClose(); + return (stream, realEntry); } catch (Exception ex) { logger.Error(ex); - ms = null; - realEntry = null; + return (null, null); } - - return (ms, realEntry); } #endregion diff --git a/SabreTools.FileTypes/Archives/TapeArchive.cs b/SabreTools.FileTypes/Archives/TapeArchive.cs index 27c81601..015cd0b1 100644 --- a/SabreTools.FileTypes/Archives/TapeArchive.cs +++ b/SabreTools.FileTypes/Archives/TapeArchive.cs @@ -138,31 +138,40 @@ namespace SabreTools.FileTypes.Archives public override (Stream?, string?) GetEntryStream(string entryName) { #if NET462_OR_GREATER || NETCOREAPP - var ms = new MemoryStream(); - string? realEntry = null; - try { - TarArchive ta = TarArchive.Open(this.Filename!, new ReaderOptions { LeaveStreamOpen = false, }); + Stream? stream = null; + string? realEntry = null; + + var ta = TarArchive.Open(this.Filename!, new ReaderOptions { LeaveStreamOpen = false, }); foreach (TarArchiveEntry entry in ta.Entries) { - if (entry?.Key != null && !entry.IsDirectory && entry.Key.Contains(entryName)) - { - // Write the file out - realEntry = entry.Key; - entry.WriteTo(ms); - } + // Skip invalid entries + if (entry?.Key == null || !entry.IsComplete) + continue; + + // Skip directory entries + if (entry.IsDirectory) + continue; + + // Skip non-matching keys + if (!entry.Key.Contains(entryName)) + continue; + + // Open the entry stream + realEntry = entry.Key; + stream = entry.OpenEntryStream(); + break; } + ta.Dispose(); + return (stream, realEntry); } catch (Exception ex) { logger.Error(ex); - ms = null; - realEntry = null; + return (null, null); } - - return (ms, realEntry); #else // TODO: Support tape archives in old .NET return (null, null); diff --git a/SabreTools.FileTypes/Archives/XZArchive.cs b/SabreTools.FileTypes/Archives/XZArchive.cs index d6ae5cb0..31854bef 100644 --- a/SabreTools.FileTypes/Archives/XZArchive.cs +++ b/SabreTools.FileTypes/Archives/XZArchive.cs @@ -155,36 +155,24 @@ namespace SabreTools.FileTypes.Archives public override (Stream?, string?) GetEntryStream(string entryName) { #if NET462_OR_GREATER || NETCOREAPP - var ms = new MemoryStream(); - string? realEntry; + // If we have an invalid file + if (this.Filename == null) + return (null, null); try { - // Decompress the _filename stream - realEntry = Path.GetFileNameWithoutExtension(this.Filename); - var xz = new XZStream(File.OpenRead(this.Filename!)); + // Open the entry stream + string realEntry = Path.GetFileNameWithoutExtension(this.Filename); + var stream = new XZStream(File.OpenRead(this.Filename)); - // Write the file out - byte[] xbuffer = new byte[_bufferSize]; - int xlen; - while ((xlen = xz.Read(xbuffer, 0, _bufferSize)) > 0) - { - - ms.Write(xbuffer, 0, xlen); - ms.Flush(); - } - - // Dispose of the streams - xz.Dispose(); + // Return the stream + return (stream, realEntry); } catch (Exception ex) { logger.Error(ex); - ms = null; - realEntry = null; + return (null, null); } - - return (ms, realEntry); #else // TODO: Support XZ archives in old .NET return (null, null); diff --git a/SabreTools.FileTypes/Archives/ZipArchive.cs b/SabreTools.FileTypes/Archives/ZipArchive.cs index d8a69520..65a89d68 100644 --- a/SabreTools.FileTypes/Archives/ZipArchive.cs +++ b/SabreTools.FileTypes/Archives/ZipArchive.cs @@ -198,66 +198,51 @@ namespace SabreTools.FileTypes.Archives /// public override (Stream?, string?) GetEntryStream(string entryName) { - var ms = new MemoryStream(); - string? realEntry = null; + // If we have an invalid file + if (this.Filename == null) + return (null, null); try { - Zip zf = new(); + Stream? stream = null; + string? realEntry = null; + + var zf = new Zip(); ZipReturn zr = zf.ZipFileOpen(this.Filename!, -1, true); if (zr != ZipReturn.ZipGood) - { throw new Exception(CompressUtils.ZipErrorMessageText(zr)); - } for (int i = 0; i < zf.LocalFilesCount() && zr == ZipReturn.ZipGood; i++) { - if (zf.GetLocalFile(i).Filename!.Contains(entryName)) - { - // Open the read stream - realEntry = zf.GetLocalFile(i).Filename; - zr = zf.ZipFileOpenReadStream(i, false, out Stream? readStream, out ulong streamsize, out ushort cm); + // Get the entry + var entry = zf.GetLocalFile(i); - // If the stream is smaller than the buffer, just run one loop through to avoid issues - if (streamsize < _bufferSize) - { - byte[] ibuffer = new byte[streamsize]; - int ilen = readStream!.Read(ibuffer, 0, (int)streamsize); - ms.Write(ibuffer, 0, ilen); - ms.Flush(); - } - // Otherwise, we do the normal loop - else - { - byte[] ibuffer = new byte[_bufferSize]; - int ilen; - while (streamsize > _bufferSize) - { - ilen = readStream!.Read(ibuffer, 0, _bufferSize); - ms.Write(ibuffer, 0, ilen); - ms.Flush(); - streamsize -= _bufferSize; - } + // Skip invalid entries + if (entry.Filename == null) + continue; - ilen = readStream!.Read(ibuffer, 0, (int)streamsize); - ms.Write(ibuffer, 0, ilen); - ms.Flush(); - } + // Skip directory entries + if (entry.IsDirectory) + continue; - zr = zf.ZipFileCloseReadStream(); - } + // Skip non-matching keys + if (!entry.Filename.Contains(entryName)) + continue; + + // Open the entry stream + realEntry = entry.Filename; + zr = zf.ZipFileOpenReadStream(i, out stream, out ulong streamsize); + break; } zf.ZipFileClose(); + return (stream, realEntry); } catch (Exception ex) { logger.Error(ex); - ms = null; - realEntry = null; + return (null, null); } - - return (ms, realEntry); } #endregion @@ -779,7 +764,7 @@ namespace SabreTools.FileTypes.Archives // Instantiate the streams oldZipFile.ZipFileOpenReadStream(index, false, out Stream? zreadStream, out ulong istreamSize, out ushort icompressionMethod); long msDosDateTime = oldZipFile.GetLocalFile(index).LastModified; - TimeStamps ts = new() { ModTime = msDosDateTime }; + TimeStamps ts = new() { ModTime = msDosDateTime }; zipFile.ZipFileOpenWriteStream(false, true, oldZipFile.GetLocalFile(index).Filename!, istreamSize, (ushort)CompressionMethod.Deflated, out writeStream, ts); // Copy the input stream to the output diff --git a/SabreTools.FileTypes/Folder.cs b/SabreTools.FileTypes/Folder.cs index eed50535..7d4d225e 100644 --- a/SabreTools.FileTypes/Folder.cs +++ b/SabreTools.FileTypes/Folder.cs @@ -212,9 +212,6 @@ namespace SabreTools.FileTypes /// Stream representing the entry, null on error public virtual (Stream?, string?) GetEntryStream(string entryName) { - var ms = new MemoryStream(); - string? realentry = null; - // If we have an invalid filename if (this.Filename == null) return (null, null); @@ -231,30 +228,20 @@ namespace SabreTools.FileTypes // Now sort through to find the first file that matches string? match = files.Where(s => s.EndsWith(entryName)).FirstOrDefault(); - // If we had a file, copy that over to the new name + // If we had a file, open and return the stream if (!string.IsNullOrEmpty(match)) { -#if NET20 || NET35 - var tempStream = File.OpenRead(match); - byte[] buffer = new byte[32768]; - int read; - while ((read = tempStream.Read(buffer, 0, buffer.Length)) > 0) - { - ms.Write(buffer, 0, read); - } -#else - File.OpenRead(match).CopyTo(ms); -#endif - realentry = match; + var stream = File.OpenRead(match); + return (stream, match); } + + return (null, null); } catch (Exception ex) { logger.Error(ex); - return (ms, realentry); + return (null, null); } - - return (ms, realentry); } #endregion