using UnityEngine;
using System;
using System.IO;
using System.Text;
using System.IO.Compression;
using System.Security;
using System.Security.Cryptography;
using System.Diagnostics;
public class CompressTool
{
private static CompressTool instance = null;
//加密所用的key,必须为32位
byte[] keyArray = UTF8Encoding.UTF8.GetBytes("01234567890123456789012345678901");
public static CompressTool GetInstance()
{
if (instance == null)
instance = new CompressTool();
return instance;
}
/// <summary>
/// 将源流中的全部内容复制到目标流
/// </summary>
/// <param name="desStream">目标流</param>
/// <param name="srcStream">源流</param>
/// <param name="blockSize">复制的循环中每次读取的长度,默认1024</param>
void CopyStream(Stream desStream, Stream srcStream, int blockSize = 1024)
{
byte[] content = new byte[blockSize];
int readSize;
while ((readSize = srcStream.Read(content, 0, blockSize)) > 0)
{
desStream.Write(content, 0, readSize);
}
}
/// <summary>
/// 将源流中当前位置起,指定长度的内容复制到目标流
/// </summary>
/// <param name="desStream">目标流</param>
/// <param name="srcStream">源流</param>
/// <param name="totalSize">复制长度,默认为-1,表示复制全部</param>
/// <param name="blockSize">复制的循环中每次读取的长度,默认1024</param>
void CopyStreamPartly(Stream desStream, Stream srcStream, long totalSize = -1, int blockSize = 1024)
{
if (totalSize < 0)
return;
if (-1 == totalSize)
{
CopyStream(desStream, srcStream, blockSize);
return;
}
byte[] content = new byte[blockSize];
int readSize;
if (totalSize <= blockSize)
{
readSize = srcStream.Read(content, 0, Convert.ToInt32(totalSize));
desStream.Write(content, 0, readSize);
return;
}
int contentByte = srcStream.ReadByte();
for (long i = 0; i < totalSize && contentByte != -1; i++)
{
desStream.WriteByte((byte)contentByte);
contentByte = srcStream.ReadByte();
}
}
/// <summary>
/// 从文件的全路径中获取文件名
/// </summary>
/// <returns>文件名</returns>
/// <param name="fullPath">文件全路径</param>
/// <param name="isFullName">返回的文件名中是否包含扩展名<c>true</c>包含扩展名</param>
string GetFileName(string fullPath, bool isFullName = false)
{
string result = fullPath.Substring(fullPath.LastIndexOf("/") + 1);
if (!isFullName)
result = result.Substring(0, (result.LastIndexOf(".")));
return result;
}
/// <summary>
/// 从文件的全路径中获取扩展名
/// </summary>
/// <returns>文件的扩展名</returns>
/// <param name="fullPath">文件全路径</param>
string GetExtentName(string fullPath)
{
return fullPath.Substring(fullPath.LastIndexOf(".") + 1);
}
/// <summary>
/// 将一个long型值写入流
/// </summary>
/// <param name="stream">待写入的流</param>
/// <param name="value">需要写入的long型值</param>
void WriteValueToStream(Stream stream, long value)
{
byte[] contentLenBytes = BitConverter.GetBytes(value);
stream.Write(contentLenBytes, 0, contentLenBytes.Length);
}
/// <summary>
/// 将一个int型值写入流
/// </summary>
/// <param name="stream">待写入的流</param>
/// <param name="value">需要写入的int型值</param>
void WriteValueToStream(Stream stream, int value)
{
byte[] contentLenBytes = BitConverter.GetBytes(value);
stream.Write(contentLenBytes, 0, contentLenBytes.Length);
}
/// <summary>
/// 将一个字符串写入流
/// </summary>
/// <param name="stream">待写入的流</param>
/// <param name="value">需要写入的字符串</param>
void WriteValueToStream(Stream stream, string value)
{
for (int i = 0; i < value.Length; i++)
{
byte[] contentLenBytes = BitConverter.GetBytes(value[i]);
stream.Write(contentLenBytes, 0, contentLenBytes.Length);
}
}
/// <summary>
/// 从流中读取一个long型值
/// </summary>
/// <returns>读取的long型值</returns>
/// <param name="stream">待读取的流</param>
long ReadLongFromStream(Stream stream)
{
int readLength = sizeof(long);
byte[] lengthBytes = new byte[readLength];
stream.Read(lengthBytes, 0, readLength);
return BitConverter.ToInt64(lengthBytes, 0);
}
/// <summary>
/// 从流中读取一个int型值
/// </summary>
/// <returns>读取的int型值</returns>
/// <param name="stream">待读取的流</param>
int ReadIntFromStream(Stream stream)
{
int readLength = sizeof(int);
byte[] lengthBytes = new byte[readLength];
stream.Read(lengthBytes, 0, readLength);
return BitConverter.ToInt32(lengthBytes, 0);
}
/// <summary>
/// 从流中读取一个字符串
/// </summary>
/// <returns>读取的字符串</returns>
/// <param name="stream">待读取的流</param>
/// <param name="length">字符串长度</param>
string ReadStringFromStream(Stream stream, int length)
{
StringBuilder result = new StringBuilder();
int readLength = sizeof(char) * length;
byte[] charBytes = new byte[readLength];
stream.Read(charBytes, 0, readLength);
for (int i = 0; i < length; i++)
result.Append(BitConverter.ToChar(charBytes, sizeof(char) * i));
return result.ToString();
}
/// <summary>
/// 添加压缩信息(文件名长度、文件名、文件压缩后长度)
/// </summary>
/// <param name="resultStream">输出结果流</param>
/// <param name="fileName">文件名</param>
/// <param name="compressStream">文件压缩后长度</param>
void WriteCompressInfo(Stream resultStream, string filePath, long compressLength)
{
string fileName = GetFileName(filePath, true);
//写入文件名长度(4bytes)
WriteValueToStream(resultStream, fileName.Length);
//写入文件名
WriteValueToStream(resultStream, fileName);
//写入压缩后的文件长度(8bytes)
WriteValueToStream(resultStream, compressLength);
// GLogger.Log("hyw test WriteCompressInfo name" + fileName + " name length" + fileName.Length + " compresslength" + compressLength);
}
/// <summary>
/// 从流中读取压缩信息(文件名长度、文件名、文件压缩后长度)
/// </summary>
/// <param name="input">输入的压缩流</param>
/// <param name="fileName">文件名</param>
/// <param name="compressLength">文件压缩后长度</param>
void ReadCompressInfo(Stream input, out string fileName, out long compressLength)
{
//读取文件名的长度(4bytes)
int fileNameLength = ReadIntFromStream(input);
//读取文件名
fileName = ReadStringFromStream(input, fileNameLength);
// GLogger.Log("hyw test write fileName " + fileName);
//文件压缩后长度(8bytes)
compressLength = ReadLongFromStream(input);
// GLogger.Log("hyw test compressLength " + compressLength);
}
/// <summary>
/// 通过7zip,压缩指定文件,并在压缩流之前添加文件信息(文件名长度,文件名,文件压缩后长度)
/// </summary>
/// <param name="fullPath">待压缩文件的路径</param>
/// <param name="output">压缩后的流</param>
void CompressFile7Zip(string fullPath, Stream output)
{
FileStream input = new FileStream(fullPath, FileMode.Open);
MemoryStream tempStream = new MemoryStream();
SevenZip.Compression.LZMA.Encoder coder = new SevenZip.Compression.LZMA.Encoder();
//压缩原始文件
//写入5byte的属性
coder.WriteCoderProperties(tempStream);
//写入8byte的原始文件长度
WriteValueToStream(tempStream, input.Length);
//压缩
coder.Code(input, tempStream, input.Length, -1, null);
//在压缩文件前添加压缩信息(文件名长度、文件名、文件压缩后长度)
string fileName = GetFileName(fullPath, true);
WriteCompressInfo(output, fileName, tempStream.Length);
//写入压缩内容
byte[] content = tempStream.GetBuffer();
for (long i = 0; i < content.Length; i++)
output.WriteByte(content[i]);
tempStream.Close();
input.Close();
}
/// <summary>
/// 通过7zip压缩,从指定流中解压文件,写入指定路径
/// </summary>
/// <param name="string">解压后文件存储路径</param>
/// <param name="input">压缩文件所在流</param>
void DecompressFile7Zip(string path, Stream input)
{
MemoryStream tempStream = new MemoryStream();
SevenZip.Compression.LZMA.Decoder coder = new SevenZip.Compression.LZMA.Decoder();
string fileName = "";
long compressLength = 0;
//读取文件的压缩信息(文件名长度、文件名、文件压缩后长度)
ReadCompressInfo(input, out fileName, out compressLength);
FileStream output = new FileStream(path + fileName, FileMode.Create);
//读取压缩后文件的内容
for (long i = 0; i < compressLength; i++)
tempStream.WriteByte((byte)input.ReadByte());
tempStream.Seek(0, SeekOrigin.Begin);
//读取5byte的属性
byte[] properties = new byte[5];
tempStream.Read(properties, 0, 5);
//读取8byte的原始文件长度
long originalLength = ReadLongFromStream(tempStream);
// GLogger.Log("hyw test originalLength " + originalLength);
//解压
coder.SetDecoderProperties(properties);
coder.Code(tempStream, output, compressLength, originalLength, null);
tempStream.Close();
output.Flush();
output.Close();
}
/// <summary>
/// 通过7Zip压缩单个文件
/// </summary>
/// <param name="inputFilePath">待压缩文件路径</param>
/// <param name="outputFilePath">压缩后文件的保存路径</param>
public void CompressSingleFile7Zip(string inputFilePath, string outputFilePath)
{
if (!File.Exists(inputFilePath))
{
GLogger.LogError("未找到待压缩文件!" + inputFilePath);
return;
}
GLogger.Log("hyw test sourece " + inputFilePath);
GLogger.Log("hyw test outputPath " + outputFilePath);
FileStream output = new FileStream(outputFilePath, FileMode.Create);
CompressFile7Zip(inputFilePath, output);
output.Flush();
output.Close();
GLogger.Log("CompressSingleFile7Zip success");
}
/// <summary>
/// 通过7Zip解压单个文件
/// </summary>
/// <param name="inputFilePath">待解压件路径</param>
/// <param name="outputDirPath">解压后文件的保存目录</param>
public void DecompressSingleFile7Zip(string inputFilePath, string outputDirPath)
{
if (!File.Exists(inputFilePath))
{
GLogger.LogError("未找待解缩文件!" + inputFilePath);
return;
}
GLogger.Log("hyw test sourece " + inputFilePath);
GLogger.Log("hyw test outputPath " + outputDirPath);
FileStream input = new FileStream(inputFilePath, FileMode.Open);
DecompressFile7Zip(outputDirPath, input);
input.Flush();
input.Close();
GLogger.Log("DecompressSingleFile7Zip success");
}
/// <summary>
/// 通过7Zip将目录中指定扩展名的所有文件压缩到一个文件
/// </summary>
/// <param name="inputDirPath">待压缩文件所在目录</param>
/// <param name="outputFilePath">压缩后文件的保存路径</param>
/// <param name="extendName">待压缩文件的扩展名(默认为空,不筛选)</param>
public void CompressFiles7Zip(string inputDirPath, string outputFilePath, string extendName)
{
if (!Directory.Exists(inputDirPath))
{
GLogger.LogError("未找待压缩文件目录! " + inputDirPath);
return;
}
string[] files = Directory.GetFiles(inputDirPath);
FileStream output = new FileStream(outputFilePath, FileMode.Create);
for (int i = 0; i < files.Length; i++)
{
if (extendName != "" && GetExtentName(files[i]) != extendName)
continue;
GLogger.Log("hyw test files[i]" + files[i]);
CompressFile7Zip(files[i], output);
}
GLogger.Log("all content length" + output.Length);
output.Flush();
output.Close();
}
/// <summary>
/// 通过7Zip将压缩文件解压到指定目录中
/// </summary>
/// <param name="inputFilePath">待解压文件路径</param>
/// <param name="outputDirPath">解压后文件的保存目录</param>
public void DecompressFiles7Zip(string inputFilePath, string outputDirPath)
{
if (!File.Exists(inputFilePath))
{
GLogger.LogError("未找待解压文件!" + inputFilePath);
return;
}
if (!Directory.Exists(outputDirPath))
Directory.CreateDirectory(outputDirPath);
FileStream input = new FileStream(inputFilePath, FileMode.Open);
while (input.Position < input.Length)
{
// GLogger.Log("hyw test input.Position" + input.Position + " input.Length" + input.Length);
DecompressFile7Zip(outputDirPath, input);
//去掉压缩文件末尾填充的0
while (0 == input.ReadByte())
{
// GLogger.Log("hyw test zero byte");
}
if (input.Position < input.Length)
input.Seek(-1, SeekOrigin.Current);
}
input.Flush();
input.Close();
}
/// <summary>
/// 准备加密所需的信息
/// </summary>
/// <returns>加密所需信息</returns>
/// <param name="keyArray">密钥</param>
RijndaelManaged PrepareCodeInfo(byte[] keyArray)
{
RijndaelManaged rDel = new RijndaelManaged();
rDel.Key = keyArray;
rDel.Mode = CipherMode.ECB;
rDel.Padding = PaddingMode.PKCS7;
return rDel;
}
/// <summary>
/// 将文件读取为byte
/// </summary>
/// <returns>保存文件内容的byte数组</returns>
/// <param name="filePath">文件路径</param>
/// <param name="readSize">读取文件循环中每次读取的文件长度(默认为1024)</param>
byte[] ReadFileToBytes(string filePath, int readSize = 1024)
{
FileStream input = new FileStream(filePath, FileMode.Open);
long leftLength = input.Length;
int currentPos = 0;
byte[] readContent = new byte[leftLength];
while (leftLength / readSize > 0)
{
input.Read(readContent, currentPos, readSize);
leftLength -= readSize;
currentPos += readSize;
}
if (leftLength > 0)
{
input.Read(readContent, currentPos, Convert.ToInt32(leftLength));
}
input.Close();
return readContent;
}
string ReadFileToString(string filePath, int readSize = 1024)
{
FileStream input = new FileStream(filePath, FileMode.Open);
StreamReader sr = new StreamReader(input);
StringBuilder sb = new StringBuilder();
string line;
while ((line = sr.ReadLine()) != null)
sb.Append(line);
sr.Close();
input.Close();
return sb.ToString();
}
/// <summary>
/// 加密单个文件
/// </summary>
/// <param name="inputFilePath">待加密文件路径</param>
/// <param name="outputFilePath">加密后文件的保存路径</param>
public void EncodeSingleFile(string inputFilePath, string outputFilePath)
{
if (!File.Exists(inputFilePath))
{
GLogger.LogError("未找待加密文件!");
return;
}
GLogger.Log("hyw test dbSourcePath " + inputFilePath);
GLogger.Log("hyw test outputPath " + outputFilePath);
ICryptoTransform cTransform = PrepareCodeInfo(keyArray).CreateEncryptor();
byte[] toEncryptArray = ReadFileToBytes(inputFilePath);
// byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(ReadFileToString(inputFilePath));
byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
FileStream output = new FileStream(outputFilePath, FileMode.Create);
output.Write(resultArray, 0, resultArray.Length);
output.Flush();
output.Close();
}
/// <summary>
/// 解密单个文件
/// </summary>
/// <param name="inputFilePath">待解密文件路径</param>
/// <param name="outputFilePath">解密后文件保存路径</param>
public void DecodeSingleFile(string inputFilePath, string outputFilePath)
{
if (!File.Exists(inputFilePath))
{
GLogger.LogError("未找待解密文件!");
return;
}
GLogger.Log("hyw test dbSourcePath " + inputFilePath);
GLogger.Log("hyw test outputPath " + outputFilePath);
ICryptoTransform cTransform = PrepareCodeInfo(keyArray).CreateDecryptor();
byte[] toDecryptArray = ReadFileToBytes(inputFilePath);
// byte[] toDecryptArray = Convert.FromBase64String(ReadFileToString(inputFilePath));
byte[] resultArray = cTransform.TransformFinalBlock(toDecryptArray, 0, toDecryptArray.Length);
FileStream output = new FileStream(outputFilePath, FileMode.Create);
output.Write(resultArray, 0, resultArray.Length);
output.Flush();
output.Close();
}
/// <summary>
/// 加密目录中指定扩展名的所有文件
/// </summary>
/// <param name="inputDirPath">待加密的目录</param>
/// <param name="outputDirPath">加密后文件的保存目录</param>
/// <param name="extendName">待加密文件扩展名(默认为空,不筛选)</param>
public void EncodeFiles(string inputDirPath, string outputDirPath, string extendName = "")
{
if (!Directory.Exists(inputDirPath))
{
GLogger.LogError("未找待加密文件目录!");
return;
}
GLogger.Log (outputDirPath);
if (!Directory.Exists(outputDirPath))
Directory.CreateDirectory(outputDirPath);
string[] files = Directory.GetFiles(inputDirPath);
for (int i = 0; i < files.Length; i++)
{
if (extendName == "" || GetExtentName(files[i]) == extendName)
EncodeSingleFile(files[i], outputDirPath + GetFileName(files[i], true));
}
}
/// <summary>
/// 解密目录中指定扩展名的所有文件
/// </summary>
/// <param name="inputDirPath">待解密文件目录</param>
/// <param name="outputDirPath">解密后文件的保存目录</param>
/// <param name="extendName">待解密文件扩展名(默认为空,不筛选)</param>
public void DecodeFiles(string inputDirPath, string outputDirPath, string extendName = "")
{
if (!Directory.Exists(inputDirPath))
{
GLogger.LogError("未找待解密文件目录!");
return;
}
if (!Directory.Exists(outputDirPath))
Directory.CreateDirectory(outputDirPath);
string[] files = Directory.GetFiles(inputDirPath);
for (int i = 0; i < files.Length; i++)
{
if (extendName == "" || GetExtentName(files[i]) == extendName)
DecodeSingleFile(files[i], outputDirPath + GetFileName(files[i], true));
}
}
/// <summary>
/// 通过Gzip,压缩指定文件,并在压缩流之前添加文件信息(文件名长度,文件名,文件压缩后长度)
/// </summary>
/// <param name="fullPath">待压缩文件名</param>
/// <param name="output">添加了压缩信息的压缩流</param>
void CompressFileGZip(string fullPath, Stream output)
{
// GLogger.Log("hyw test CompressGZip " + fileName);
FileStream originalFileStream = new FileStream(fullPath, FileMode.Open);
// using (FileStream compressedFileStream = File.Create(fileName + ".gz"))
// {
// using (GZipStream compressionStream = new GZipStream(compressedFileStream, CompressionMode.Compress))
// {
// // originalFileStream.CopyTo(compressionStream);
// byte[] fileContent = new byte[originalFileStream.Length];
// originalFileStream.Read(fileContent, 0, fileContent.Length);
// compressionStream.Write(fileContent, 0, fileContent.Length);
//// CopyStream(compressionStream, originalFileStream);
// GLogger.Log(string.Format("Compressed {0} from {1} to {2} bytes.",
// fileName, originalFileStream.Length.ToString(), compressedFileStream.Length.ToString()));
// GLogger.Log(compressionStream.Position);
// }
// }
MemoryStream compressStream = new MemoryStream();
GZipStream gZipStream = new GZipStream(compressStream, CompressionMode.Compress);
CopyStream(originalFileStream, gZipStream);
long currentLength = compressStream.Position;
//写入压缩信息
WriteCompressInfo(output, GetFileName(fullPath, true), currentLength);
GLogger.Log("hyw test compressStream" + compressStream.Length + compressStream.Position);
compressStream.Seek(0, SeekOrigin.Begin);
CopyStream(output, compressStream);
gZipStream.Close();
compressStream.Close();
originalFileStream.Close();
}
/// <summary>
/// 通过Gzip压缩,从指定流中解压文件,写入指定路径
/// </summary>
/// <param name="string">解压后文件存储路径</param>
/// <param name="input">压缩文件所在流</param>
void DecompressFileGZip(string path, Stream input)
{
string fileName = "";
long compressLength = 0;
//读取文件的压缩信息(文件名长度、文件名、文件压缩后长度)
ReadCompressInfo(input, out fileName, out compressLength);
MemoryStream tempStream = new MemoryStream();
FileStream output = new FileStream(path + fileName, FileMode.Create);
//读取压缩后文件的内容
for (long i = 0; i < compressLength; i++)
tempStream.WriteByte((byte)input.ReadByte());
tempStream.Seek(0, SeekOrigin.Begin);
GZipStream gZipStream = new GZipStream(tempStream, CompressionMode.Compress);
CopyStream(gZipStream, tempStream);
tempStream.Close();
output.Flush();
output.Close();
}
public void CompressSingleFileGZip(string inputFilePath, string outputFilePath)
{
if (!File.Exists(inputFilePath))
{
GLogger.LogError("未找到待压缩文件!" + inputFilePath);
return;
}
GLogger.Log("hyw test sourece " + inputFilePath);
GLogger.Log("hyw test outputPath " + outputFilePath);
FileStream output = new FileStream(outputFilePath, FileMode.Create);
CompressFileGZip(inputFilePath, output);
output.Flush();
output.Close();
GLogger.Log("CompressSingleFileGZip success");
}
/// <summary>
/// 通过GZip,压缩指定文件夹中的指定扩展名的文件,成为一个.gz
/// </summary>
/// <param name="DirPath">文件夹路径</param>
/// <param name="compressPath">压缩后的文件路径</param>
/// <param name="extendName">指定扩展名</param>
public void CompressFilesGZip(string DirPath, string extendName, string compressPath)
{
GLogger.Log("hyw test compressPath" + compressPath);
FileStream resultStream = new FileStream(compressPath, FileMode.Create);
string[] files = Directory.GetFiles(DirPath);
for (int i = 0; i < files.Length; i++)
{
if (0 != extendName.CompareTo(GetExtentName(files[i])))
continue;
if (!File.Exists(files[i]))
{
GLogger.LogError("no such file");
return;
}
CompressFileGZip(files[i], resultStream);
}
resultStream.Flush();
resultStream.Close();
}
/// <summary>
/// 通过GZip解压文件
/// </summary>
/// <param name="compressStream">压缩流</param>
/// <param name="fileName">文件名</param>
/// <param name="compressLength">原文件压缩后的长度</param>
void DecompressGZip(Stream compressStream, string DirPath)
{
string fileName;
long compressLength;
ReadCompressInfo(compressStream, out fileName, out compressLength);
MemoryStream tempStream = new MemoryStream();
CopyStreamPartly(tempStream, compressStream, compressLength);
FileStream resultStream = new FileStream(DirPath + fileName, FileMode.Create);
GZipStream gZipStream = new GZipStream(tempStream, CompressionMode.Decompress);
CopyStreamPartly(resultStream, gZipStream, compressLength);
gZipStream.Close();
tempStream.Close();
resultStream.Flush();
resultStream.Close();
}
/// <summary>
/// 通过GZip,从指定压缩文件中解压出多个文件
/// </summary>
/// <param name="DirPath">解压文件保存路径</param>
/// <param name="compressPath">压缩文件路径</param>
public void DecompressFilesGZip(string DirPath, string compressPath)
{
Stopwatch st = new Stopwatch ();
st.Start ();
if (!File.Exists(compressPath))
{
GLogger.LogError("no such file");
return;
}
if (!Directory.Exists(DirPath))
Directory.CreateDirectory(DirPath);
FileStream compressStream = new FileStream(compressPath, FileMode.Open);
while (compressStream.Position < compressStream.Length)
{
// GLogger.Log("hyw test input.Position" + compressStream.Position + " input.Length" + compressStream.Length);
DecompressGZip(compressStream, DirPath);
}
compressStream.Flush();
compressStream.Close();
st.Stop ();
GLogger.Log ("wm===="+st.Elapsed);
}
}
解压缩
最新推荐文章于 2021-02-12 20:31:06 发布