Stream MSCab extraction output.
This commit is contained in:
@@ -87,23 +87,22 @@ namespace OpenRA.Mods.Common.FileFormats
|
|||||||
files[i] = new CabFile(stream);
|
files[i] = new CabFile(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] ExtractFile(string filename, Action<int> onProgress = null)
|
public void ExtractFile(string filename, Stream output, Action<int> onProgress = null)
|
||||||
{
|
{
|
||||||
var file = files.FirstOrDefault(f => f.FileName == filename);
|
var file = files.FirstOrDefault(f => f.FileName == filename);
|
||||||
if (file == null)
|
if (file == null)
|
||||||
return null;
|
throw new FileNotFoundException(filename);
|
||||||
|
|
||||||
var folder = folders[file.FolderIndex];
|
var folder = folders[file.FolderIndex];
|
||||||
stream.Seek(folder.BlockOffset, SeekOrigin.Begin);
|
stream.Seek(folder.BlockOffset, SeekOrigin.Begin);
|
||||||
|
|
||||||
using (var outputStream = new MemoryStream())
|
|
||||||
{
|
|
||||||
var inflater = new Inflater(true);
|
var inflater = new Inflater(true);
|
||||||
var buffer = new byte[4096];
|
var buffer = new byte[4096];
|
||||||
|
var decompressedBytes = 0;
|
||||||
for (var i = 0; i < folder.BlockCount; i++)
|
for (var i = 0; i < folder.BlockCount; i++)
|
||||||
{
|
{
|
||||||
if (onProgress != null)
|
if (onProgress != null)
|
||||||
onProgress((int)(100 * outputStream.Position / file.DecompressedLength));
|
onProgress((int)(100 * output.Position / file.DecompressedLength));
|
||||||
|
|
||||||
// Ignore checksums
|
// Ignore checksums
|
||||||
stream.Position += 4;
|
stream.Position += 4;
|
||||||
@@ -115,15 +114,18 @@ namespace OpenRA.Mods.Common.FileFormats
|
|||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
while ((n = inflaterStream.Read(buffer, 0, buffer.Length)) > 0)
|
while ((n = inflaterStream.Read(buffer, 0, buffer.Length)) > 0)
|
||||||
outputStream.Write(buffer, 0, n);
|
{
|
||||||
|
var offset = Math.Max(0, file.DecompressedOffset - decompressedBytes);
|
||||||
|
var count = Math.Min(n - offset, file.DecompressedLength - decompressedBytes);
|
||||||
|
if (offset < n)
|
||||||
|
output.Write(buffer, (int)offset, (int)count);
|
||||||
|
|
||||||
|
decompressedBytes += n;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inflater.Reset();
|
inflater.Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
outputStream.Seek(file.DecompressedOffset, SeekOrigin.Begin);
|
|
||||||
return outputStream.ReadBytes((int)file.DecompressedLength);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<string> Contents { get { return files.Select(f => f.FileName); } }
|
public IEnumerable<string> Contents { get { return files.Select(f => f.FileName); } }
|
||||||
|
|||||||
@@ -304,12 +304,10 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
Directory.CreateDirectory(Path.GetDirectoryName(targetPath));
|
Directory.CreateDirectory(Path.GetDirectoryName(targetPath));
|
||||||
using (var target = File.OpenWrite(targetPath))
|
using (var target = File.OpenWrite(targetPath))
|
||||||
{
|
{
|
||||||
// This is a bit dumb memory-wise, but we load the whole thing when running the game anyway
|
|
||||||
Log.Write("install", "Extracting {0} -> {1}".F(sourcePath, targetPath));
|
Log.Write("install", "Extracting {0} -> {1}".F(sourcePath, targetPath));
|
||||||
|
|
||||||
var displayFilename = Path.GetFileName(Path.GetFileName(targetPath));
|
var displayFilename = Path.GetFileName(Path.GetFileName(targetPath));
|
||||||
Action<int> onProgress = percent => updateMessage("Extracting {0} ({1}%)".F(displayFilename, percent));
|
Action<int> onProgress = percent => updateMessage("Extracting {0} ({1}%)".F(displayFilename, percent));
|
||||||
target.Write(reader.ExtractFile(node.Value.Value, onProgress));
|
reader.ExtractFile(node.Value.Value, target, onProgress);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user