Improve the handling of compressed files.

This commit is contained in:
Perfare 2021-11-19 17:54:06 +08:00
parent d08b78c2cf
commit 91410a33b1
5 changed files with 54 additions and 56 deletions

View File

@ -62,6 +62,11 @@ namespace AssetStudio
private void LoadFile(string fullName) private void LoadFile(string fullName)
{ {
var reader = new FileReader(fullName); var reader = new FileReader(fullName);
LoadFile(reader);
}
private void LoadFile(FileReader reader)
{
switch (reader.FileType) switch (reader.FileType)
{ {
case FileType.AssetsFile: case FileType.AssetsFile:
@ -73,6 +78,12 @@ namespace AssetStudio
case FileType.WebFile: case FileType.WebFile:
LoadWebFile(reader); LoadWebFile(reader);
break; break;
case FileType.GZipFile:
LoadFile(DecompressGZip(reader));
break;
case FileType.BrotliFile:
LoadFile(DecompressBrotli(reader));
break;
} }
} }

View File

@ -9,6 +9,9 @@ namespace AssetStudio
public string FileName; public string FileName;
public FileType FileType; public FileType FileType;
private static readonly byte[] gzipMagic = { 0x1f, 0x8b };
private static readonly byte[] brotliMagic = { 0x62, 0x72, 0x6F, 0x74, 0x6C, 0x69 };
public FileReader(string path) : this(path, File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { } public FileReader(string path) : this(path, File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { }
public FileReader(string path, Stream stream) : base(stream, EndianType.BigEndian) public FileReader(string path, Stream stream) : base(stream, EndianType.BigEndian)
@ -35,16 +38,16 @@ namespace AssetStudio
{ {
var magic = ReadBytes(2); var magic = ReadBytes(2);
Position = 0; Position = 0;
if (WebFile.gzipMagic.SequenceEqual(magic)) if (gzipMagic.SequenceEqual(magic))
{ {
return FileType.WebFile; return FileType.GZipFile;
} }
Position = 0x20; Position = 0x20;
magic = ReadBytes(6); magic = ReadBytes(6);
Position = 0; Position = 0;
if (WebFile.brotliMagic.SequenceEqual(magic)) if (brotliMagic.SequenceEqual(magic))
{ {
return FileType.WebFile; return FileType.BrotliFile;
} }
if (IsSerializedFile()) if (IsSerializedFile())
{ {

View File

@ -11,6 +11,8 @@ namespace AssetStudio
AssetsFile, AssetsFile,
BundleFile, BundleFile,
WebFile, WebFile,
ResourceFile ResourceFile,
GZipFile,
BrotliFile
} }
} }

View File

@ -1,5 +1,7 @@
using System.Collections.Generic; using Org.Brotli.Dec;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.IO.Compression;
using System.Linq; using System.Linq;
namespace AssetStudio namespace AssetStudio
@ -48,5 +50,33 @@ namespace AssetStudio
} }
return selectFile.Distinct().ToArray(); return selectFile.Distinct().ToArray();
} }
public static FileReader DecompressGZip(FileReader reader)
{
using (reader)
{
var stream = new MemoryStream();
using (var gs = new GZipStream(reader.BaseStream, CompressionMode.Decompress))
{
gs.CopyTo(stream);
}
stream.Position = 0;
return new FileReader(reader.FullPath, stream);
}
}
public static FileReader DecompressBrotli(FileReader reader)
{
using (reader)
{
var stream = new MemoryStream();
using (var brotliStream = new BrotliInputStream(reader.BaseStream))
{
brotliStream.CopyTo(stream);
}
stream.Position = 0;
return new FileReader(reader.FullPath, stream);
}
}
} }
} }

View File

@ -1,17 +1,11 @@
using System; using System.Collections.Generic;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text; using System.Text;
using Org.Brotli.Dec;
namespace AssetStudio namespace AssetStudio
{ {
public class WebFile public class WebFile
{ {
public static byte[] gzipMagic = { 0x1f, 0x8b };
public static byte[] brotliMagic = { 0x62, 0x72, 0x6F, 0x74, 0x6C, 0x69 };
public StreamFile[] fileList; public StreamFile[] fileList;
private class WebData private class WebData
@ -23,50 +17,8 @@ namespace AssetStudio
public WebFile(EndianBinaryReader reader) public WebFile(EndianBinaryReader reader)
{ {
var magic = reader.ReadBytes(2); reader.endian = EndianType.LittleEndian;
reader.Position = 0;
if (gzipMagic.SequenceEqual(magic))
{
var stream = new MemoryStream();
using (var gs = new GZipStream(reader.BaseStream, CompressionMode.Decompress))
{
gs.CopyTo(stream);
}
stream.Position = 0;
using (var binaryReader = new BinaryReader(stream))
{
ReadWebData(binaryReader);
}
}
else
{
reader.Position = 0x20;
magic = reader.ReadBytes(6);
reader.Position = 0;
if (brotliMagic.SequenceEqual(magic))
{
var brotliStream = new BrotliInputStream(reader.BaseStream);
var stream = new MemoryStream();
brotliStream.CopyTo(stream);
stream.Position = 0;
using (var binaryReader = new BinaryReader(stream))
{
ReadWebData(binaryReader);
}
}
else
{
reader.endian = EndianType.LittleEndian;
ReadWebData(reader);
}
}
}
private void ReadWebData(BinaryReader reader)
{
var signature = reader.ReadStringToNull(); var signature = reader.ReadStringToNull();
if (signature != "UnityWebData1.0")
return;
var headLength = reader.ReadInt32(); var headLength = reader.ReadInt32();
var dataList = new List<WebData>(); var dataList = new List<WebData>();
while (reader.BaseStream.Position < headLength) while (reader.BaseStream.Position < headLength)