diff --git a/src/libraries/System.IO.FileSystem/tests/File/Open.cs b/src/libraries/System.IO.FileSystem/tests/File/Open.cs index 3a042d8a65b9e..d014cf0efb94d 100644 --- a/src/libraries/System.IO.FileSystem/tests/File/Open.cs +++ b/src/libraries/System.IO.FileSystem/tests/File/Open.cs @@ -42,6 +42,42 @@ protected override FileStream CreateFileStream(string path, FileMode mode, FileA } } + public class File_Open_str_options_as : FileStream_ctor_options_as + { + protected override FileStream CreateFileStream(string path, FileMode mode) + { + return File.Open(path, + new FileStreamOptions { + Mode = mode, + Access = mode == FileMode.Append ? FileAccess.Write : FileAccess.ReadWrite, + PreallocationSize = PreallocationSize + }); + } + + protected override FileStream CreateFileStream(string path, FileMode mode, FileAccess access) + { + return File.Open(path, + new FileStreamOptions { + Mode = mode, + Access = access, + PreallocationSize = PreallocationSize + }); + } + + protected override FileStream CreateFileStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options) + { + return File.Open(path, + new FileStreamOptions { + Mode = mode, + Access = access, + Share = share, + Options = options, + BufferSize = bufferSize, + PreallocationSize = PreallocationSize + }); + } + } + public class File_OpenSpecial : FileStream_ctor_str_fm_fa_fs { protected override FileStream CreateFileStream(string path, FileMode mode, FileAccess access) diff --git a/src/libraries/System.IO.FileSystem/tests/FileInfo/Open.cs b/src/libraries/System.IO.FileSystem/tests/FileInfo/Open.cs index 1401b8b2fef35..2324a92eafce4 100644 --- a/src/libraries/System.IO.FileSystem/tests/FileInfo/Open.cs +++ b/src/libraries/System.IO.FileSystem/tests/FileInfo/Open.cs @@ -74,6 +74,42 @@ protected override FileStream CreateFileStream(string path, FileMode mode, FileA } } + public class FileInfo_Open_options_as : FileStream_ctor_options_as + { + protected override FileStream CreateFileStream(string path, FileMode mode) + { + return new FileInfo(path).Open( + new FileStreamOptions { + Mode = mode, + Access = mode == FileMode.Append ? FileAccess.Write : FileAccess.ReadWrite, + PreallocationSize = PreallocationSize + }); + } + + protected override FileStream CreateFileStream(string path, FileMode mode, FileAccess access) + { + return new FileInfo(path).Open( + new FileStreamOptions { + Mode = mode, + Access = access, + PreallocationSize = PreallocationSize + }); + } + + protected override FileStream CreateFileStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options) + { + return new FileInfo(path).Open( + new FileStreamOptions { + Mode = mode, + Access = access, + Share = share, + Options = options, + BufferSize = bufferSize, + PreallocationSize = PreallocationSize + }); + } + } + public class FileInfo_OpenSpecial : FileStream_ctor_str_fm_fa_fs { protected override FileStream CreateFileStream(string path, FileMode mode, FileAccess access) diff --git a/src/libraries/System.IO/tests/StreamReader/StreamReader.StringCtorTests.cs b/src/libraries/System.IO/tests/StreamReader/StreamReader.StringCtorTests.cs index 51a8122a444fe..d4c7ac4ad847f 100644 --- a/src/libraries/System.IO/tests/StreamReader/StreamReader.StringCtorTests.cs +++ b/src/libraries/System.IO/tests/StreamReader/StreamReader.StringCtorTests.cs @@ -14,12 +14,18 @@ public class StreamReader_StringCtorTests public static void NullArgs_ThrowsArgumentNullException() { AssertExtensions.Throws("path", () => new StreamReader((string)null)); - AssertExtensions.Throws("path", () => new StreamReader((string)null, null)); + AssertExtensions.Throws("path", () => new StreamReader((string)null, (FileStreamOptions)null)); + AssertExtensions.Throws("path", () => new StreamReader((string)null, (Encoding)null)); AssertExtensions.Throws("path", () => new StreamReader((string)null, null, true)); + AssertExtensions.Throws("path", () => new StreamReader((string)null, null, true, null)); AssertExtensions.Throws("path", () => new StreamReader((string)null, null, true, -1)); - AssertExtensions.Throws("encoding", () => new StreamReader("", null)); + AssertExtensions.Throws("encoding", () => new StreamReader("", (Encoding)null)); AssertExtensions.Throws("encoding", () => new StreamReader("", null, true)); + AssertExtensions.Throws("encoding", () => new StreamReader("", null, true, null)); AssertExtensions.Throws("encoding", () => new StreamReader("", null, true, -1)); + AssertExtensions.Throws("options", () => new StreamReader("path", (FileStreamOptions)null)); + AssertExtensions.Throws("options", () => new StreamReader("path", Encoding.UTF8, true, null)); + } [Fact] @@ -27,8 +33,10 @@ public static void EmptyPath_ThrowsArgumentException() { // No argument name for the empty path exception AssertExtensions.Throws(null, () => new StreamReader("")); + AssertExtensions.Throws(null, () => new StreamReader("", new FileStreamOptions())); AssertExtensions.Throws(null, () => new StreamReader("", Encoding.UTF8)); AssertExtensions.Throws(null, () => new StreamReader("", Encoding.UTF8, true)); + AssertExtensions.Throws(null, () => new StreamReader("", Encoding.UTF8, true, new FileStreamOptions())); AssertExtensions.Throws(null, () => new StreamReader("", Encoding.UTF8, true, -1)); } diff --git a/src/libraries/System.IO/tests/StreamReader/StreamReader.cs b/src/libraries/System.IO/tests/StreamReader/StreamReader.cs index 8fe7e4d2ba7bb..bd455448efcca 100644 --- a/src/libraries/System.IO/tests/StreamReader/StreamReader.cs +++ b/src/libraries/System.IO/tests/StreamReader/StreamReader.cs @@ -72,5 +72,30 @@ public void DetectEncoding_EncodingRoundtrips(Encoding encoding) Assert.Equal(encoding.EncodingName, reader.CurrentEncoding.EncodingName); } } + + [Theory] + [MemberData(nameof(DetectEncoding_EncodingRoundtrips_MemberData))] + public void DetectEncoding_EncodingRoundtrips_Path(Encoding encoding) + { + const string Text = "This is some text for testing."; + string path = GetTestFilePath(); + + using (var writer = new StreamWriter(path, false, encoding)) + { + writer.Write(Text); + } + + using (var reader = new StreamReader(path, detectEncodingFromByteOrderMarks: true)) + { + Assert.Equal(Text, reader.ReadToEnd()); + Assert.Equal(encoding.EncodingName, reader.CurrentEncoding.EncodingName); + } + + using (var reader = new StreamReader(path, encoding)) + { + Assert.Equal(Text, reader.ReadToEnd()); + Assert.Equal(encoding.EncodingName, reader.CurrentEncoding.EncodingName); + } + } } } diff --git a/src/libraries/System.IO/tests/StreamWriter/StreamWriter.StringCtorTests.cs b/src/libraries/System.IO/tests/StreamWriter/StreamWriter.StringCtorTests.cs index cf00dfc9df327..95041cd56503a 100644 --- a/src/libraries/System.IO/tests/StreamWriter/StreamWriter.StringCtorTests.cs +++ b/src/libraries/System.IO/tests/StreamWriter/StreamWriter.StringCtorTests.cs @@ -15,12 +15,15 @@ public class StreamWriter_StringCtorTests public static void NullArgs_ThrowsArgumentNullException() { AssertExtensions.Throws("path", () => new StreamWriter((string)null)); + AssertExtensions.Throws("path", () => new StreamWriter((string)null, null)); AssertExtensions.Throws("path", () => new StreamWriter((string)null, true)); AssertExtensions.Throws("path", () => new StreamWriter((string)null, true, null)); AssertExtensions.Throws("path", () => new StreamWriter((string)null, true, null, -1)); AssertExtensions.Throws("encoding", () => new StreamWriter("path", true, null)); + AssertExtensions.Throws("encoding", () => new StreamWriter("path", null, null)); AssertExtensions.Throws("encoding", () => new StreamWriter("path", true, null, -1)); AssertExtensions.Throws("encoding", () => new StreamWriter("", true, null)); + AssertExtensions.Throws("encoding", () => new StreamWriter("", null, null)); AssertExtensions.Throws("encoding", () => new StreamWriter("", true, null, -1)); } @@ -29,8 +32,10 @@ public static void EmptyPath_ThrowsArgumentException() { // No argument name for the empty path exception AssertExtensions.Throws(null, () => new StreamWriter("")); + AssertExtensions.Throws(null, () => new StreamWriter("", new FileStreamOptions())); AssertExtensions.Throws(null, () => new StreamWriter("", true)); AssertExtensions.Throws(null, () => new StreamWriter("", true, Encoding.UTF8)); + AssertExtensions.Throws(null, () => new StreamWriter("", Encoding.UTF8, new FileStreamOptions())); AssertExtensions.Throws(null, () => new StreamWriter("", true, Encoding.UTF8, -1)); } diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems index bbbd804c83e6f..ba9fe6acfd0a8 100644 --- a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems +++ b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems @@ -407,9 +407,11 @@ + + diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/File.cs b/src/libraries/System.Private.CoreLib/src/System/IO/File.cs index c8f63b8b32d89..bfd16b8cfb99c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/File.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/File.cs @@ -21,7 +21,7 @@ namespace System.IO { // Class for creating FileStream objects, and some basic file management // routines such as Delete, etc. - public static class File + public static partial class File { private const int MaxByteArrayLength = 0x7FFFFFC7; private static Encoding? s_UTF8NoBOM; @@ -262,8 +262,7 @@ public static FileStream OpenRead(string path) public static FileStream OpenWrite(string path) { - return new FileStream(path, FileMode.OpenOrCreate, - FileAccess.Write, FileShare.None); + return new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None); } public static string ReadAllText(string path) diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/File.netcoreapp.cs b/src/libraries/System.Private.CoreLib/src/System/IO/File.netcoreapp.cs new file mode 100644 index 0000000000000..1996833ae40c3 --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/IO/File.netcoreapp.cs @@ -0,0 +1,14 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.IO +{ + public static partial class File + { + /// + /// Initializes a new instance of the class with the specified path, creation mode, read/write and sharing permission, the access other FileStreams can have to the same file, the buffer size, additional file options and the allocation size. + /// + /// for information about exceptions. + public static FileStream Open(string path, FileStreamOptions options) => new FileStream(path, options); + } +} diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/FileInfo.cs b/src/libraries/System.Private.CoreLib/src/System/IO/FileInfo.cs index fc391cdf81475..c7401018a8381 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/FileInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/FileInfo.cs @@ -122,7 +122,7 @@ public FileStream Open(FileMode mode, FileAccess access, FileShare share) => new FileStream(NormalizedPath, mode, access, share); public FileStream OpenRead() - => new FileStream(NormalizedPath, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, false); + => new FileStream(NormalizedPath, FileMode.Open, FileAccess.Read, FileShare.Read, File.DefaultBufferSize, false); public FileStream OpenWrite() => new FileStream(NormalizedPath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None); diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/FileInfo.netcoreapp.cs b/src/libraries/System.Private.CoreLib/src/System/IO/FileInfo.netcoreapp.cs new file mode 100644 index 0000000000000..4c6c5f343e24f --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/IO/FileInfo.netcoreapp.cs @@ -0,0 +1,14 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.IO +{ + public sealed partial class FileInfo : FileSystemInfo + { + /// + /// Initializes a new instance of the class with the specified creation mode, read/write and sharing permission, the access other FileStreams can have to the same file, the buffer size, additional file options and the allocation size. + /// + /// for information about exceptions. + public FileStream Open(FileStreamOptions options) => File.Open(NormalizedPath, options); + } +} 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 2e2821a2b17d6..af35711a682d0 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/StreamReader.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/StreamReader.cs @@ -193,12 +193,40 @@ public StreamReader(string path, Encoding encoding, bool detectEncodingFromByteO { } - public StreamReader(string path, Encoding encoding, bool detectEncodingFromByteOrderMarks, int bufferSize) : - this(ValidateArgsAndOpenPath(path, encoding, bufferSize), encoding, detectEncodingFromByteOrderMarks, bufferSize, leaveOpen: false) + public StreamReader(string path, Encoding encoding, bool detectEncodingFromByteOrderMarks, int bufferSize) + : this(ValidateArgsAndOpenPath(path, encoding, bufferSize), encoding, detectEncodingFromByteOrderMarks, bufferSize, leaveOpen: false) { } + public StreamReader(string path, FileStreamOptions options) + : this(path, Encoding.UTF8, true, options) + { + } + + public StreamReader(string path, Encoding encoding, bool detectEncodingFromByteOrderMarks, FileStreamOptions options) + : this(ValidateArgsAndOpenPath(path, encoding, options), encoding, detectEncodingFromByteOrderMarks, DefaultBufferSize) + { + } + + private static Stream ValidateArgsAndOpenPath(string path, Encoding encoding, FileStreamOptions options) + { + ValidateArgs(path, encoding); + if (options == null) + throw new ArgumentNullException(nameof(options)); + + return new FileStream(path, options); + } + private static Stream ValidateArgsAndOpenPath(string path, Encoding encoding, int bufferSize) + { + ValidateArgs(path, encoding); + if (bufferSize <= 0) + throw new ArgumentOutOfRangeException(nameof(bufferSize), SR.ArgumentOutOfRange_NeedPosNum); + + return new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, DefaultFileStreamBufferSize); + } + + private static void ValidateArgs(string path, Encoding encoding) { if (path == null) throw new ArgumentNullException(nameof(path)); @@ -206,10 +234,6 @@ private static Stream ValidateArgsAndOpenPath(string path, Encoding encoding, in throw new ArgumentNullException(nameof(encoding)); if (path.Length == 0) throw new ArgumentException(SR.Argument_EmptyPath); - if (bufferSize <= 0) - throw new ArgumentOutOfRangeException(nameof(bufferSize), SR.ArgumentOutOfRange_NeedPosNum); - - return new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, DefaultFileStreamBufferSize, FileOptions.SequentialScan); } 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 875211723da6b..96ac62fd51dd4 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/StreamWriter.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/StreamWriter.cs @@ -154,7 +154,35 @@ public StreamWriter(string path, bool append, Encoding encoding) { } + public StreamWriter(string path, FileStreamOptions options) + : this(path, UTF8NoBOM, options) + { + } + + public StreamWriter(string path, Encoding encoding, FileStreamOptions options) + : this(ValidateArgsAndOpenPath(path, encoding, options), encoding, DefaultFileStreamBufferSize) + { + } + + private static Stream ValidateArgsAndOpenPath(string path, Encoding encoding, FileStreamOptions options) + { + ValidateArgs(path, encoding); + if (options == null) + throw new ArgumentNullException(nameof(options)); + + return new FileStream(path, options); + } + private static Stream ValidateArgsAndOpenPath(string path, bool append, Encoding encoding, int bufferSize) + { + ValidateArgs(path, encoding); + if (bufferSize <= 0) + throw new ArgumentOutOfRangeException(nameof(bufferSize), SR.ArgumentOutOfRange_NeedPosNum); + + return new FileStream(path, append ? FileMode.Append : FileMode.Create, FileAccess.Write, FileShare.Read, DefaultFileStreamBufferSize); + } + + private static void ValidateArgs(string path, Encoding encoding) { if (path == null) throw new ArgumentNullException(nameof(path)); @@ -162,10 +190,6 @@ private static Stream ValidateArgsAndOpenPath(string path, bool append, Encoding throw new ArgumentNullException(nameof(encoding)); if (path.Length == 0) throw new ArgumentException(SR.Argument_EmptyPath); - if (bufferSize <= 0) - throw new ArgumentOutOfRangeException(nameof(bufferSize), SR.ArgumentOutOfRange_NeedPosNum); - - return new FileStream(path, append ? FileMode.Append : FileMode.Create, FileAccess.Write, FileShare.Read, DefaultFileStreamBufferSize, FileOptions.SequentialScan); } public override void Close() diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index ba30ccf66a0aa..adc2dde2f8fc3 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -7564,6 +7564,7 @@ public static partial class File public static System.IO.FileStream Open(string path, System.IO.FileMode mode) { throw null; } public static System.IO.FileStream Open(string path, System.IO.FileMode mode, System.IO.FileAccess access) { throw null; } public static System.IO.FileStream Open(string path, System.IO.FileMode mode, System.IO.FileAccess access, System.IO.FileShare share) { throw null; } + public static System.IO.FileStream Open(string path, System.IO.FileStreamOptions options) { throw null; } public static System.IO.FileStream OpenRead(string path) { throw null; } public static System.IO.StreamReader OpenText(string path) { throw null; } public static System.IO.FileStream OpenWrite(string path) { throw null; } @@ -7625,6 +7626,7 @@ public sealed partial class FileInfo : System.IO.FileSystemInfo public System.IO.FileStream Open(System.IO.FileMode mode) { throw null; } public System.IO.FileStream Open(System.IO.FileMode mode, System.IO.FileAccess access) { throw null; } public System.IO.FileStream Open(System.IO.FileMode mode, System.IO.FileAccess access, System.IO.FileShare share) { throw null; } + public System.IO.FileStream Open(System.IO.FileStreamOptions options) { throw null; } public System.IO.FileStream OpenRead() { throw null; } public System.IO.StreamReader OpenText() { throw null; } public System.IO.FileStream OpenWrite() { throw null; } @@ -7821,10 +7823,12 @@ public partial class StreamReader : System.IO.TextReader public StreamReader(System.IO.Stream stream, System.Text.Encoding encoding, bool detectEncodingFromByteOrderMarks, int bufferSize) { } public StreamReader(System.IO.Stream stream, System.Text.Encoding? encoding = null, bool detectEncodingFromByteOrderMarks = true, int bufferSize = -1, bool leaveOpen = false) { } public StreamReader(string path) { } + public StreamReader(string path, System.IO.FileStreamOptions options) { } public StreamReader(string path, bool detectEncodingFromByteOrderMarks) { } public StreamReader(string path, System.Text.Encoding encoding) { } public StreamReader(string path, System.Text.Encoding encoding, bool detectEncodingFromByteOrderMarks) { } public StreamReader(string path, System.Text.Encoding encoding, bool detectEncodingFromByteOrderMarks, int bufferSize) { } + public StreamReader(string path, System.Text.Encoding encoding, bool detectEncodingFromByteOrderMarks, System.IO.FileStreamOptions options) { } public virtual System.IO.Stream BaseStream { get { throw null; } } public virtual System.Text.Encoding CurrentEncoding { get { throw null; } } public bool EndOfStream { get { throw null; } } @@ -7854,9 +7858,11 @@ public partial class StreamWriter : System.IO.TextWriter public StreamWriter(System.IO.Stream stream, System.Text.Encoding encoding, int bufferSize) { } public StreamWriter(System.IO.Stream stream, System.Text.Encoding? encoding = null, int bufferSize = -1, bool leaveOpen = false) { } public StreamWriter(string path) { } + public StreamWriter(string path, System.IO.FileStreamOptions options) { } public StreamWriter(string path, bool append) { } public StreamWriter(string path, bool append, System.Text.Encoding encoding) { } public StreamWriter(string path, bool append, System.Text.Encoding encoding, int bufferSize) { } + public StreamWriter(string path, System.Text.Encoding encoding, System.IO.FileStreamOptions options) { } public virtual bool AutoFlush { get { throw null; } set { } } public virtual System.IO.Stream BaseStream { get { throw null; } } public override System.Text.Encoding Encoding { get { throw null; } }