是否有.NET的Base64Stream?

x8diyxa7  于 12个月前  发布在  .NET
关注(0)|答案(7)|浏览(121)

如果我想生成一个Base64编码的输出,我该如何在.NET中实现?
我知道自从.NET 2.0以来,有ICryptoTransform接口,以及该接口的ToBase64Transform()FromBase64Transform()实现。
但是这些类嵌入到System.Security命名空间中,并且需要使用TransformBlock、TransformFinalBlock等。
有没有更简单的方法在.NET中对数据流进行base64编码?

p1iqtdky

p1iqtdky1#

如果你想要一个转换为Base64的流,你可以把一个ToBase64Transform转换为一个CryptoStream

new CryptoStream(stream, new ToBase64Transform(), CryptoStreamMode.Write)

字符串
如果你只想将一个字节数组转换为Base64,你可以简单地调用Convert.ToBase64String(bytes)
在这两种情况下,您都可以将单词To替换为From

kkih6yb8

kkih6yb82#

通过**@Slaks**的简单回答,我写了一个简单的解决方案:

/// <summary>
///     Encodes the specified input stream into the specified output stream.
/// </summary>
/// <param name="inputStream">
///     The input stream.
/// </param>
/// <param name="outputStream">
///     The output stream.
/// </param>
/// <param name="lineLength">
///     The length of lines.
/// </param>
/// <param name="dispose">
///     true to release all resources used by the input and output <see cref="Stream"/>;
///     otherwise, false.
/// </param>
/// <exception cref="ArgumentNullException">
///     inputStream or outputStream is null.
/// </exception>
/// <exception cref="ArgumentException">
///     inputStream or outputStream is invalid.
/// </exception>
/// <exception cref="NotSupportedException">
///     inputStream is not readable -or- outputStream is not writable.
/// </exception>
/// <exception cref="IOException">
///     An I/O error occured, such as the specified file cannot be found.
/// </exception>
/// <exception cref="ObjectDisposedException">
///     Methods were called after the inputStream or outputStream was closed.
/// </exception>
public static void EncodeStream(Stream inputStream, Stream outputStream, int lineLength = 0, bool dispose = false)
{
    if (inputStream == null)
        throw new ArgumentNullException(nameof(inputStream));
    if (outputStream == null)
        throw new ArgumentNullException(nameof(outputStream));
    var si = inputStream;
    var so = outputStream;
    try
    {
        int i;
        var cs = new CryptoStream(si, new ToBase64Transform(), CryptoStreamMode.Read);
        var ba = new byte[lineLength < 1 ? 4096 : lineLength];
        var sep = new byte[] { 0xd, 0xa };
        while ((i = cs.Read(ba, 0, ba.Length)) > 0)
        {
            so.Write(ba, 0, i);
            if (lineLength < 1 || i < ba.Length)
                continue;
            so.Write(sep, 0, sep.Length);
        }
    }
    finally
    {
        if (dispose)
        {
            si.Dispose();
            so.Dispose();
        }
    }
}

/// <summary>
///     Decodes the specified input stream into the specified output stream.
/// </summary>
/// <param name="inputStream">
///     The input stream.
/// </param>
/// <param name="outputStream">
///     The output stream.
/// </param>
/// <param name="dispose">
///     true to release all resources used by the input and output <see cref="Stream"/>;
///     otherwise, false.
/// </param>
/// <exception cref="ArgumentNullException">
///     inputStream or outputStream is null.
/// </exception>
/// <exception cref="ArgumentException">
///     inputStream or outputStream is invalid.
/// </exception>
/// <exception cref="NotSupportedException">
///     inputStream is not readable -or- outputStream is not writable.
/// </exception>
/// <exception cref="IOException">
///     An I/O error occured, such as the specified file cannot be found.
/// </exception>
/// <exception cref="ObjectDisposedException">
///     Methods were called after the inputStream or outputStream was closed.
/// </exception>
public static void DecodeStream(Stream inputStream, Stream outputStream, bool dispose = false)
{
    if (inputStream == null)
        throw new ArgumentNullException(nameof(inputStream));
    if (outputStream == null)
        throw new ArgumentNullException(nameof(outputStream));
    var si = inputStream;
    var so = outputStream;
    try
    {
        var bai = new byte[4096];
        var bao = new byte[bai.Length];
        using (var fbt = new FromBase64Transform())
        {
            int i;
            while ((i = si.Read(bai, 0, bai.Length)) > 0)
            {
                i = fbt.TransformBlock(bai, 0, i, bao, 0);
                so.Write(bao, 0, i);
            }
        }
    }
    finally
    {
        if (dispose)
        {
            si.Dispose();
            so.Dispose();
        }
    }
}

字符串
我只使用CryptoStream来编码,因为我发现它在解码带有换行符的Base64哈希时有问题,而FromBase 64 Transform可以在没有CryptoStream的情况下轻松完成。我希望剩下的足够清楚,我不必解释任何东西。

