diff --git a/src/Ramstack.FileProviders.Extensions/FileInfoExtensions.cs b/src/Ramstack.FileProviders.Extensions/FileInfoExtensions.cs index 5679723..c033aee 100644 --- a/src/Ramstack.FileProviders.Extensions/FileInfoExtensions.cs +++ b/src/Ramstack.FileProviders.Extensions/FileInfoExtensions.cs @@ -153,38 +153,11 @@ public static ValueTask ReadAllTextAsync(this IFileInfo file, Cancellati /// public static async ValueTask ReadAllTextAsync(this IFileInfo file, Encoding? encoding, CancellationToken cancellationToken = default) { - const int BufferSize = 4096; - - var stream = file.OpenRead(); - var reader = new StreamReader(stream, encoding ??= Encoding.UTF8); - var buffer = (char[]?)null; - - try - { - cancellationToken.ThrowIfCancellationRequested(); - - buffer = ArrayPool.Shared.Rent(encoding.GetMaxCharCount(BufferSize)); - var sb = new StringBuilder(); - - while (true) - { - var count = await reader - .ReadAsync(new Memory(buffer), cancellationToken) - .ConfigureAwait(false); - - if (count == 0) - return sb.ToString(); - - sb.Append(buffer.AsSpan(0, count)); - } - } - finally - { - reader.Dispose(); + // ReSharper disable once UseAwaitUsing + using var stream = file.OpenRead(); + using var reader = new StreamReader(stream, encoding!); - if (buffer is not null) - ArrayPool.Shared.Return(buffer); - } + return await reader.ReadToEndAsync(cancellationToken).ConfigureAwait(false); } /// @@ -211,15 +184,13 @@ public static ValueTask ReadAllLinesAsync(this IFileInfo file, Cancell /// public static async ValueTask ReadAllLinesAsync(this IFileInfo file, Encoding? encoding, CancellationToken cancellationToken = default) { - var stream = file.OpenRead(); + // ReSharper disable once UseAwaitUsing + using var stream = file.OpenRead(); using var reader = new StreamReader(stream, encoding!); var list = new List(); - while (await reader.ReadLineAsync().ConfigureAwait(false) is { } line) - { - cancellationToken.ThrowIfCancellationRequested(); + while (await reader.ReadLineAsync(cancellationToken).ConfigureAwait(false) is { } line) list.Add(line); - } return list.ToArray(); } diff --git a/src/Ramstack.FileProviders.Extensions/Internal/StreamReaderExtensions.cs b/src/Ramstack.FileProviders.Extensions/Internal/StreamReaderExtensions.cs new file mode 100644 index 0000000..445dfa2 --- /dev/null +++ b/src/Ramstack.FileProviders.Extensions/Internal/StreamReaderExtensions.cs @@ -0,0 +1,62 @@ +#if NET6_0 +using System.Buffers; +using System.Text; + +// ReSharper disable once CheckNamespace +namespace System.IO; +/// +/// Provides extension methods for the to offer API compatibility with newer .NET versions. +/// +internal static class StreamReaderExtensions +{ + /// + /// Reads a line of characters asynchronously from the current stream and returns the data as a string. + /// + /// The to read from. + /// An optional cancellation token to cancel the operation. + /// + /// A that represents the asynchronous read operation. + /// The value of the task contains the next line from the stream, or is + /// if the end of the stream is reached. + /// + public static ValueTask ReadLineAsync(this StreamReader reader, CancellationToken cancellationToken = default) + { + if (cancellationToken.IsCancellationRequested) + return ValueTask.FromCanceled(cancellationToken); + + return new ValueTask(reader.ReadLineAsync()); + } + + /// + /// Reads all characters from the current position to the end of the stream asynchronously and returns them as one string. + /// + /// The to read from. + /// An optional cancellation token to cancel the operation. + /// + /// A that represents the asynchronous read operation. + /// The value of the task contains a string with the characters from the current position to the end of the stream. + /// + public static async Task ReadToEndAsync(this StreamReader reader, CancellationToken cancellationToken = default) + { + const int BufferSize = 4096; + + var chars = ArrayPool.Shared.Rent(BufferSize); + var sb = new StringBuilder(); + + while (true) + { + var count = await reader + .ReadAsync(new Memory(chars), cancellationToken) + .ConfigureAwait(false); + + if (count == 0) + break; + + sb.Append(chars.AsSpan(0, count)); + } + + ArrayPool.Shared.Return(chars); + return sb.ToString(); + } +} +#endif diff --git a/src/Ramstack.FileProviders.Extensions/Ramstack.FileProviders.Extensions.csproj b/src/Ramstack.FileProviders.Extensions/Ramstack.FileProviders.Extensions.csproj index 7c03c7b..76886f7 100644 --- a/src/Ramstack.FileProviders.Extensions/Ramstack.FileProviders.Extensions.csproj +++ b/src/Ramstack.FileProviders.Extensions/Ramstack.FileProviders.Extensions.csproj @@ -1,7 +1,7 @@ - net6.0 + net6.0;net8.0 A lightweight .NET library of useful and convenient extensions for IFileProvider. enable enable @@ -36,8 +36,15 @@ true - + + + + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -63,7 +70,7 @@ - + Properties\README.md True \ diff --git a/tests/Ramstack.FileProviders.Extensions.Tests/Ramstack.FileProviders.Extensions.Tests.csproj b/tests/Ramstack.FileProviders.Extensions.Tests/Ramstack.FileProviders.Extensions.Tests.csproj index 3863c7c..6957d1f 100644 --- a/tests/Ramstack.FileProviders.Extensions.Tests/Ramstack.FileProviders.Extensions.Tests.csproj +++ b/tests/Ramstack.FileProviders.Extensions.Tests/Ramstack.FileProviders.Extensions.Tests.csproj @@ -1,7 +1,7 @@ - net6.0 + net6.0;net8.0 enable enable preview