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
|
||||
{
|
||||
// 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<ItemType>();
|
||||
(stream, _) = archive.GetEntryStream(datItem.GetName() ?? itemType.AsStringValue() ?? string.Empty);
|
||||
|
||||
@@ -172,42 +172,26 @@ namespace SabreTools.FileTypes.Archives
|
||||
/// <inheritdoc/>
|
||||
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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -223,70 +223,51 @@ namespace SabreTools.FileTypes.Archives
|
||||
/// <inheritdoc/>
|
||||
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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -198,66 +198,51 @@ namespace SabreTools.FileTypes.Archives
|
||||
/// <inheritdoc/>
|
||||
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
|
||||
|
||||
@@ -212,9 +212,6 @@ namespace SabreTools.FileTypes
|
||||
/// <returns>Stream representing the entry, null on error</returns>
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user