使用 c# 将 FileStream 编码为 base64
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19134062/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Encode a FileStream to base64 with c#
提问by feedwall
I know how to encode / decode a simple string to / from base64.
我知道如何将一个简单的字符串编码/解码为base64。
But how would I do that if the data is already been written to a FileStreamobject. Let's say I have only access to the FileStream object not to the previously stored original data in it. How would I encode a FileStream to base64before I flush the FileStream to a file.
但是,如果数据已经写入FileStream对象,我该怎么做。假设我只能访问 FileStream 对象,而不能访问以前存储在其中的原始数据。在将FileStream刷新到文件之前,我将如何将FileStream编码为 base64。
Ofc I could just open my file and encode / decode it after I have written the FileStream to the file, but I would like to do this all in one single step without doing two file operations one after another. The file could be larger and it would also take double time to load, encode and save it again after it was just saved a short time before.
Ofc 在我将 FileStream 写入文件后,我可以打开我的文件并对其进行编码/解码,但我想一步完成这一切,而不是一个接一个地执行两个文件操作。文件可能会更大,而且在之前刚刚保存了很短的时间后,加载、编码和再次保存它也需要双倍的时间。
Maybe someone of you knows a better solution? Can I convert the FileStream to a string, encode the string and then convert the string back to a FileStream for example or what would I do and how would such a code look like?
也许你们中有人知道更好的解决方案?例如,我可以将 FileStream 转换为字符串,对字符串进行编码,然后将字符串转换回 FileStream,或者我会做什么以及这样的代码是什么样的?
采纳答案by alpham8
You can also encode bytes to Base64. How to get this from a stream see here: How to convert an Stream into a byte[] in C#?
您还可以将字节编码为 Base64。如何从流中获取它,请参见此处:How to convert an Stream into a byte[] in C#?
Or I think it should be also possible to use the .ToString() method and encode this.
或者我认为也应该可以使用 .ToString() 方法并对其进行编码。
回答by David Heffernan
Since the file will be larger, you don't have very much choice in how to do this. You cannot process the file in place since that will destroy the information you need to use. You have two options that I can see:
由于文件会更大,因此您在如何执行此操作方面没有太多选择。您无法就地处理文件,因为这会破坏您需要使用的信息。我可以看到您有两个选项:
- Read in the entire file, base64 encode, re-write the encoded data.
- Read the file in smaller pieces, encoding as you go along. Encode to a temporary file in the same directory. When you are finished, delete the original file, and rename the temporary file.
- 读入整个文件,base64编码,重新写入编码后的数据。
- 以较小的部分读取文件,并在进行过程中进行编码。编码到同一目录中的临时文件。完成后,删除原始文件,并重命名临时文件。
Of course, the whole point of streams is to avoid this sort of scenario. Instead of creating the content and stuffing it into a file stream, stuff it into a memory stream. Then encode that and only then save to disk.
当然,流的全部意义在于避免这种情况。不是创建内容并将其填充到文件流中,而是将其填充到内存流中。然后对其进行编码,然后才保存到磁盘。
回答by Jacob
You may try something likethat:
您可以尝试一些类似的是:
public Stream ConvertToBase64(Stream stream)
{
Byte[] inArray = new Byte[(int)stream.Length];
Char[] outArray = new Char[(int)(stream.Length * 1.34)];
stream.Read(inArray, 0, (int)stream.Length);
Convert.ToBase64CharArray(inArray, 0, inArray.Length, outArray, 0);
return new MemoryStream(Encoding.UTF8.GetBytes(outArray));
}
回答by chris31389
An easy one as an extension method
一种简单的扩展方法
public static class Extensions
{
public static Stream ConvertToBase64(this Stream stream)
{
byte[] bytes;
using (var memoryStream = new MemoryStream())
{
stream.CopyTo(memoryStream);
bytes = memoryStream.ToArray();
}
string base64 = Convert.ToBase64String(bytes);
return new MemoryStream(Encoding.UTF8.GetBytes(base64));
}
}
回答by Dai
When dealing with large streams, like a file sized over 4GB - you don't want to load the file into memory (as a Byte[]
) because not only is it very slow, but also may cause a crash as even in 64-bit processes a Byte[]
cannot exceed 2GB (or 4GB with gcAllowVeryLargeObjects
).
处理大流时,例如大小超过 4GB 的文件 - 您不想将文件加载到内存中(作为Byte[]
),因为它不仅速度非常慢,而且可能导致崩溃,因为即使在 64 位进程中Byte[]
不能超过 2GB(或 4GB,带gcAllowVeryLargeObjects
)。
Fortunately there's a neat helper in .NET called ToBase64Transform
which processes a stream in chunks. For some reason Microsoft put it in System.Security.Cryptography
and it implements ICryptoTransform
(for use with CryptoStream
), but disregard that ("a rose by any other name...") just because you aren't performing any cryprographic tasks.
幸运的是,.NET 中有一个巧妙的帮助程序ToBase64Transform
,它可以分块处理流。出于某种原因,微软将它放入System.Security.Cryptography
并实现ICryptoTransform
(用于CryptoStream
),但忽略它(“任何其他名称的玫瑰......”),因为您没有执行任何加密任务。
You use it with CryptoStream
like so:
你CryptoStream
像这样使用它:
using System.Security.Cryptography;
using System.IO;
//
using( FileStream inputFile = new FileStream( @"C:\VeryLargeFile.bin", FileMode.Open, FileAccess.Read ) )
using( CryptoStream base64Stream = new CryptoStream( inputFile, new ToBase64Transform(), CryptoStreamMode.Read ) )
using( FileStream outputFile = new FileStream( @"C:\VeryLargeBase64File.txt", FileMode.CreateNew, FileAccess.Write ) )
{
await base64Stream.CopyToAsync( outputFile ).ConfigureAwait(false);
}
回答by Vasil Popov
A simple Stream extension method would do the job:
一个简单的 Stream 扩展方法可以完成这项工作:
public static class StreamExtensions
{
public static string ConvertToBase64(this Stream stream)
{
var bytes = new Byte[(int)stream.Length];
stream.Seek(0, SeekOrigin.Begin);
stream.Read(bytes, 0, (int)stream.Length);
return Convert.ToBase64String(bytes);
}
}
The methods for Read (and also Write) and optimized for the respective class (whether is file stream, memory stream, etc.) and will do the work for you. For simple task like this, there is no need of readers, and etc.
读取(以及写入)和针对相应类(无论是文件流、内存流等)优化的方法将为您完成工作。对于这样的简单任务,不需要读者等。
The only drawback is that the stream is copied into byte array, but that is how the conversion to base64 via Convert.ToBase64String works unfortunately.
唯一的缺点是流被复制到字节数组中,但不幸的是,这就是通过 Convert.ToBase64String 转换为 base64 的工作方式。