将大文件读入字节数组并将其编码为 ToBase64String
Read large file into byte array and encode it to ToBase64String
我已经实现了 POC 以将整个文件内容读入 Byte[] 数组。我现在成功地读取了大小低于 100MB 的文件,当我加载大小超过 100MB 的文件时它抛出
Convert.ToBase64String(mybytearray) Cannot obtain value of the
local variable or argument because there is not enough memory
available.
下面是我尝试将内容从文件读取到字节数组的代码
var sFile = fileName;
var mybytearray = File.ReadAllBytes(sFile);
var binaryModel = new BinaryModel
{
fileName = binaryFile.FileName,
binaryData = Convert.ToBase64String(mybytearray),
filePath = string.Empty
};
我的模型class如下
public class BinaryModel
{
public string fileName { get; set; }
public string binaryData { get; set; }
public string filePath { get; set; }
}
我在 Convert.ToBase64String(mybytearray) 收到 "Convert.ToBase64String(mybytearray) Cannot obtain value of the local variable or argument because there is not enough memory available." 这个错误。
我需要注意什么以防止出现此错误吗?
注意:我不想在我的文件内容中添加换行符
为了节省内存,您可以将字节流转换为 3 包。在 Base64 中每三个字节产生 4 个字节。您不需要一次将整个文件存入内存。
这是伪代码:
Repeat
1. Try to read max 3 bytes from stream
2. Convert to base64, write to output stream
简单实现:
using (var inStream = File.OpenRead("E:\Temp\File.xml"))
using (var outStream = File.CreateText("E:\Temp\File.base64"))
{
var buffer = new byte[3];
int read;
while ((read = inStream.Read(buffer, 0, 3)) > 0)
{
var base64 = Convert.ToBase64String(buffer, 0, read);
outStream.Write(base64);
}
}
提示:每次乘以 3 都是有效的。更高 - 更多内存,更好的性能,更低 - 更少的内存,更差的性能。
附加信息:
文件流就是一个例子。结果流使用 [HttpContext].Response.OutputStream
并直接写入它。在一个块中处理数百兆字节会杀死您和您的服务器。
考虑总内存需求。 100MB 的字符串,导致 133MB 的字节数组,因为你写了关于模型我期望这个 133MB 的副本作为响应。请记住,这只是一个简单的请求。一些这样的请求可能会耗尽您的记忆。
我会使用两个文件流 - 一个用于读取大文件,一个用于写回结果。
因此,在块中,您将转换为 base 64 ...然后将结果字符串转换为字节 ...然后写入。
private static void ConvertLargeFileToBase64()
{
var buffer = new byte[16 * 1024];
using (var fsIn = new FileStream("D:\in.txt", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
using (var fsOut = new FileStream("D:\out.txt", FileMode.CreateNew, FileAccess.Write))
{
int read;
while ((read = fsIn.Read(buffer, 0, buffer.Length)) > 0)
{
// convert to base 64 and convert to bytes for writing back to file
var b64 = Encoding.ASCII.GetBytes(Convert.ToBase64String(buffer));
// write to the output filestream
fsOut.Write(b64, 0, read);
}
fsOut.Close();
}
}
}
我已经实现了 POC 以将整个文件内容读入 Byte[] 数组。我现在成功地读取了大小低于 100MB 的文件,当我加载大小超过 100MB 的文件时它抛出
Convert.ToBase64String(mybytearray) Cannot obtain value of the local variable or argument because there is not enough memory available.
下面是我尝试将内容从文件读取到字节数组的代码
var sFile = fileName;
var mybytearray = File.ReadAllBytes(sFile);
var binaryModel = new BinaryModel
{
fileName = binaryFile.FileName,
binaryData = Convert.ToBase64String(mybytearray),
filePath = string.Empty
};
我的模型class如下
public class BinaryModel
{
public string fileName { get; set; }
public string binaryData { get; set; }
public string filePath { get; set; }
}
我在 Convert.ToBase64String(mybytearray) 收到 "Convert.ToBase64String(mybytearray) Cannot obtain value of the local variable or argument because there is not enough memory available." 这个错误。
我需要注意什么以防止出现此错误吗?
注意:我不想在我的文件内容中添加换行符
为了节省内存,您可以将字节流转换为 3 包。在 Base64 中每三个字节产生 4 个字节。您不需要一次将整个文件存入内存。
这是伪代码:
Repeat
1. Try to read max 3 bytes from stream
2. Convert to base64, write to output stream
简单实现:
using (var inStream = File.OpenRead("E:\Temp\File.xml"))
using (var outStream = File.CreateText("E:\Temp\File.base64"))
{
var buffer = new byte[3];
int read;
while ((read = inStream.Read(buffer, 0, 3)) > 0)
{
var base64 = Convert.ToBase64String(buffer, 0, read);
outStream.Write(base64);
}
}
提示:每次乘以 3 都是有效的。更高 - 更多内存,更好的性能,更低 - 更少的内存,更差的性能。
附加信息:
文件流就是一个例子。结果流使用 [HttpContext].Response.OutputStream
并直接写入它。在一个块中处理数百兆字节会杀死您和您的服务器。
考虑总内存需求。 100MB 的字符串,导致 133MB 的字节数组,因为你写了关于模型我期望这个 133MB 的副本作为响应。请记住,这只是一个简单的请求。一些这样的请求可能会耗尽您的记忆。
我会使用两个文件流 - 一个用于读取大文件,一个用于写回结果。
因此,在块中,您将转换为 base 64 ...然后将结果字符串转换为字节 ...然后写入。
private static void ConvertLargeFileToBase64()
{
var buffer = new byte[16 * 1024];
using (var fsIn = new FileStream("D:\in.txt", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
using (var fsOut = new FileStream("D:\out.txt", FileMode.CreateNew, FileAccess.Write))
{
int read;
while ((read = fsIn.Read(buffer, 0, buffer.Length)) > 0)
{
// convert to base 64 and convert to bytes for writing back to file
var b64 = Encoding.ASCII.GetBytes(Convert.ToBase64String(buffer));
// write to the output filestream
fsOut.Write(b64, 0, read);
}
fsOut.Close();
}
}
}