Anixe.IO 4.0.0

dotnet add package Anixe.IO --version 4.0.0                
NuGet\Install-Package Anixe.IO -Version 4.0.0                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Anixe.IO" Version="4.0.0" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Anixe.IO --version 4.0.0                
#r "nuget: Anixe.IO, 4.0.0"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install Anixe.IO as a Cake Addin
#addin nuget:?package=Anixe.IO&version=4.0.0

// Install Anixe.IO as a Cake Tool
#tool nuget:?package=Anixe.IO&version=4.0.0                

Anixe.IO

Package includes

Base64ReverseStream

The reverse stream is a kind of stream which allows to copy from source to destination with passing source stream in constructor and destination steam while copy. Regular forward streams requires destination stream in constructor, which is not always possible to archive.

the Base64ReverseStream allows you to encode source stream into base64 while copying data into destination stream

  var source = new MemoryStream(Encoding.UTF8.GetBytes("test sample"));
  var target = new MemoryStream();
  using (var subject = new Base64ReverseStream(source, 2048, leaveOpen: true))
  {
    subject.CopyTo(target);
  }

BatchesEnumerator

The struct allows to split IList<T> into batches without allocations using ListSegment class. Check BatchesEnumeratorTest for details

CustomMemoryPool

The class implements an MemoryPool<T> abstraction. The class holds only ArrayPool instance inside and does not require disposing. Creating multiple instances of this class will spawn multiple ArrayPool instances so use it as a singleton in the application. The class has been added here because of limitation inside MemoryPool<T> default implementation which causes memory leaks for > 1 Mb arrays. For explanation refer to: https://adamsitnik.com/Array-Pool/

var oneMb  = 1024 * 1024;
var pool = new CustomMemoryPool<byte>(50 * oneMb);
using (var memoryOwner = pool.Rent(30 * oneMb))
{
  DoSomething(memoryOwner);
}
var oneMb  = 1024 * 1024;
var pool = new CustomMemoryPool<byte>(50 * oneMb);
using (var stream = new MemoryOwnedStream(pool)) // pass custom pool to the stream for renting
{
  SerializeObject(stream);
  return (stream.GetBuffer(), stream.Length); // pass the ownership of IMemoryOwner<byte> to next executor and length to have information about bytes written into the memory buffer.
}

DeflateReverseStream

The reverse stream is a kind of stream which allows to copy from source to destination with passing source stream in constructor and destination steam while copy. Regular forward streams requires destination stream in constructor, which is not always possible to archive.

the DeflateReverseStream allows you to compress source stream into gzip format while copying data into destination stream

  var source = new MemoryStream(Encoding.UTF8.GetBytes("test sample"));
  var target = new MemoryStream();
  using (var subject = new DeflateReverseStream(source, 2048, leaveOpen: true))
  {
    subject.CopyTo(target);
  }

DelegatingTextWriter

The class delegates TextWriter signals to provided inner TextWriters, it is useful to feed multiple TextWriters at the same time.

Examples

  var tw1 = new StreamWriter(someStream);
  var tw2 = Console.Out;
  using (var subject = new DelegatingTextWriter(tw1, tw2))
  {
    subject.WriteLine("some text");
  }

DelimitedEachSpanEnumerator

The struct allows to enumerate through tokens delimited by single char from ReadOnlySpan<char> It has the same output as string.Split with StringSplitOptions.None

Examples

  var iterator = new DelimitedEachSpanEnumerator(text.AsSpan(), delimiter);
  while (iterator.MoveNext())
  {
    ReadOnlySpan<char> segment = iterator.Current;
    // do something
  }

also exists extension method for convenience:

  foreach (var span in text.AsSpan().SpliIncludeEmptyEntries(','))
  {
    ReadOnlySpan<char> segment = span;
    // do something
  }

DelimitedSpanEnumerator

The struct allows to enumerate through tokens delimited by single char from ReadOnlySpan<char> It has the same output as string.Split with StringSplitOptions.RemoveEmptyEntries Use case:

  var iterator = new DelimitedSpanEnumerator(text.AsSpan(), delimiter);
  while (iterator.MoveNext())
  {
    ReadOnlySpan<char> segment = iterator.Current;
    // do something
  }

also exists extension method for convenience:

  foreach (var span in text.AsSpan().SpliExcludeEmptyEntries(','))
  {
    ReadOnlySpan<char> segment = span;
    // do something
  }

EnhancedTextWriter

