Is there a Base64Stream for .NET?
If you want a stream that converts to Base64, you can put a ToBase64Transform
into a CryptoStream
:
new CryptoStream(stream, new ToBase64Transform(), CryptoStreamMode.Write)
If you just want to convert a single byte array to Base64, you can simply call Convert.ToBase64String(bytes)
.
In both cases, you can replace the word To
with From
.
With the simple answer from @SLaks I have written a simple solution:
/// <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();
}
}
}
I only use CryptoStream to encode because I've found it has problems decoding Base64 hahes with line breaks, while FromBase64Transform can do that easily without CryptoStream. I hope the rest is clear enough that I do not have to explain anything.
Example:
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);