From 0fd95dcc20a46506e8f31180536f382cb76d50d8 Mon Sep 17 00:00:00 2001 From: Cloudea <2025140062@qq.com> Date: Thu, 21 Aug 2025 23:29:10 +0800 Subject: [PATCH 1/7] Enhance consistency of StreamReader and StreamWriter --- .../src/System/IO/StreamReader.cs | 8 ++++++-- .../src/System/IO/StreamWriter.cs | 10 +++++++--- .../StreamReader/StreamReader.StringCtorTests.cs | 8 +++++++- .../StreamWriter/StreamWriter.StringCtorTests.cs | 8 +++++++- 4 files changed, 27 insertions(+), 7 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/StreamReader.cs b/src/libraries/System.Private.CoreLib/src/System/IO/StreamReader.cs index cd3bc29187abdb..5031f3340adbd5 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/StreamReader.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/StreamReader.cs @@ -25,7 +25,6 @@ public class StreamReader : TextReader // saves construction time. This does break adaptive buffering, // but this is slightly faster. private const int DefaultBufferSize = 1024; // Byte buffer size - private const int DefaultFileStreamBufferSize = 4096; private const int MinBufferSize = 128; private readonly Stream _stream; @@ -226,10 +225,15 @@ private static FileStream ValidateArgsAndOpenPath(string path, FileStreamOptions private static FileStream ValidateArgsAndOpenPath(string path, int bufferSize) { + if (bufferSize == -1) + { + bufferSize = DefaultBufferSize; + } + ArgumentException.ThrowIfNullOrEmpty(path); ArgumentOutOfRangeException.ThrowIfNegativeOrZero(bufferSize); - return new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, DefaultFileStreamBufferSize); + return new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, FileStream.DefaultBufferSize); } public override void Close() diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/StreamWriter.cs b/src/libraries/System.Private.CoreLib/src/System/IO/StreamWriter.cs index 229509254e1d99..cd8f577f989dc0 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/StreamWriter.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/StreamWriter.cs @@ -24,7 +24,6 @@ public class StreamWriter : TextWriter // which means we take advantage of adaptive buffering code. // The performance using UnicodeEncoding is acceptable. private const int DefaultBufferSize = 1024; // char[] - private const int DefaultFileStreamBufferSize = 4096; private const int MinBufferSize = 128; // Bit bucket - Null has no backing store. Non closable. @@ -156,7 +155,7 @@ public StreamWriter(string path, FileStreamOptions options) } public StreamWriter(string path, Encoding? encoding, FileStreamOptions options) - : this(ValidateArgsAndOpenPath(path, options), encoding, DefaultFileStreamBufferSize) + : this(ValidateArgsAndOpenPath(path, options), encoding, DefaultBufferSize) { } @@ -183,10 +182,15 @@ private static FileStream ValidateArgsAndOpenPath(string path, FileStreamOptions private static FileStream ValidateArgsAndOpenPath(string path, bool append, int bufferSize) { + if (bufferSize == -1) + { + bufferSize = DefaultBufferSize; + } + ArgumentException.ThrowIfNullOrEmpty(path); ArgumentOutOfRangeException.ThrowIfNegativeOrZero(bufferSize); - return new FileStream(path, append ? FileMode.Append : FileMode.Create, FileAccess.Write, FileShare.Read, DefaultFileStreamBufferSize); + return new FileStream(path, append ? FileMode.Append : FileMode.Create, FileAccess.Write, FileShare.Read, FileStream.DefaultBufferSize); } public override void Close() diff --git a/src/libraries/System.Runtime/tests/System.IO.Tests/StreamReader/StreamReader.StringCtorTests.cs b/src/libraries/System.Runtime/tests/System.IO.Tests/StreamReader/StreamReader.StringCtorTests.cs index 4cab5d2134290e..edda927ae10051 100644 --- a/src/libraries/System.Runtime/tests/System.IO.Tests/StreamReader/StreamReader.StringCtorTests.cs +++ b/src/libraries/System.Runtime/tests/System.IO.Tests/StreamReader/StreamReader.StringCtorTests.cs @@ -50,10 +50,16 @@ public static void NullEncodingParamInCtor_ShouldNotThrowException() [Fact] public static void NegativeBufferSize_ThrowsArgumentOutOfRangeException() { - AssertExtensions.Throws("bufferSize", () => new StreamReader("path", Encoding.UTF8, true, -1)); + AssertExtensions.Throws("bufferSize", () => new StreamReader("path", Encoding.UTF8, true, -2)); AssertExtensions.Throws("bufferSize", () => new StreamReader("path", Encoding.UTF8, true, 0)); } + [Fact] + public static void NegativeOneBufferSize_ShouldNotThrowException() + { + StreamReader streamReaderTest = new StreamReader("path", Encoding.UTF8, true, -1); + } + [Fact] public static void LackOfReadAccess_ThrowsArgumentException() { diff --git a/src/libraries/System.Runtime/tests/System.IO.Tests/StreamWriter/StreamWriter.StringCtorTests.cs b/src/libraries/System.Runtime/tests/System.IO.Tests/StreamWriter/StreamWriter.StringCtorTests.cs index ec94e8cb606372..f252065a67cbeb 100644 --- a/src/libraries/System.Runtime/tests/System.IO.Tests/StreamWriter/StreamWriter.StringCtorTests.cs +++ b/src/libraries/System.Runtime/tests/System.IO.Tests/StreamWriter/StreamWriter.StringCtorTests.cs @@ -37,10 +37,16 @@ public static void EmptyPath_ThrowsArgumentException() [Fact] public static void NegativeBufferSize_ThrowsArgumentOutOfRangeException() { - AssertExtensions.Throws("bufferSize", () => new StreamWriter("path", false, Encoding.UTF8, -1)); + AssertExtensions.Throws("bufferSize", () => new StreamWriter("path", false, Encoding.UTF8, -2)); AssertExtensions.Throws("bufferSize", () => new StreamWriter("path", true, Encoding.UTF8, 0)); } + [Fact] + public static void NegativeOneBufferSize_ShouldNotThrowException() + { + StreamWriter streamWriterTest = new StreamWriter("path", false, Encoding.UTF8, -1); + } + [Fact] public static void LackOfWriteAccess_ThrowsArgumentException() { From ba2752b90030b08393b1cf2681fe98d9b82e3cfc Mon Sep 17 00:00:00 2001 From: Cloudea <2025140062@qq.com> Date: Fri, 22 Aug 2025 08:46:55 +0800 Subject: [PATCH 2/7] Fix path missing error in StringCtorTests of StreamReader and StreamWriter --- .../StreamReader/StreamReader.StringCtorTests.cs | 13 ++++++++++++- .../StreamWriter/StreamWriter.StringCtorTests.cs | 13 ++++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Runtime/tests/System.IO.Tests/StreamReader/StreamReader.StringCtorTests.cs b/src/libraries/System.Runtime/tests/System.IO.Tests/StreamReader/StreamReader.StringCtorTests.cs index edda927ae10051..aea7a4c269cd5f 100644 --- a/src/libraries/System.Runtime/tests/System.IO.Tests/StreamReader/StreamReader.StringCtorTests.cs +++ b/src/libraries/System.Runtime/tests/System.IO.Tests/StreamReader/StreamReader.StringCtorTests.cs @@ -57,7 +57,18 @@ public static void NegativeBufferSize_ThrowsArgumentOutOfRangeException() [Fact] public static void NegativeOneBufferSize_ShouldNotThrowException() { - StreamReader streamReaderTest = new StreamReader("path", Encoding.UTF8, true, -1); + string testfile = Path.GetTempFileName(); + try + { + using (var sr = new StreamReader(testfile, Encoding.UTF8, true, -1)) + { + Assert.NotNull(sr); + } + } + finally + { + File.Delete(testfile); + } } [Fact] diff --git a/src/libraries/System.Runtime/tests/System.IO.Tests/StreamWriter/StreamWriter.StringCtorTests.cs b/src/libraries/System.Runtime/tests/System.IO.Tests/StreamWriter/StreamWriter.StringCtorTests.cs index f252065a67cbeb..592a548a16d350 100644 --- a/src/libraries/System.Runtime/tests/System.IO.Tests/StreamWriter/StreamWriter.StringCtorTests.cs +++ b/src/libraries/System.Runtime/tests/System.IO.Tests/StreamWriter/StreamWriter.StringCtorTests.cs @@ -44,7 +44,18 @@ public static void NegativeBufferSize_ThrowsArgumentOutOfRangeException() [Fact] public static void NegativeOneBufferSize_ShouldNotThrowException() { - StreamWriter streamWriterTest = new StreamWriter("path", false, Encoding.UTF8, -1); + string testfile = Path.GetTempFileName(); + try + { + using (StreamWriter sw = new StreamWriter("path", false, Encoding.UTF8, -1)) + { + Assert.NotNull(sw); + } + } + finally + { + File.Delete(testfile); + } } [Fact] From 73e78816774058d227660d7207fe057121b7c8dc Mon Sep 17 00:00:00 2001 From: Cloudea Date: Fri, 22 Aug 2025 21:02:01 +0800 Subject: [PATCH 3/7] Fix a param error in StreamWriter.StringCtorTests.cs --- .../StreamWriter/StreamWriter.StringCtorTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Runtime/tests/System.IO.Tests/StreamWriter/StreamWriter.StringCtorTests.cs b/src/libraries/System.Runtime/tests/System.IO.Tests/StreamWriter/StreamWriter.StringCtorTests.cs index 592a548a16d350..c1a1fff544038c 100644 --- a/src/libraries/System.Runtime/tests/System.IO.Tests/StreamWriter/StreamWriter.StringCtorTests.cs +++ b/src/libraries/System.Runtime/tests/System.IO.Tests/StreamWriter/StreamWriter.StringCtorTests.cs @@ -47,7 +47,7 @@ public static void NegativeOneBufferSize_ShouldNotThrowException() string testfile = Path.GetTempFileName(); try { - using (StreamWriter sw = new StreamWriter("path", false, Encoding.UTF8, -1)) + using (StreamWriter sw = new StreamWriter(testfile, false, Encoding.UTF8, -1)) { Assert.NotNull(sw); } From e1afb42887e41c2bab221dc2bda83766a348e01b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviana=20Due=C3=B1as?= <50237907+ViveliDuCh@users.noreply.github.com> Date: Wed, 17 Sep 2025 16:15:03 -0700 Subject: [PATCH 4/7] PR change suggestions --- .../src/System/IO/StreamReader.cs | 16 +++++++--------- .../src/System/IO/StreamWriter.cs | 14 ++++++-------- 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/StreamReader.cs b/src/libraries/System.Private.CoreLib/src/System/IO/StreamReader.cs index 5031f3340adbd5..254fefacd24a11 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/StreamReader.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/StreamReader.cs @@ -122,7 +122,7 @@ public StreamReader(Stream stream, Encoding? encoding, bool detectEncodingFromBy // Creates a new StreamReader for the given stream. The // character encoding is set by encoding and the buffer size, - // in number of 16-bit characters, is set by bufferSize. + // in bytes, is set by bufferSize. // // Note that detectEncodingFromByteOrderMarks is a very // loose attempt at detecting the encoding by looking at the first @@ -147,11 +147,10 @@ public StreamReader(Stream stream, Encoding? encoding = null, bool detectEncodin throw new ArgumentException(SR.Argument_StreamNotReadable); } - if (bufferSize == -1) + if (bufferSize != -1) { - bufferSize = DefaultBufferSize; + ArgumentOutOfRangeException.ThrowIfNegativeOrZero(bufferSize); } - ArgumentOutOfRangeException.ThrowIfNegativeOrZero(bufferSize); _stream = stream; _encoding = encoding ??= Encoding.UTF8; @@ -225,14 +224,13 @@ private static FileStream ValidateArgsAndOpenPath(string path, FileStreamOptions private static FileStream ValidateArgsAndOpenPath(string path, int bufferSize) { - if (bufferSize == -1) + ArgumentException.ThrowIfNullOrEmpty(path); + + if (bufferSize != -1) { - bufferSize = DefaultBufferSize; + ArgumentOutOfRangeException.ThrowIfNegativeOrZero(bufferSize); } - ArgumentException.ThrowIfNullOrEmpty(path); - ArgumentOutOfRangeException.ThrowIfNegativeOrZero(bufferSize); - return new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, FileStream.DefaultBufferSize); } diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/StreamWriter.cs b/src/libraries/System.Private.CoreLib/src/System/IO/StreamWriter.cs index cd8f577f989dc0..ca6e45f621e432 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/StreamWriter.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/StreamWriter.cs @@ -103,11 +103,10 @@ public StreamWriter(Stream stream, Encoding? encoding = null, int bufferSize = - throw new ArgumentException(SR.Argument_StreamNotWritable); } - if (bufferSize == -1) + if (bufferSize != -1) { - bufferSize = DefaultBufferSize; + ArgumentOutOfRangeException.ThrowIfNegativeOrZero(bufferSize); } - ArgumentOutOfRangeException.ThrowIfNegativeOrZero(bufferSize); _stream = stream; _encoding = encoding ?? UTF8NoBOM; @@ -182,14 +181,13 @@ private static FileStream ValidateArgsAndOpenPath(string path, FileStreamOptions private static FileStream ValidateArgsAndOpenPath(string path, bool append, int bufferSize) { - if (bufferSize == -1) + ArgumentException.ThrowIfNullOrEmpty(path); + + if (bufferSize != -1) { - bufferSize = DefaultBufferSize; + ArgumentOutOfRangeException.ThrowIfNegativeOrZero(bufferSize); } - ArgumentException.ThrowIfNullOrEmpty(path); - ArgumentOutOfRangeException.ThrowIfNegativeOrZero(bufferSize); - return new FileStream(path, append ? FileMode.Append : FileMode.Create, FileAccess.Write, FileShare.Read, FileStream.DefaultBufferSize); } From e937c9d55f8d8632e7bf67dfaf9ff48c1a9d9798 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviana=20Due=C3=B1as?= <50237907+ViveliDuCh@users.noreply.github.com> Date: Wed, 17 Sep 2025 16:27:49 -0700 Subject: [PATCH 5/7] Revert change for constructors --- .../System.Private.CoreLib/src/System/IO/StreamReader.cs | 5 +++-- .../System.Private.CoreLib/src/System/IO/StreamWriter.cs | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/StreamReader.cs b/src/libraries/System.Private.CoreLib/src/System/IO/StreamReader.cs index 254fefacd24a11..38e6f5fc80b1eb 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/StreamReader.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/StreamReader.cs @@ -147,10 +147,11 @@ public StreamReader(Stream stream, Encoding? encoding = null, bool detectEncodin throw new ArgumentException(SR.Argument_StreamNotReadable); } - if (bufferSize != -1) + if (bufferSize == -1) { - ArgumentOutOfRangeException.ThrowIfNegativeOrZero(bufferSize); + bufferSize = DefaultBufferSize; } + ArgumentOutOfRangeException.ThrowIfNegativeOrZero(bufferSize); _stream = stream; _encoding = encoding ??= Encoding.UTF8; diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/StreamWriter.cs b/src/libraries/System.Private.CoreLib/src/System/IO/StreamWriter.cs index ca6e45f621e432..76b46b1a764f9d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/StreamWriter.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/StreamWriter.cs @@ -103,10 +103,11 @@ public StreamWriter(Stream stream, Encoding? encoding = null, int bufferSize = - throw new ArgumentException(SR.Argument_StreamNotWritable); } - if (bufferSize != -1) + if (bufferSize == -1) { - ArgumentOutOfRangeException.ThrowIfNegativeOrZero(bufferSize); + bufferSize = DefaultBufferSize; } + ArgumentOutOfRangeException.ThrowIfNegativeOrZero(bufferSize); _stream = stream; _encoding = encoding ?? UTF8NoBOM; From 32363a4f83da5a958c0342eb75ec555047f76c40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviana=20Due=C3=B1as?= <50237907+ViveliDuCh@users.noreply.github.com> Date: Thu, 18 Sep 2025 11:27:07 -0700 Subject: [PATCH 6/7] Fix whitespace --- .../System.Private.CoreLib/src/System/IO/StreamReader.cs | 2 +- .../System.Private.CoreLib/src/System/IO/StreamWriter.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/StreamReader.cs b/src/libraries/System.Private.CoreLib/src/System/IO/StreamReader.cs index 38e6f5fc80b1eb..e06a2512264c8d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/StreamReader.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/StreamReader.cs @@ -226,7 +226,7 @@ private static FileStream ValidateArgsAndOpenPath(string path, FileStreamOptions private static FileStream ValidateArgsAndOpenPath(string path, int bufferSize) { ArgumentException.ThrowIfNullOrEmpty(path); - + if (bufferSize != -1) { ArgumentOutOfRangeException.ThrowIfNegativeOrZero(bufferSize); diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/StreamWriter.cs b/src/libraries/System.Private.CoreLib/src/System/IO/StreamWriter.cs index 76b46b1a764f9d..4f370df7937b0f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/StreamWriter.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/StreamWriter.cs @@ -183,7 +183,7 @@ private static FileStream ValidateArgsAndOpenPath(string path, FileStreamOptions private static FileStream ValidateArgsAndOpenPath(string path, bool append, int bufferSize) { ArgumentException.ThrowIfNullOrEmpty(path); - + if (bufferSize != -1) { ArgumentOutOfRangeException.ThrowIfNegativeOrZero(bufferSize); From 23ecb09f59961f63a6e7a701fff40bf3e5f2b5a4 Mon Sep 17 00:00:00 2001 From: Cloudea Date: Fri, 19 Sep 2025 10:13:40 +0800 Subject: [PATCH 7/7] Add buffer size test in stream ctor tests --- .../StreamReader/StreamReader.CtorTests.cs | 28 +++++++++++++++++++ .../StreamWriter/StreamWriter.CtorTests.cs | 28 +++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/src/libraries/System.Runtime/tests/System.IO.Tests/StreamReader/StreamReader.CtorTests.cs b/src/libraries/System.Runtime/tests/System.IO.Tests/StreamReader/StreamReader.CtorTests.cs index c7bf35f44eced1..3522d8b94be31c 100644 --- a/src/libraries/System.Runtime/tests/System.IO.Tests/StreamReader/StreamReader.CtorTests.cs +++ b/src/libraries/System.Runtime/tests/System.IO.Tests/StreamReader/StreamReader.CtorTests.cs @@ -68,6 +68,34 @@ byte[] GetEncodedDataWithPreamble(byte[] data, Encoding encoding) => encoding.GetPreamble().Concat(data).ToArray(); } + [Fact] + public static void NegativeBufferSize_ThrowsArgumentOutOfRangeException() + { + var ms2 = new MemoryStream(); + + AssertExtensions.Throws("bufferSize", () => new StreamReader(ms2, bufferSize: -2)); + AssertExtensions.Throws("bufferSize", () => new StreamReader(ms2, bufferSize: 0)); + + ms2.Dispose(); + } + + [Fact] + public static void NegativeOneBufferSize_ShouldNotThrowException() + { + var ms2 = new MemoryStream(); + try + { + using (var sr = new StreamReader(ms2, bufferSize: -1)) + { + Assert.NotNull(sr); + } + } + finally + { + ms2.Dispose(); + } + } + [Theory] [MemberData(nameof(EncodingsWithEncodedDataWithPreamble))] public static void CreationFromMemoryStreamWithEncodingTrueDetectsCorrectEncodingWhenPreambleAvailable(Encoding expectedEncoding, byte[] encodedData, string expectedOutput) diff --git a/src/libraries/System.Runtime/tests/System.IO.Tests/StreamWriter/StreamWriter.CtorTests.cs b/src/libraries/System.Runtime/tests/System.IO.Tests/StreamWriter/StreamWriter.CtorTests.cs index bf0075139e699d..936e811bbcff5a 100644 --- a/src/libraries/System.Runtime/tests/System.IO.Tests/StreamWriter/StreamWriter.CtorTests.cs +++ b/src/libraries/System.Runtime/tests/System.IO.Tests/StreamWriter/StreamWriter.CtorTests.cs @@ -70,5 +70,33 @@ private static void TestEncoding(System.Text.Encoding? encoding, string testStri str2 = sr2.ReadToEnd(); Assert.Equal(testString, str2); } + + [Fact] + public static void NegativeBufferSize_ThrowsArgumentOutOfRangeException() + { + var ms2 = new MemoryStream(); + + AssertExtensions.Throws("bufferSize", () => new StreamWriter(ms2, bufferSize: -2)); + AssertExtensions.Throws("bufferSize", () => new StreamWriter(ms2, bufferSize: 0)); + + ms2.Dispose(); + } + + [Fact] + public static void NegativeOneBufferSize_ShouldNotThrowException() + { + var ms2 = new MemoryStream(); + try + { + using (var sw = new StreamWriter(ms2, bufferSize: -1)) + { + Assert.NotNull(sw); + } + } + finally + { + ms2.Dispose(); + } + } } }