The class implements TextWriter + some Stream class methods:

  • TotalBytesWritten - returns total bytes written to target stream. It is useful to track if target stream receives data even for forward-only streams (e.g. NetworkStream)
  • WriteBase64(byte[] data, int offset, int count) - writes data as base64 encoded string into underlying stream
  • CanRead - calls the same method from underlying stream
  • CanSeek - calls the same method from underlying stream
  • CanWrite - calls the same method from underlying stream
  • Length - calls the same method from underlying stream
  • Position - calls the same method from underlying stream
  • Seek(long offset, SeekOrigin origin) - calls the same method from underlying stream
  • SetLength(long value) - calls the same method from underlying stream

EscapedXmlStreamReader

Reads XML-entities encoded stream

Example usage

  using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(escapedXml)))
  {
    var reader = XmlReader.Create(new EscapedXmlStreamReader(ms));
    return ReadResponse(reader);
  }

FastStreamReader

The class reads content from file line by line exposing it as ArraySegment<char>. It has minimal memory footprint. Use case:

using(var reader = new FastStreamReader(File.OpenRead(path)
{
  while(reader.Read())
  {
    ArraySegment<char> line = reader.CurrentRawLine;
    // do something
  }
}

JoinedSegmentsEnumerator

Enumerates through the span of characters delimited by provided char and joins each segment with previous one on each iteration.

Example usage

var enumerator = new JoinedSegmentsEnumerator("GR.AT.AT.ATH", '.');

foreach (var span in enumerator)
{
  Console.WriteLine(span.ToString());
}

displays:

GR
GR.AT
GR.AT.AT
GR.AT.AT.ATH

JsonTextWriter

The class derives from Newtonsoft.Json.JsonTextWriter providing additions WriteValue routines (check JsonTextWriterTest for details)

ListSegment

The class (similar to ArraySegment<T>) provides a allocation free view of the IList<T>.

Log

Added in order to ease integration with Resfinity Logging Platform

LoggingHandler

Added allocationless http payloads logger which passes pooled array filled with data to the logging system. Use LoggingHandler class as http client delegating handler.

MemoryOwnedStream

This is a memory stream wrapping ReadOnlyMemory<byte> (read-only mode) or wrapping IMemoryOwner<byte> taken from MemoryPool<byte> (read or write mode). It allows you to encapsulate Memory<byte> inside managed stream. Be aware that default constructor requires to dispose IMemoryOwner<byte> manually.

using (var stream = new MemoryOwnedStream())
{
  SerializeObject(stream);
  return (stream.GetBuffer(), stream.Length); // pass the ownership of IMemoryOwner<byte> to next executor and length to have information about bytes written into the memory buffer.
}
ReadOnlyMemory<byte> mem = ReadSomething();
using (var stream = new MemoryOwnedStream(mem)) // only for reading
{
  var obj = DeserializeObject(stream);
  return obj;
}

PooledStream

This is a memory stream with internal byte buffer pooled from ArrayPool<byte>. Use it as regular stream. Useful hints:

  • The stream resizes its internal array by rent an array with bigger size if the bytes written exceeds the actual buffer size.
  • The stream must be disposed to avoid memory leaks.
  • The stream exposes it's internal buffer similar to MemoryStream with GetBuffer() method.
  • SetLength method is important to limit the content of the stream it it's real length. Internal buffer is always bigger than written content.
  var str = "test string";
  var stream = new PooledStream(str.Length);
  var bytesConverted = Encoding.UTF8.GetBytes(str, 0, str.Length, stream.GetBuffer(), 0);
  stream.SetLength(bytesConverted);

RefineReverseStream

the RefineReverseStream allows you to remove certain bytes from source stream while copying data into destination stream. It is useful to remove new line character, but it can be any byte.

  var source = new MemoryStream(Encoding.UTF8.GetBytes("test sample\ntest sample2"));
  var target = new MemoryStream();
  using (var subject = new RefineReverseStream(source, byteToRefine: (byte) '\n', leaveOpen: true))
  {
    subject.CopyTo(target);
  }

Stream2Stream

The class delegates source Stream reads and writes to destination Stream writes

Stream2TextWriter

The class writes input bytes into both: Stream and TextWriter.

Example usage

var subject = new Stream2TextWriter(outputStream, outputTextWriter, writeBuffer: new char[1024]);
subject.Write(inputByteArray, offset: 0, count: inputByteArray.Length);

StreamCopy

Example usage

using(var tw = new StreamWriter(outputStream, Encoding.UTF8))
{
  var buffer = new char[buffSize];
  StreamCopy.Copy(inputStream, tw, 0, 50, buffer);
}

StreamReader

The class uses array pool for internal buffers allocations (.NET Core only)

StreamWriter

The class uses array pool for internal buffers allocations (.NET Core only)

TextFormatter

Stream implementation that allows to write input as text in provided encoding and exposes counter of written bytes.

Example usage

using(var tf = new TextFormatter(outputStream, Encoding.UTF8, 1024))
{
    tf.Write(123);
    tf.Write("text");
    tf.WriteBase64(bytes, 0, bytes.Length);
}

TextWriter2StreamDelegate

The class delegates source TextWriter reads and writes to destination Stream writes

UnescapeXmlStreamReader

UrlEncodededWriter

The class writes text applying URL-encoding to provided <see cref="TextWriter"/>.

Example usage

using (var ms = new MemoryStream())
{
    using (var writer = new StreamWriter(ms))
    using (var urlWriter = new UrlEncodededWriter(writer))
    {
        urlWriter.Write("Wrocław");
    }
    var text = Consts.DefaultEncoding.GetString(ms.ToArray());
    Console.WriteLine(text); // prints `Wroc%C5%82aw`

UrlWriter

Example usage

  var urlWriter = new UrlWriter();
  urlWriter.WriteBaseUrl("http://site.com");
  urlWriter.WriteUrlSegment("page");
  urlWriter.WriteUrlSegment("subpage");
  urlWriter.WriteStartArguments();
  urlWriter.WriteArgument("id", "1234");
  urlWriter.WriteArgument("device", "mobile");
  var url = UrlWriter.toString();
  // produces: http://site.com/page/subpage?id=1234&device=mobile

ValueStringBuilder

Anixe implementation of internal .NET library type for building strings without heap allocations. It uses a ReadOnlySpan<char> provided in constructor as an internal buffer, or an array from ArrayPool.Shared if the buffer was not provided or was too small.

Use case:

var sb = new ValueStringBuilder(stackalloc char[50]);
var names = new[] { "first", "second" };
for (int i = 0; i < names.Length; i++)
{
    if (i > 0)
    {
        sb.Append(',');
    }
    sb.Append(i.ToString());
    sb.Append(": ");
    sb.Append(name);
}
return sb.ToString();

ValueUrlWriter

Allocationless implementation of UrlWriter. It is implemented as ref struct and operates on Span<char> buffer. Rents an array from ArrayPool.Shared if provided buffer was too small to write.

Example usage

  var urlWriter = new ValueUrlWriter(stackallock char[256]);
  urlWriter.WriteBaseUrl("http://site.com");
  urlWriter.WriteUrlSegment("page");
  urlWriter.WriteUrlSegment("subpage");
  urlWriter.WriteStartArguments();
  urlWriter.WriteArgument("id", "1234");
  urlWriter.WriteArgument("device", "mobile");
  var url = UrlWriter.toString();
  // produces: http://site.com/page/subpage?id=1234&device=mobile

Remarks

ListSegment<T> is a wrapper around an IList<T> that delimits a range of elements in that list. Multiple ListSegment<T> instances can refer to the same original list and can overlap. The original list must have zero-based indexing and cannot change size in the meantime.

Each message requires logging level to be assigned. For majority of Anixe apps it's easy mapping

  • transactions with status OK → MessageLevel.INFORMATIONAL
  • transactions with status ERR → MessageLevel.ERROR

If you don't need any customization register:

  • MessageAsSyslogWriter as IMessageWriter for syslog messages
  • MessageAsGelfWriter as IMessageWriter for GELF messages]
    • MessageAsGelfWriter writer has dependency to IArrayPool<char> - it must be passed directly to the constructor or registered via dependency injection framework

If you don't need any custom message object use Anixe.IO.Log.Message

  • if you need to store data in Graylog and model does not define key for it you can use
    • keyDoublePairs, keyLongPairs, keyIntPairs for numbers
    • keyStringPairs for strings

If customization is required

  • define custom writer that inherits from MessageAsSyslogWriter and override:

    • WriteCustom(TextWriter writer, IMessage message) method for SeriLog
    • AppendCustom(StringBuilder builder, IMessage message) method for NLog
  • define custom writer that inherits from MessageAsGelfWriter and override:

    • WriteCustom(Anixe.IO.JsonTextWriter, IMessage message) method for both SeriLog/NLog
  • define custom IMessage model that either inherits from Message or implements IMessage directly

public class CustomMessage : Message
{
    public string foo;
    public string bar;
}

public class CustomWriter : MessageAsSyslogTextWriterWriter
{
    protected override void WriteCustom(TextWriter writer, IMessage message)
    {
        var m = message as CustomMessage;

        WriteProperty(writer, "foo", m.foo);
        WriteProperty(writer, "bar", m.bar);
    }
}
Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (4)

Showing the top 4 NuGet packages that depend on Anixe.IO:

Package Downloads
Anixe.IO.Messaging

Package Description

Anixe.IO.NLog.Extensions

Package Description

Anixe.IO.Appmetrics

Package Description

Anixe.IO.AuditlogClient

Package Description

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
4.0.0 10,900 1/8/2024
3.1.0 1,438 12/4/2023
3.0.1 6,443 2/27/2023
3.0.0 1,161 1/10/2023
2.5.0 9,482 10/14/2022
2.4.10 1,313 10/3/2022
2.4.9 388 9/29/2022
2.4.8 1,956 7/7/2022
2.4.7 491 6/30/2022
2.4.6 2,310 6/21/2022
2.4.5 650 6/20/2022
2.4.4 1,253 6/8/2022
2.4.3 7,268 4/6/2022
2.4.2 973 3/28/2022
2.4.1 445 3/22/2022
2.4.0 3,283 3/1/2022
2.3.3 5,054 12/15/2021
2.3.2 2,653 10/29/2021
2.3.1 382 10/7/2021
2.3.0 611 9/29/2021
2.2.0 1,098 9/6/2021
2.1.0 7,483 8/31/2021
2.0.26 7,717 7/8/2021
2.0.25 6,050 4/28/2021
2.0.24 9,581 2/22/2021
2.0.23 4,368 1/26/2021
2.0.22 371 1/26/2021
2.0.21 1,687 12/15/2020
2.0.20 4,205 9/9/2020
2.0.19 11,967 6/23/2020
2.0.17 785 5/29/2020
2.0.16 1,635 5/25/2020
2.0.15 3,177 5/12/2020
2.0.14 1,074 5/12/2020
2.0.13 5,394 4/24/2020
2.0.12 581 4/22/2020
2.0.11 1,509 4/20/2020
2.0.10 3,686 3/19/2020
2.0.9 770 3/18/2020
2.0.8 546 3/17/2020
2.0.7 4,572 1/14/2020
2.0.6 743 12/31/2019
2.0.5 901 12/11/2019
2.0.4 2,871 11/29/2019
2.0.2 1,198 9/5/2019
2.0.1 4,289 7/23/2019
2.0.0 1,207 7/22/2019
1.9.1 8,533 7/14/2019
1.9.0 685 7/9/2019
1.8.1 2,368 5/9/2019
1.8.0 1,588 4/4/2019
1.6.8 1,161 2/13/2019
1.6.7 780 2/6/2019
1.6.6 703 2/4/2019
1.6.5 1,707 11/5/2018
1.6.4 772 11/1/2018
1.6.3 772 10/28/2018
1.6.2 775 10/20/2018
1.6.1 766 10/20/2018
1.5.0 836 10/14/2018

# Anixe.IO CHANGELOG

## 4.0.0 - 2024-01-03

- Updated Microsoft.Extensions.Logging from v7.0.0 to v8.0.0
- Updated Microsoft.IO.RecyclableMemoryStream from v2.2.1 to v3.0.0
- Updated Newtonsoft.Json from v13.0.2 to v13.0.3
- BREAKING CHANGE: marked EnchancedTextWriter as obsolete as its name contains typo. Use EnhancedTextWriter instead.
- BREAKING CHANGE: removed obsoleted property PayloadFielName in Anixe.IO.Extensions.Logger.LoggingHandlerOptions; use property PayloadFieldName instead. WARNING: if you bind this options as an appsettings.json section, rename key "PayloadFielName" to "PayloadFieldName".

## 3.1.0 - 2023-12-05

- Added XML comments to some classes and methods & improved existing ones
- Added extension methods `ReadOnlySpan<char>.SplitIncludeEmptyEntries(separator)` and `ReadOnlySpan<char>.SplitIncludeEmptyEntries(separator)` whose results can be enumerated in foreach loop
- Added possibility to iterate JoinedSegmentsEnumerator using foreach loop
- Fix incorrect behavior of RefineReverseStream.ReadByte
- Fix internal buffer of Base64Stream was not returned to array pool after dispose
- Fix Base64ReverseStream.DisposeAsync() was disposing wrapped stream synchronously
- Fix pool determination in CustomMemoryPool
- Improved performance of some operations in DelegatingTextWriter
- Improved performance of StreamCopy.CopyToAsync
- Improved performance of DelimitedEachSpanEnumerator and DelimitedSpanEnumerator
- Improved performance of RefineReverseStream asynchronous operations
- Improved performance of CustomMemoryPool.Rent method when minBufferSize is -1
- Improved performance of formatting syslog logs in MessageAsSyslogWriter
- Improved performance of FastStreamReader.Read()
- Improved performance of formatting numbers to bytes in EnchancedTextWriter and TextFormatter

## 3.0.1 - 2023-02-20
- minor performance enhancement in ValueStringBuilder

## 3.0.0 - 2022-12-21

- Drop support of .NET below 6.0
- Update Newtonsoft.Json to 13.0.2
- Update Microsoft.IO.RecyclableMemoryStream to 2.2.1
- Update Microsoft.Extensions.Logging to 7.0.0
- Removed obsolete constructors in MemoryOwnedStream - use the other ones with explicit `leaveUndisposed` flag
- Removed obsolete method CopyToAsync(Stream) in TextFormatter - use method WriteAsync(Stream) instead
- Removed obsolete method CopyTo(Stream) in TextFormatter - use method Write(Stream) instead
- Removed obsolete XmlResponseStreamReader class - it had bugs and was bad for performance
- Fixed Message.AddPair(string key, int value) - the value was treated as double, not integer

## 2.5.0 - 2022-10-12

- Fix memory leak in AuditlogClient
- Fix incorrect behavior of TextFormatter
- Fix invariant culture not always was applied in EnchancedTextWriter
- Various performance optimizations

## 2.4.10 - 2022-10-01

- Fix PooledStream the last array was not disposed on dispose

## 2.4.9 - 2022-09-29

- Fix UnescapeXmlStreamReader to properly compare escaped strings

## 2.4.8 - 2022-07-07

- Fix not logged HTTP responses with forward-only stream content that was not fully consumed in reader

## 2.4.7 - 2022-06-30

- Fixed in Stream2TextWriter.Read(...) when encoded destination was sliced with wrong start index

## 2.4.6 - 2022-06-21

- Added CopyTo(Stream ) and Write(ReadOnlyMemory<byte> ) synchronous method to TextFormatter

## 2.4.5 - 2022-06-17

- Fix TextFormatter counted not all written bytes

## 2.4.4 - 2022-06-06

- Added EnchancedTextWriter class

## 2.4.3 - 2022-04-05

- Fixed NullRefernceException when Anixe.IO.StreamWriter that was created with leaveOpen:true was disposed twice

## 2.4.2 - 2022-03-25

- Fixed not working PooledStream methods: ReadAsync, CopyTo, Read, Close
- Fixed incorrect null annotations in some classes
- Fixed not applied cancellation token in Base64ReverseStream.ReadAsync and DeflateReverseStream.ReadAsync
- Improved performance of some classes

## 2.4.1 - 2022-03-21

- Fix InternalBufferOverflowException in ValueUrlWriter
- Added property RentedBufferFromPool to ValueUrlWriter
- Updated RecyclableMemoryStream to 2.2.0

## 2.4.0 - 2022-02-28

- added ValueStringBuilder
- added build for .NET 5 and .NET 6

## 2.3.3 - 2021-12-15

- Fix error in FastStreamReader when multiple empty lines in a row causes null instead of empty string

## 2.3.2 - 2021-10-29

- Various memory optimizations

## 2.3.1 - 2021-19-04

- Fix DelegatingTextWriter.WriteLine was not adding new line at the end
- Logging HttpResponseMessage did not fully take into account the cancellation token

## 2.3.0 - 2021-09-29

- Added method FlushAsync to Stream2Stream class

## 2.2.0 - 2021-09-06

- Added method ReadAsync and WriteAsync Stream2Stream

## 2.1.0 - 2021-08-31

- Update Newtonsoft.Json to 13.0.*
- Update Microsoft.IO.RecyclableMemoryStream to 2.1.3

## 2.0.26 - 2021-07-08

### Added

- License information in package metadata

## 2.0.25 - 2021-04-28

### Fixed

- Text smaller than 3 bytes was not formatted by `Base64ReverseStream` class.