@@ -8,13 +8,6 @@ namespace Ramstack.FileSystem;
88/// </summary>
99public static class VirtualFileExtensions
1010{
11- private static Encoding ? s_utf8NoBom ;
12-
13- /// <summary>
14- /// Gets an instance of the <see cref="UTF8Encoding"/> without BOM.
15- /// </summary>
16- private static Encoding Utf8NoBom => s_utf8NoBom ??= new UTF8Encoding ( encoderShouldEmitUTF8Identifier : false , throwOnInvalidBytes : true ) ;
17-
1811 /// <summary>
1912 /// Asynchronously returns a <see cref="StreamReader"/> with <see cref="Encoding.UTF8"/>
2013 /// character encoding that reads from the specified text file.
@@ -26,7 +19,7 @@ public static class VirtualFileExtensions
2619 /// The result is a <see cref="StreamReader"/> that reads from the text file.
2720 /// </returns>
2821 public static ValueTask < StreamReader > OpenTextAsync ( this VirtualFile file , CancellationToken cancellationToken = default ) =>
29- file . OpenTextAsync ( Encoding . UTF8 , cancellationToken ) ;
22+ file . OpenTextAsync ( encoding : null , cancellationToken ) ;
3023
3124 /// <summary>
3225 /// Asynchronously returns a <see cref="StreamReader"/> with the specified character encoding
@@ -67,7 +60,7 @@ public static ValueTask WriteAsync(this VirtualFile file, Stream stream, Cancell
6760 /// containing the full text from the current file.
6861 /// </returns>
6962 public static ValueTask < string > ReadAllTextAsync ( this VirtualFile file , CancellationToken cancellationToken = default ) =>
70- ReadAllTextAsync ( file , Encoding . UTF8 , cancellationToken ) ;
63+ ReadAllTextAsync ( file , encoding : null , cancellationToken ) ;
7164
7265 /// <summary>
7366 /// Asynchronously reads all the text in the current file with the specified encoding.
@@ -81,9 +74,15 @@ public static ValueTask<string> ReadAllTextAsync(this VirtualFile file, Cancella
8174 /// </returns>
8275 public static async ValueTask < string > ReadAllTextAsync ( this VirtualFile file , Encoding ? encoding , CancellationToken cancellationToken = default )
8376 {
77+ //
78+ // Use a manual read loop since .NET 6 lacks a StreamReader.ReadToEndAsync overload that accepts a CancellationToken.
79+ // This ensures the operation remains responsive to cancellation requests.
80+ //
81+
8482 const int BufferSize = 4096 ;
8583
86- var stream = await file . OpenReadAsync ( cancellationToken ) . ConfigureAwait ( false ) ;
84+ // ReSharper disable once UseAwaitUsing
85+ using var stream = await file . OpenReadAsync ( cancellationToken ) . ConfigureAwait ( false ) ;
8786 var reader = new StreamReader ( stream , encoding ??= Encoding . UTF8 ) ;
8887 var buffer = ( char [ ] ? ) null ;
8988
@@ -217,20 +216,20 @@ static async ValueTask<byte[]> ReadAllBytesUnknownLengthImplAsync(Stream stream,
217216 total += count ;
218217 }
219218
220- static byte [ ] ResizeBuffer ( byte [ ] bytes )
219+ static byte [ ] ResizeBuffer ( byte [ ] oldArray )
221220 {
222- var length = ( uint ) bytes . Length * 2 ;
221+ var length = ( uint ) oldArray . Length * 2 ;
223222 if ( length > ( uint ) Array . MaxLength )
224- length = ( uint ) Math . Max ( Array . MaxLength , bytes . Length + 1 ) ;
223+ length = ( uint ) Math . Max ( Array . MaxLength , oldArray . Length + 1 ) ;
225224
226- var tmp = ArrayPool < byte > . Shared . Rent ( ( int ) length ) ;
227- Buffer . BlockCopy ( bytes , 0 , tmp , 0 , bytes . Length ) ;
225+ var newArray = ArrayPool < byte > . Shared . Rent ( ( int ) length ) ;
226+ oldArray . AsSpan ( ) . TryCopyTo ( newArray ) ;
228227
229- var rented = bytes ;
230- bytes = tmp ;
228+ var rented = oldArray ;
229+ oldArray = newArray ;
231230
232231 ArrayPool < byte > . Shared . Return ( rented ) ;
233- return bytes ;
232+ return oldArray ;
234233 }
235234 }
236235
@@ -302,7 +301,7 @@ public static ValueTask WriteAllTextAsync(this VirtualFile file, ReadOnlyMemory<
302301 /// </returns>
303302 public static async ValueTask WriteAllTextAsync ( this VirtualFile file , ReadOnlyMemory < char > contents , Encoding ? encoding , CancellationToken cancellationToken = default )
304303 {
305- var stream = await file . OpenWriteAsync ( cancellationToken ) . ConfigureAwait ( false ) ;
304+ await using var stream = await file . OpenWriteAsync ( cancellationToken ) . ConfigureAwait ( false ) ;
306305 await using var writer = new StreamWriter ( stream , encoding ! ) ;
307306 await writer . WriteAsync ( contents , cancellationToken ) . ConfigureAwait ( false ) ;
308307 }
@@ -331,13 +330,11 @@ public static ValueTask WriteAllLinesAsync(this VirtualFile file, IEnumerable<st
331330 /// </returns>
332331 public static async ValueTask WriteAllLinesAsync ( this VirtualFile file , IEnumerable < string > contents , Encoding ? encoding , CancellationToken cancellationToken = default )
333332 {
334- var stream = await file . OpenWriteAsync ( cancellationToken ) . ConfigureAwait ( false ) ;
333+ await using var stream = await file . OpenWriteAsync ( cancellationToken ) . ConfigureAwait ( false ) ;
335334 await using var writer = new StreamWriter ( stream , encoding , bufferSize : - 1 , leaveOpen : false ) ;
336335
337336 foreach ( var line in contents )
338337 await writer . WriteLineAsync ( line ) . ConfigureAwait ( false ) ;
339-
340- await writer . FlushAsync ( ) . ConfigureAwait ( false ) ;
341338 }
342339
343340 /// <summary>
0 commit comments