mirror of
https://github.com/claunia/SabreTools.git
synced 2025-12-16 19:14:27 +00:00
Return direct stream from archives
This commit is contained in:
@@ -749,7 +749,6 @@ namespace SabreTools.DatTools
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
// TODO: Write entry to a temporary file to avoid over-large in-memory streams
|
// 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
|
// TODO: Only write to file if there are multiple dupes
|
||||||
ItemType itemType = datItem.GetStringFieldValue(Models.Metadata.DatItem.TypeKey).AsEnumValue<ItemType>();
|
ItemType itemType = datItem.GetStringFieldValue(Models.Metadata.DatItem.TypeKey).AsEnumValue<ItemType>();
|
||||||
(stream, _) = archive.GetEntryStream(datItem.GetName() ?? itemType.AsStringValue() ?? string.Empty);
|
(stream, _) = archive.GetEntryStream(datItem.GetName() ?? itemType.AsStringValue() ?? string.Empty);
|
||||||
|
|||||||
@@ -172,42 +172,26 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public override (Stream?, string?) GetEntryStream(string entryName)
|
public override (Stream?, string?) GetEntryStream(string entryName)
|
||||||
{
|
{
|
||||||
var ms = new MemoryStream();
|
|
||||||
string? realEntry;
|
|
||||||
|
|
||||||
// If we have an invalid file
|
// If we have an invalid file
|
||||||
if (this.Filename == null)
|
if (this.Filename == null)
|
||||||
return (null, null);
|
return (null, null);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Decompress the _filename stream
|
// Open the entry stream
|
||||||
realEntry = Path.GetFileNameWithoutExtension(this.Filename);
|
string realEntry = Path.GetFileNameWithoutExtension(this.Filename);
|
||||||
var gz = new gZip();
|
var gz = new gZip();
|
||||||
ZipReturn ret = gz.ZipFileOpen(this.Filename);
|
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
|
// Return the stream
|
||||||
byte[] gbuffer = new byte[_bufferSize];
|
return (stream, realEntry);
|
||||||
int glen;
|
|
||||||
while ((glen = gzstream!.Read(gbuffer, 0, _bufferSize)) > 0)
|
|
||||||
{
|
|
||||||
|
|
||||||
ms.Write(gbuffer, 0, glen);
|
|
||||||
ms.Flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dispose of the streams
|
|
||||||
gzstream.Dispose();
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.Error(ex);
|
logger.Error(ex);
|
||||||
ms = null;
|
return (null, null);
|
||||||
realEntry = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (ms, realEntry);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
@@ -137,35 +137,44 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
public override (Stream?, string?) GetEntryStream(string entryName)
|
public override (Stream?, string?) GetEntryStream(string entryName)
|
||||||
{
|
{
|
||||||
#if NET462_OR_GREATER || NETCOREAPP
|
#if NET462_OR_GREATER || NETCOREAPP
|
||||||
var ms = new MemoryStream();
|
|
||||||
string? realEntry = null;
|
|
||||||
|
|
||||||
// If we have an invalid file
|
// If we have an invalid file
|
||||||
if (this.Filename == null)
|
if (this.Filename == null)
|
||||||
return (null, null);
|
return (null, null);
|
||||||
|
|
||||||
try
|
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)
|
foreach (RarArchiveEntry entry in ra.Entries)
|
||||||
{
|
{
|
||||||
if (entry?.Key != null && !entry.IsDirectory && entry.Key.Contains(entryName))
|
// Skip invalid entries
|
||||||
{
|
if (entry?.Key == null || !entry.IsComplete)
|
||||||
// Write the file out
|
continue;
|
||||||
realEntry = entry.Key;
|
|
||||||
entry.WriteTo(ms);
|
// 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();
|
ra.Dispose();
|
||||||
|
return (stream, realEntry);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.Error(ex);
|
logger.Error(ex);
|
||||||
ms = null;
|
return (null, null);
|
||||||
realEntry = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (ms, realEntry);
|
|
||||||
#else
|
#else
|
||||||
// TODO: Support RAR archives in old .NET
|
// TODO: Support RAR archives in old .NET
|
||||||
return (null, null);
|
return (null, null);
|
||||||
|
|||||||
@@ -223,70 +223,51 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public override (Stream?, string?) GetEntryStream(string entryName)
|
public override (Stream?, string?) GetEntryStream(string entryName)
|
||||||
{
|
{
|
||||||
var ms = new MemoryStream();
|
|
||||||
string? realEntry = null;
|
|
||||||
|
|
||||||
// If we have an invalid file
|
// If we have an invalid file
|
||||||
if (this.Filename == null)
|
if (this.Filename == null)
|
||||||
return (null, null);
|
return (null, null);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
SevenZ zf = new();
|
Stream? stream = null;
|
||||||
|
string? realEntry = null;
|
||||||
|
|
||||||
|
var zf = new SevenZ();
|
||||||
ZipReturn zr = zf.ZipFileOpen(this.Filename, -1, true);
|
ZipReturn zr = zf.ZipFileOpen(this.Filename, -1, true);
|
||||||
if (zr != ZipReturn.ZipGood)
|
if (zr != ZipReturn.ZipGood)
|
||||||
{
|
|
||||||
throw new Exception(CompressUtils.ZipErrorMessageText(zr));
|
throw new Exception(CompressUtils.ZipErrorMessageText(zr));
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < zf.LocalFilesCount() && zr == ZipReturn.ZipGood; i++)
|
for (int i = 0; i < zf.LocalFilesCount() && zr == ZipReturn.ZipGood; i++)
|
||||||
{
|
{
|
||||||
if (zf.GetLocalFile(i).Filename!.Contains(entryName))
|
// Get the entry
|
||||||
{
|
var entry = zf.GetLocalFile(i);
|
||||||
// Open the read stream
|
|
||||||
realEntry = zf.GetLocalFile(i).Filename;
|
|
||||||
zr = zf.ZipFileOpenReadStream(i, out Stream? readStream, out ulong streamsize);
|
|
||||||
|
|
||||||
// If the stream is smaller than the buffer, just run one loop through to avoid issues
|
// Skip invalid entries
|
||||||
if (streamsize < _bufferSize)
|
if (entry.Filename == null)
|
||||||
{
|
continue;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
ilen = readStream!.Read(ibuffer, 0, (int)streamsize);
|
// Skip directory entries
|
||||||
ms.Write(ibuffer, 0, ilen);
|
if (entry.IsDirectory)
|
||||||
ms.Flush();
|
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();
|
zf.ZipFileClose();
|
||||||
|
return (stream, realEntry);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.Error(ex);
|
logger.Error(ex);
|
||||||
ms = null;
|
return (null, null);
|
||||||
realEntry = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (ms, realEntry);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
@@ -138,31 +138,40 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
public override (Stream?, string?) GetEntryStream(string entryName)
|
public override (Stream?, string?) GetEntryStream(string entryName)
|
||||||
{
|
{
|
||||||
#if NET462_OR_GREATER || NETCOREAPP
|
#if NET462_OR_GREATER || NETCOREAPP
|
||||||
var ms = new MemoryStream();
|
|
||||||
string? realEntry = null;
|
|
||||||
|
|
||||||
try
|
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)
|
foreach (TarArchiveEntry entry in ta.Entries)
|
||||||
{
|
{
|
||||||
if (entry?.Key != null && !entry.IsDirectory && entry.Key.Contains(entryName))
|
// Skip invalid entries
|
||||||
{
|
if (entry?.Key == null || !entry.IsComplete)
|
||||||
// Write the file out
|
continue;
|
||||||
realEntry = entry.Key;
|
|
||||||
entry.WriteTo(ms);
|
// 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();
|
ta.Dispose();
|
||||||
|
return (stream, realEntry);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.Error(ex);
|
logger.Error(ex);
|
||||||
ms = null;
|
return (null, null);
|
||||||
realEntry = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (ms, realEntry);
|
|
||||||
#else
|
#else
|
||||||
// TODO: Support tape archives in old .NET
|
// TODO: Support tape archives in old .NET
|
||||||
return (null, null);
|
return (null, null);
|
||||||
|
|||||||
@@ -155,36 +155,24 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
public override (Stream?, string?) GetEntryStream(string entryName)
|
public override (Stream?, string?) GetEntryStream(string entryName)
|
||||||
{
|
{
|
||||||
#if NET462_OR_GREATER || NETCOREAPP
|
#if NET462_OR_GREATER || NETCOREAPP
|
||||||
var ms = new MemoryStream();
|
// If we have an invalid file
|
||||||
string? realEntry;
|
if (this.Filename == null)
|
||||||
|
return (null, null);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Decompress the _filename stream
|
// Open the entry stream
|
||||||
realEntry = Path.GetFileNameWithoutExtension(this.Filename);
|
string realEntry = Path.GetFileNameWithoutExtension(this.Filename);
|
||||||
var xz = new XZStream(File.OpenRead(this.Filename!));
|
var stream = new XZStream(File.OpenRead(this.Filename));
|
||||||
|
|
||||||
// Write the file out
|
// Return the stream
|
||||||
byte[] xbuffer = new byte[_bufferSize];
|
return (stream, realEntry);
|
||||||
int xlen;
|
|
||||||
while ((xlen = xz.Read(xbuffer, 0, _bufferSize)) > 0)
|
|
||||||
{
|
|
||||||
|
|
||||||
ms.Write(xbuffer, 0, xlen);
|
|
||||||
ms.Flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dispose of the streams
|
|
||||||
xz.Dispose();
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.Error(ex);
|
logger.Error(ex);
|
||||||
ms = null;
|
return (null, null);
|
||||||
realEntry = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (ms, realEntry);
|
|
||||||
#else
|
#else
|
||||||
// TODO: Support XZ archives in old .NET
|
// TODO: Support XZ archives in old .NET
|
||||||
return (null, null);
|
return (null, null);
|
||||||
|
|||||||
@@ -198,66 +198,51 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public override (Stream?, string?) GetEntryStream(string entryName)
|
public override (Stream?, string?) GetEntryStream(string entryName)
|
||||||
{
|
{
|
||||||
var ms = new MemoryStream();
|
// If we have an invalid file
|
||||||
string? realEntry = null;
|
if (this.Filename == null)
|
||||||
|
return (null, null);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Zip zf = new();
|
Stream? stream = null;
|
||||||
|
string? realEntry = null;
|
||||||
|
|
||||||
|
var zf = new Zip();
|
||||||
ZipReturn zr = zf.ZipFileOpen(this.Filename!, -1, true);
|
ZipReturn zr = zf.ZipFileOpen(this.Filename!, -1, true);
|
||||||
if (zr != ZipReturn.ZipGood)
|
if (zr != ZipReturn.ZipGood)
|
||||||
{
|
|
||||||
throw new Exception(CompressUtils.ZipErrorMessageText(zr));
|
throw new Exception(CompressUtils.ZipErrorMessageText(zr));
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < zf.LocalFilesCount() && zr == ZipReturn.ZipGood; i++)
|
for (int i = 0; i < zf.LocalFilesCount() && zr == ZipReturn.ZipGood; i++)
|
||||||
{
|
{
|
||||||
if (zf.GetLocalFile(i).Filename!.Contains(entryName))
|
// Get the entry
|
||||||
{
|
var entry = zf.GetLocalFile(i);
|
||||||
// Open the read stream
|
|
||||||
realEntry = zf.GetLocalFile(i).Filename;
|
|
||||||
zr = zf.ZipFileOpenReadStream(i, false, out Stream? readStream, out ulong streamsize, out ushort cm);
|
|
||||||
|
|
||||||
// If the stream is smaller than the buffer, just run one loop through to avoid issues
|
// Skip invalid entries
|
||||||
if (streamsize < _bufferSize)
|
if (entry.Filename == null)
|
||||||
{
|
continue;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
ilen = readStream!.Read(ibuffer, 0, (int)streamsize);
|
// Skip directory entries
|
||||||
ms.Write(ibuffer, 0, ilen);
|
if (entry.IsDirectory)
|
||||||
ms.Flush();
|
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();
|
zf.ZipFileClose();
|
||||||
|
return (stream, realEntry);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.Error(ex);
|
logger.Error(ex);
|
||||||
ms = null;
|
return (null, null);
|
||||||
realEntry = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (ms, realEntry);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -779,7 +764,7 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
// Instantiate the streams
|
// Instantiate the streams
|
||||||
oldZipFile.ZipFileOpenReadStream(index, false, out Stream? zreadStream, out ulong istreamSize, out ushort icompressionMethod);
|
oldZipFile.ZipFileOpenReadStream(index, false, out Stream? zreadStream, out ulong istreamSize, out ushort icompressionMethod);
|
||||||
long msDosDateTime = oldZipFile.GetLocalFile(index).LastModified;
|
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);
|
zipFile.ZipFileOpenWriteStream(false, true, oldZipFile.GetLocalFile(index).Filename!, istreamSize, (ushort)CompressionMethod.Deflated, out writeStream, ts);
|
||||||
|
|
||||||
// Copy the input stream to the output
|
// Copy the input stream to the output
|
||||||
|
|||||||
@@ -212,9 +212,6 @@ namespace SabreTools.FileTypes
|
|||||||
/// <returns>Stream representing the entry, null on error</returns>
|
/// <returns>Stream representing the entry, null on error</returns>
|
||||||
public virtual (Stream?, string?) GetEntryStream(string entryName)
|
public virtual (Stream?, string?) GetEntryStream(string entryName)
|
||||||
{
|
{
|
||||||
var ms = new MemoryStream();
|
|
||||||
string? realentry = null;
|
|
||||||
|
|
||||||
// If we have an invalid filename
|
// If we have an invalid filename
|
||||||
if (this.Filename == null)
|
if (this.Filename == null)
|
||||||
return (null, null);
|
return (null, null);
|
||||||
@@ -231,30 +228,20 @@ namespace SabreTools.FileTypes
|
|||||||
// Now sort through to find the first file that matches
|
// Now sort through to find the first file that matches
|
||||||
string? match = files.Where(s => s.EndsWith(entryName)).FirstOrDefault();
|
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 (!string.IsNullOrEmpty(match))
|
||||||
{
|
{
|
||||||
#if NET20 || NET35
|
var stream = File.OpenRead(match);
|
||||||
var tempStream = File.OpenRead(match);
|
return (stream, 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return (null, null);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.Error(ex);
|
logger.Error(ex);
|
||||||
return (ms, realentry);
|
return (null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (ms, realentry);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
Reference in New Issue
Block a user