示例:

const int lineLength = 76;
const string sourcePath = @"C:\test\file-to-encode.example";
const string encodedPath = @"C:\test\encoded-example.base64";
const string decodedPath = @"C:\test\decoded-base64.example";

// encoding
using(var fsi = new FileStream(sourcePath, FileMode.Open))
    using (var fso = new FileStream(encodedPath, FileMode.Create))
        EncodeStream(fsi, fso, lineLength);

// decoding
using(var fsi = new FileStream(encodedPath, FileMode.Open))
    using (var fso = new FileStream(decodedPath, FileMode.Create))
        DecodeStream(fsi, fso);

cld4siwp

cld4siwp3#

这应该是你正在寻找的:
http://mews.codeplex.com/SourceControl/changeset/view/52969#392973

unhi4e5o

unhi4e5o4#

Convert提供了这一点,下面是一个代码示例,

private string EncodeBase64(string toEncode)
{
  byte[] toEncodeAsBytes = System.Text.ASCIIEncoding.ASCII.GetBytes(toEncode);
  string returnValue = System.Convert.ToBase64String(toEncodeAsBytes);
  return returnValue;
}

字符串

rvpgvaaj

rvpgvaaj5#

基于@sombra的回答,我需要一些类似的东西,但在处理需要以流格式发送到其S3存储的大文件时,我的Web API更容易使用。

/// <summary>
///     Decodes input Base 64 encoded data to the specified <see cref="Stream"/>
/// </summary>
/// <param name="outputStream">
///     Output <see cref="Stream"/>
/// </param>
/// <param name="base64Data">
///     Base 64 encoded data
/// </param>
/// <returns>
///     outputStream length
/// </returns>
/// <exception cref="ArgumentNullException">
///     outputStream or base64Data were null
/// </exception>
/// <exception cref="ArgumentException">
///     outputStream is invalid
/// </exception>
/// <exception cref="NotSupportedException">
///     outputStream isn't writable
/// </exception>
/// <exception cref="ObjectDisposedException">
///     Methods were called to outputStream after it closed
/// </exception>
public static long DecodeBase64Stream(Stream outputStream, string base64Data)
{
    if (outputStream == null)
    {
        throw new ArgumentNullException(nameof(outputStream));
    }

    if (string.IsNullOrEmpty(base64Data))
    {
        throw new ArgumentNullException(nameof(base64Data));
    }

    const int bufferSize = 80 * 1024;
    byte[] byteArray = new byte[bufferSize];
    byte[] byteOutput = new byte[bufferSize];
    int c = Math.Min(base64Data.Length, bufferSize);

    using FromBase64Transform transform = new();

    while (base64Data[..c].Length > 0)
    {
        int totalBytes = Encoding.UTF8.GetByteCount(base64Data[..c]);

        byteArray = Encoding.UTF8.GetBytes(base64Data[..c]);
        totalBytes = transform.TransformBlock(byteArray, 0, totalBytes, byteOutput, 0);
        outputStream.Write(byteOutput, 0, totalBytes);
        base64Data = base64Data[c..];

        c = Math.Min(base64Data.Length, bufferSize);
    }

    transform.Dispose();
    return outputStream.Length;
}

字符串

r8xiu3jd

r8xiu3jd6#

看起来好像有一个Base64Stream类。也许它会帮助未来的读者。
http://referencesource.microsoft.com/#system/net/System/Net/mail/Base64Stream.cs

vnzz0bqm

vnzz0bqm7#

CryptoStream不做RFC2045行结束。因此,这对我不起作用。
ToBase64String是不可接受的,因为它不是一种流方法。我不想一次在内存中保存所有数据。
所以我需要别的选择。
Richard Grimes在这里发布了一个:
http://www.grimes.nildram.co.uk/workshops/encodedStream.htm
由于许可和功能需求,我没有使用它,而是编写了一个独立的实现,可以在这里找到:
http://cheeso.members.winisp.net/srcview.aspx?dir=streams&file=Base64Stream.cs
它的许可证是the MS-PL
要使用它来压缩然后对文件进行base64编码,请执行以下操作:

byte[] working= new byte[1024];
int n;
using (Stream input = File.OpenRead(fileToCompress))
{
    using (Stream output = new FileStream("file.deflated.b64"))
    {
        using (var b64 = new Base64Stream(output, Base64Stream.Mode.Encode))
        {
            b64.Rfc2045Compliant = true; // OutputLineLength = 76;

            using (var compressor = new DeflateStream(b64, CompressionMode.Compress, true))
            {
                while ((n = input.Read(working, 0, working.Length)) != 0)
                {
                    compressor.Write(working, 0, n);
                }
            }
        }
    }
}

字符串

相关问题