Overview
Cuemon.Extensions.IO extends Cuemon.IO and System.IO with four focused extension classes: ByteArrayExtensions, StreamExtensions, StringExtensions, and TextReaderExtensions. Together they cover everyday in-memory I/O work such as turning strings and byte arrays into streams, decoding streams back to strings or buffers, concatenating streams, and compressing or decompressing content with GZip, Deflate, or Brotli.
The project references Cuemon.IO, and the implementations mostly validate the incoming value and forward the work through Decorator.Enclose(...) to the lower-level stream decorators. That gives consumers concise extension-method entry points without changing the encoding, buffering, and compression behaviors defined in the underlying Cuemon I/O abstractions.
Key APIs
ByteArrayExtensions.ToStream converts a byte[] to a readable MemoryStream positioned at zero. The async overload ToStreamAsync writes the bytes into the stream asynchronously and also resets the position before returning.
StreamExtensions.ToByteArray and ToByteArrayAsync read all bytes from a stream and return them as a byte[]. Both overloads accept an optional setup delegate that configures buffer size via StreamCopyOptions or AsyncStreamCopyOptions.
StreamExtensions.ToEncodedString decodes a stream to a string using the encoding specified through StreamEncodingOptions. When no encoding is configured, the method calls ByteOrderMark.DetectEncodingOrDefault to infer the encoding from the stream's BOM before decoding. The async counterpart ToEncodedStringAsync follows the same logic.
StreamExtensions.Concat appends the content of a second stream to a first stream and returns the result as a new MemoryStream. By default both source streams are disposed; passing o.LeaveOpen = true via DisposableOptions prevents disposal. The method chains naturally, so multiple streams can be concatenated in a fluent sequence.
StreamExtensions.CompressGZip, CompressDeflate, and CompressBrotli each produce a compressed MemoryStream from the input. Corresponding Decompress* overloads reverse the operation. The Brotli pair requires .NET Standard 2.1 or .NET 9.0+. All six methods have async counterparts that accept AsyncStreamCompressionOptions or AsyncStreamCopyOptions with a CancellationToken to support cooperative cancellation.
StringExtensions.ToStream converts a string to a Stream using the encoding and preamble policy configured through EncodingOptions. The async overload ToStreamAsync uses AsyncEncodingOptions and writes the encoded bytes without blocking.
StringExtensions.ToTextReader wraps a string in a StringReader and returns it as a TextReader. This enables string content to be passed to any API that consumes a TextReader without intermediate stream allocation.
TextReaderExtensions.ReadAllLines lazily yields each line from a TextReader as an IEnumerable<string>. The async overload ReadAllLinesAsync reads all lines into an IReadOnlyList<string>. CopyToAsync copies content from a TextReader to a TextWriter using a configurable buffer size (default 81920 bytes).
Basic usage
The example below keeps the stream plumbing inside a small composer that turns text fragments into streams, concatenates them, and returns the final manifest text. It demonstrates how the package helps a caller build an in-memory artifact without manually managing MemoryStream, StreamReader, or copy loops.
using System;
using System.IO;
using System.Text;
using Codebelt.Extensions.Xunit;
using Cuemon.Extensions.IO;
using Xunit;
namespace Consumer.Digests.Tests;
public class ImportManifestComposerTest : Test
{
public ImportManifestComposerTest(ITestOutputHelper output) : base(output)
{
}
[Fact]
public void ShouldComposeManifestFromTextSegments()
{
var sut = new ImportManifestComposer();
var manifest = sut.Compose(
"package,version",
"Cuemon.Extensions.IO,8.0.0",
"Cuemon.IO,8.0.0");
TestOutput.WriteLine(manifest);
Assert.Equal(
$"package,version{Environment.NewLine}Cuemon.Extensions.IO,8.0.0{Environment.NewLine}Cuemon.IO,8.0.0{Environment.NewLine}",
manifest);
}
private sealed class ImportManifestComposer
{
public string Compose(string header, string firstRow, string secondRow)
{
using var headerStream = $"{header}{Environment.NewLine}".ToStream(o => o.Encoding = Encoding.UTF8);
using var firstRowStream = $"{firstRow}{Environment.NewLine}".ToStream(o => o.Encoding = Encoding.UTF8);
using var secondRowStream = $"{secondRow}{Environment.NewLine}".ToStream(o => o.Encoding = Encoding.UTF8);
using var manifestStream = new Stream[] { headerStream, firstRowStream, secondRowStream }.Concat();
return manifestStream.ToEncodedString(o => o.Encoding = Encoding.UTF8);
}
}
}
Use this pattern when a component needs to assemble a text payload from smaller in-memory fragments before persisting or sending it somewhere else. ToStream, Concat, and ToEncodedString keep the implementation focused on the artifact being built instead of on manual stream setup and copy mechanics.
Installation
dotnet add package Cuemon.Extensions.IO
Usage guidance
Reach for this package when you need concise, encoding-aware conversions between string, byte[], and Stream — particularly in scenarios where you would otherwise write manual MemoryStream setup or StreamReader/StreamWriter boilerplate. For in-process compression of stream content, the CompressGZip/DecompressGZip and CompressDeflate/DecompressDeflate methods work on all supported frameworks, while CompressBrotli/DecompressBrotli are available on .NET Standard 2.1 and .NET 9.0+. If you prefer the lower-level decorator API directly, use Cuemon.IO; this package is the extension-method layer on top of that foundation.
Family packages
- 🌐Cuemon.AspNetCore
- 🏭Cuemon.AspNetCore.App
- 🌐Cuemon.AspNetCore.Authentication
- 🌐Cuemon.AspNetCore.Mvc
- 🌐Cuemon.AspNetCore.Razor.TagHelpers
- 📦Cuemon.Core
- 🏭Cuemon.Core.App
- 🗄️Cuemon.Data
- 🗄️Cuemon.Data.Integrity
- 🗄️Cuemon.Data.SqlClient
- 🩺Cuemon.Diagnostics
- 🌐Cuemon.Extensions.AspNetCore
- 🌐Cuemon.Extensions.AspNetCore.Authentication
- 🌐Cuemon.Extensions.AspNetCore.Mvc
- 🌐Cuemon.Extensions.AspNetCore.Mvc.Formatters.Text.Json
- 🌐Cuemon.Extensions.AspNetCore.Mvc.Formatters.Xml
- 🌐Cuemon.Extensions.AspNetCore.Mvc.RazorPages
- 🌐Cuemon.Extensions.AspNetCore.Text.Json
- 🌐Cuemon.Extensions.AspNetCore.Xml
- 📦Cuemon.Extensions.Collections.Generic
- 📦Cuemon.Extensions.Collections.Specialized
- 📦Cuemon.Extensions.Core
- 🗄️Cuemon.Extensions.Data
- 🗄️Cuemon.Extensions.Data.Integrity
- 📦Cuemon.Extensions.DependencyInjection
- 🩺Cuemon.Extensions.Diagnostics
- 🏗️Cuemon.Extensions.Hosting
- 📦Cuemon.Extensions.Net
- 📦Cuemon.Extensions.Reflection
- 📦Cuemon.Extensions.Runtime.Caching
- 📝Cuemon.Extensions.Text
- 📝Cuemon.Extensions.Text.Json
- 📦Cuemon.Extensions.Threading
- 📦Cuemon.Extensions.Xml
- 📦Cuemon.IO
- ⚙️Cuemon.Kernel
- 📦Cuemon.Net
- 📦Cuemon.Resilience
- 📦Cuemon.Runtime.Caching
- 🔐Cuemon.Security.Cryptography
- 📦Cuemon.Threading
- 📦Cuemon.Xml