【发布时间】:2018-07-26 21:41:31
【问题描述】:
我正在尝试使用以下方法将 zip 文件转换为文本文件 (xml)。它适用于较小的文件,但似乎不适用于大于 50 mb 的文件。
class Program
{
public static void Main(string[] args)
{
try
{
string importFilePath = @"D:\CorpTax\Tasks\966442\CS Publish error\CSUPD20180604L.zip";
int maxLengthInMb = 20;
byte[] payLoad = File.ReadAllBytes(importFilePath);
int payLoadInMb = (payLoad.Length / 1024) / 1024;
bool splitIntoMultipleFiles = (payLoadInMb / maxLengthInMb) > 1;
int payLoadLength = splitIntoMultipleFiles ? maxLengthInMb * 1024 * 1024 : payLoad.Length;
if (splitIntoMultipleFiles)
{
foreach (byte[] splitPayLoad in payLoad.Slices(payLoadLength))
{
ToXml(payLoad);
}
}
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
public static string ToXml(byte[] payLoad)
{
using (XmlStringWriter xmlStringWriter = new XmlStringWriter())
{
xmlStringWriter.WriteStartDocument();
xmlStringWriter.Writer.WriteStartElement("Payload");
xmlStringWriter.Writer.WriteRaw(Convert.ToBase64String(payLoad));
xmlStringWriter.Writer.WriteEndElement();
xmlStringWriter.WriteEndDocument();
return xmlStringWriter.ToString();
}
}
}
我有一个 120 MB 大小的 .zip 文件,我得到了
System.OutOfMemoryException 调用 Convert.ToBase64String() 时。
所以我继续将字节数组拆分为 20 mb 大小的块,希望它不会失败。但是我看到它一直有效,直到它通过循环 3 次,即能够转换 60mb 的数据,并且在第 4 次迭代中我得到了同样的异常。有时我也会在 return xmlStringWriter.ToString()
行遇到异常为了拆分字节[],我使用了以下扩展类
public static class ArrayExtensions
{
public static T[] CopySlice<T>(this T[] source, int index, int length, bool padToLength = false)
{
int n = length;
T[] slice = null;
if (source.Length < index + length)
{
n = source.Length - index;
if (padToLength)
{
slice = new T[length];
}
}
if (slice == null) slice = new T[n];
Array.Copy(source, index, slice, 0, n);
return slice;
}
public static IEnumerable<T[]> Slices<T>(this T[] source, int count, bool padToLength = false)
{
for (var i = 0; i < source.Length; i += count)
{
yield return source.CopySlice(i, count, padToLength);
}
}
}
我从以下链接获得了上面的代码 Splitting a byte[] into multiple byte[] arrays in C#
有趣的是,当我在控制台应用程序中运行程序时,程序运行良好,但是当我将此代码放入 Windows 应用程序时,它会抛出 System.OutOfMemoryException。
【问题讨论】:
-
您应该使用
Stream而不是byte[]。 -
Project > Properties > Build 选项卡,取消勾选“Prefer 32-bit”复选框。你不喜欢它。
-
请注意,尝试计算切片的 Base64 不会给出相同的结果。甚至没有接近:dotnetfiddle.net/IUtlzH
-
一般来说,尝试一次操作内存中如此大量的数据是个坏主意。字符串构建器、xml 构建器等不是为这种情况设计的。我的建议是找到或实现一个 streaming 构建器,它可以直接转储到磁盘,而不是在内存中构建如此庞大的结构。
-
这也是一种反模式。此时不将 zip 文件放在 xml 中似乎更好。