Anixe.IO
4.0.0
dotnet add package Anixe.IO --version 4.0.0
NuGet\Install-Package Anixe.IO -Version 4.0.0
<PackageReference Include="Anixe.IO" Version="4.0.0" />
paket add Anixe.IO --version 4.0.0
#r "nuget: Anixe.IO, 4.0.0"
// 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
- BatchesEnumerator
- CustomMemoryPool
- DeflateReverseStream
- DelegatingTextWriter
- DelimitedEachSpanEnumerator
- DelimitedSpanEnumerator
- EnhancedTextWriter
- EscapedXmlStreamReader
- FastStreamReader
- JoinedSegmentsEnumerator
- JsonTextWriter
- ListSegment
- Log
- LoggingHandler
- MemoryOwnedStream
- PooledStream
- RefineReverseStream
- Stream2Stream
- Stream2TextWriter
- StreamCopy
- StreamReader
- StreamWriter
- TextFormatter
- TextWriter2StreamDelegate
- UnescapeXmlStreamReader
- UrlEncodededWriter
- UrlWriter
- ValueStringBuilder
- ValueUrlWriter
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
asIMessageWriter
for syslog messagesMessageAsGelfWriter
asIMessageWriter
for GELF messages]MessageAsGelfWriter
writer has dependency toIArrayPool<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 SeriLogAppendCustom(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 | Versions 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. |
-
net6.0
- Microsoft.Extensions.Logging (>= 8.0.0)
- Microsoft.IO.RecyclableMemoryStream (>= 3.0.0)
- Newtonsoft.Json (>= 13.0.3)
-
net8.0
- Microsoft.Extensions.Logging (>= 8.0.0)
- Microsoft.IO.RecyclableMemoryStream (>= 3.0.0)
- Newtonsoft.Json (>= 13.0.3)
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 | 11,011 | 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,500 | 10/14/2022 |
2.4.10 | 1,315 | 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,272 | 4/6/2022 |
2.4.2 | 973 | 3/28/2022 |
2.4.1 | 445 | 3/22/2022 |
2.4.0 | 3,293 | 3/1/2022 |
2.3.3 | 5,054 | 12/15/2021 |
2.3.2 | 2,657 | 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,574 | 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,590 | 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 | 774 | 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.