diff --git a/AsyncIO.Tests/AsyncIO.Tests.csproj b/AsyncIO.Tests/AsyncIO.Tests.csproj index aa0ff20..51e3508 100644 --- a/AsyncIO.Tests/AsyncIO.Tests.csproj +++ b/AsyncIO.Tests/AsyncIO.Tests.csproj @@ -51,6 +51,7 @@ + diff --git a/AsyncIO.Tests/FileSystem/FileTests.cs b/AsyncIO.Tests/FileSystem/FileTests.cs index cce7791..3f50b41 100644 --- a/AsyncIO.Tests/FileSystem/FileTests.cs +++ b/AsyncIO.Tests/FileSystem/FileTests.cs @@ -307,7 +307,7 @@ public async Task CopyAsync_CancellationToken_ExceptionThrown() [ExpectedException(typeof(TaskCanceledException))] public async Task CopyAsync_CancellationTokenOverwrite_ExceptionThrown() { - var contents = Enumerable.Repeat("This is a test line.", 150000).ToList(); + var contents = Enumerable.Repeat("This is a test line.", 300000).ToList(); var path = Path.Combine(TestFolder, "CopyAsync_Default_FileCopied"); Directory.CreateDirectory(TestFolder); @@ -317,7 +317,7 @@ public async Task CopyAsync_CancellationTokenOverwrite_ExceptionThrown() if (!File.Exists(copyPath)) File.Create(copyPath).Dispose(); - var tokenSource = new CancellationTokenSource(10); + var tokenSource = new CancellationTokenSource(30); await AsyncFile.CopyAsync(path, copyPath, true, tokenSource.Token); var result = File.ReadAllLines(copyPath); @@ -411,7 +411,7 @@ public async Task MoveAsync_Overwrite_ExceptionThrown() [ExpectedException(typeof(TaskCanceledException))] public async Task MoveAsync_CancellationToken_ExceptionThrown() { - var contents = Enumerable.Repeat("This is a test line.", 150000).ToList(); + var contents = Enumerable.Repeat("This is a test line.", 300000).ToList(); var path = Path.Combine(TestFolder, "MoveAsync_Default_FileMoved"); Directory.CreateDirectory(TestFolder); @@ -420,7 +420,7 @@ public async Task MoveAsync_CancellationToken_ExceptionThrown() var copyPath = "MoveAsync_Default_FileMoved_Copy"; File.Delete(copyPath); - var tokenSource = new CancellationTokenSource(10); + var tokenSource = new CancellationTokenSource(20); await AsyncFile.MoveAsync(path, copyPath, tokenSource.Token); var result = File.ReadAllLines(copyPath); @@ -447,5 +447,473 @@ public async Task MoveAsync_SamePath_FileMoved() } #endregion + + #region ReadAllBytesAsync Tests + + [TestMethod] + public async Task ReadAllBytesAsync_Default_BytesRead() + { + var bytes = new byte[10000]; + var random = new Random(); + random.NextBytes(bytes); + + var path = Path.Combine(TestFolder, "ReadAllBytesAsync_Default_BytesRead"); + Directory.CreateDirectory(TestFolder); + + File.WriteAllBytes(path, bytes); + + var result = await AsyncFile.ReadAllBytesAsync(path).ConfigureAwait(false); + + CollectionAssert.AreEqual(bytes, result); + } + + [TestMethod] + [ExpectedException(typeof (OperationCanceledException), AllowDerivedTypes = true)] + public async Task ReadAllBytesAsync_CancellationToken_BytesRead() + { + var bytes = new byte[100000]; + var random = new Random(); + random.NextBytes(bytes); + + var path = Path.Combine(TestFolder, "ReadAllBytesAsync_CancellationToken_BytesRead"); + Directory.CreateDirectory(TestFolder); + + File.WriteAllBytes(path, bytes); + + var tokenSource = new CancellationTokenSource(25); + var result = await AsyncFile.ReadAllBytesAsync(path, tokenSource.Token).ConfigureAwait(false); + + CollectionAssert.AreNotEqual(bytes, result); + } + + #endregion + + #region ReadAllLinesAsync Tests + + [TestMethod] + public async Task ReadAllLinesAsync_Default_LinesReaded() + { + var contents = Enumerable.Repeat("This is a test line.", 150).ToList(); + var path = Path.Combine(TestFolder, "ReadAllLinesAsync_Default_LinesReaded"); + + + Directory.CreateDirectory(TestFolder); + File.WriteAllLines(path, contents); + + var result = await AsyncFile.ReadAllLinesAsync(path).ConfigureAwait(false); + + CollectionAssert.AreEqual(contents, result); + } + + [TestMethod] + public async Task ReadAllLinesAsync_EncodingUtf8_LinesReaded() + { + await ReadAllLinesAsync_EncodingTest(Encoding.UTF8).ConfigureAwait(false); + } + + [TestMethod] + public async Task ReadAllLinesAsync_EncodingAscii_LinesReaded() + { + await ReadAllLinesAsync_EncodingTest(Encoding.ASCII).ConfigureAwait(false); + } + + [TestMethod] + public async Task ReadAllLinesAsync_EncodingBigEndianUnicode_LinesReaded() + { + await ReadAllLinesAsync_EncodingTest(Encoding.BigEndianUnicode).ConfigureAwait(false); + } + + [TestMethod] + public async Task ReadAllLinesAsync_EncodingUtf32_LinesReaded() + { + await ReadAllLinesAsync_EncodingTest(Encoding.UTF32).ConfigureAwait(false); + } + + [TestMethod] + public async Task ReadAllLinesAsync_EncodingUtf7_LinesReaded() + { + await ReadAllLinesAsync_EncodingTest(Encoding.UTF7).ConfigureAwait(false); + } + + [TestMethod] + public async Task ReadAllLinesAsync_EncodingUnicode_LinesReaded() + { + await ReadAllLinesAsync_EncodingTest(Encoding.Unicode).ConfigureAwait(false); + } + + [TestMethod] + [ExpectedException(typeof (OperationCanceledException))] + public async Task ReadAllLinesAsync_CancellationToken_ExceptionThrown() + { + var contents = Enumerable.Repeat("This is a test line.", 30000).ToList(); + var path = Path.Combine(TestFolder, "ReadAllLinesAsync_Default_LinesReaded"); + + + Directory.CreateDirectory(TestFolder); + File.WriteAllLines(path, contents); + + var tokenSource = new CancellationTokenSource(25); + var result = await AsyncFile.ReadAllLinesAsync(path, tokenSource.Token).ConfigureAwait(false); + + CollectionAssert.AreNotEqual(contents, result); + } + + [TestMethod] + [ExpectedException(typeof(ArgumentNullException))] + public async Task ReadAllLinesAsync_NullEncoding_ExceptionThrown() + { + var contents = Enumerable.Repeat("This is a test line.", 30000).ToList(); + var path = Path.Combine(TestFolder, "ReadAllLinesAsync_Default_LinesReaded"); + + + Directory.CreateDirectory(TestFolder); + File.WriteAllLines(path, contents); + + var result = await AsyncFile.ReadAllLinesAsync(path, null).ConfigureAwait(false); + } + + private async Task ReadAllLinesAsync_EncodingTest(Encoding encoding) + { + var contents = Enumerable.Repeat("This is a test line.", 150).ToList(); + var path = Path.Combine(TestFolder, "ReadAllLinesAsync_EncodingTest"); + Directory.CreateDirectory(TestFolder); + File.WriteAllLines(path, contents, encoding); + + var result = await AsyncFile.ReadAllLinesAsync(path, encoding).ConfigureAwait(false); + + CollectionAssert.AreEqual(contents, result); + } + + #endregion + + #region ReadAllTextAsync Tests + + [TestMethod] + public async Task ReadAllTextAsync_Default_LinesReaded() + { + var contents = string.Join(Environment.NewLine, Enumerable.Repeat("This is a test line.", 150)); + var path = Path.Combine(TestFolder, "ReadAllTextAsync_EncodingTest"); + Directory.CreateDirectory(TestFolder); + File.WriteAllText(path, contents); + + var result = await AsyncFile.ReadAllTextAsync(path).ConfigureAwait(false); + + Assert.AreEqual(contents, result); + } + + [TestMethod] + public async Task ReadAllTextAsync_EncodingUtf8_LinesReaded() + { + await ReadAllTextAsync_EncodingTest(Encoding.UTF8).ConfigureAwait(false); + } + + [TestMethod] + public async Task ReadAllTextAsync_EncodingAscii_LinesReaded() + { + await ReadAllTextAsync_EncodingTest(Encoding.ASCII).ConfigureAwait(false); + } + + [TestMethod] + public async Task ReadAllTextAsync_EncodingBigEndianUnicode_LinesReaded() + { + await ReadAllTextAsync_EncodingTest(Encoding.BigEndianUnicode).ConfigureAwait(false); + } + + [TestMethod] + public async Task ReadAllTextAsync_EncodingUtf32_LinesReaded() + { + await ReadAllTextAsync_EncodingTest(Encoding.UTF32).ConfigureAwait(false); + } + + [TestMethod] + public async Task ReadAllTextAsync_EncodingUtf7_LinesReaded() + { + await ReadAllTextAsync_EncodingTest(Encoding.UTF7).ConfigureAwait(false); + } + + [TestMethod] + public async Task ReadAllTextAsync_EncodingUnicode_LinesReaded() + { + await ReadAllTextAsync_EncodingTest(Encoding.Unicode).ConfigureAwait(false); + } + + [TestMethod] + [ExpectedException(typeof(ArgumentNullException))] + public async Task ReadAllTextAsync_NullEncoding_ExceptionThrown() + { + var contents = string.Join(Environment.NewLine, Enumerable.Repeat("This is a test line.", 150)); + var path = Path.Combine(TestFolder, "ReadAllTextAsync_EncodingTest"); + Directory.CreateDirectory(TestFolder); + File.WriteAllText(path, contents); + + var result = await AsyncFile.ReadAllTextAsync(path, null).ConfigureAwait(false); + } + + private async Task ReadAllTextAsync_EncodingTest(Encoding encoding) + { + var contents = string.Join(Environment.NewLine, Enumerable.Repeat("This is a test line.", 150)); + var path = Path.Combine(TestFolder, "ReadAllTextAsync_EncodingTest"); + Directory.CreateDirectory(TestFolder); + File.WriteAllText(path, contents, encoding); + + var result = await AsyncFile.ReadAllTextAsync(path, encoding).ConfigureAwait(false); + + Assert.AreEqual(contents, result); + } + + #endregion + + #region WriteAllBytesAsync Tests + + [TestMethod] + public async Task WriteAllBytesAsync_Default_BytesWritten() + { + var bytes = new byte[10000]; + var random = new Random(); + random.NextBytes(bytes); + + var path = Path.Combine(TestFolder, "WriteAllBytesAsync_Default_BytesWritten"); + Directory.CreateDirectory(TestFolder); + + await AsyncFile.WriteAllBytesAsync(path, bytes).ConfigureAwait(false); + + var result = File.ReadAllBytes(path); + + CollectionAssert.AreEqual(bytes, result); + } + + [TestMethod] + [ExpectedException(typeof(OperationCanceledException), AllowDerivedTypes = true)] + public async Task WriteAllBytesAsync_CancellationToken_BytesWritten() + { + var bytes = new byte[100000]; + var random = new Random(); + random.NextBytes(bytes); + + var path = Path.Combine(TestFolder, "WriteAllBytesAsync_CancellationToken_BytesWritten"); + Directory.CreateDirectory(TestFolder); + + var tokenSource = new CancellationTokenSource(15); + await AsyncFile.WriteAllBytesAsync(path, bytes, tokenSource.Token).ConfigureAwait(false); + + var result = File.ReadAllBytes(path); + + CollectionAssert.AreNotEqual(bytes, result); + } + + #endregion + + #region WriteAllLinesAsync Tests + + [TestMethod] + public async Task WriteAllLinesAsync_Default_LinesAppended() + { + var contents = Enumerable.Repeat("This is a test line.", 150).ToList(); + var path = Path.Combine(TestFolder, "WriteAllLinesAsync_Default_LinesAppended"); + + Directory.CreateDirectory(TestFolder); + + await AsyncFile.WriteAllLinesAsync(path, contents); + + var result = File.ReadAllLines(path); + + CollectionAssert.AreEqual(contents, result); + } + + [TestMethod] + public async Task WriteAllLinesAsync_EncodingAscii_LinesAppended() + { + await WriteAllLinesAsync_EncodingTest(Encoding.ASCII); + } + + [TestMethod] + public async Task WriteAllLinesAsync_EncodingUtf8_LinesAppended() + { + await WriteAllLinesAsync_EncodingTest(Encoding.UTF8); + } + + [TestMethod] + public async Task WriteAllLinesAsync_EncodingBigEndianUnicode_LinesAppended() + { + await WriteAllLinesAsync_EncodingTest(Encoding.BigEndianUnicode); + } + + [TestMethod] + public async Task WriteAllLinesAsync_EncodingDefault_LinesAppended() + { + await WriteAllLinesAsync_EncodingTest(Encoding.Default); + } + + [TestMethod] + public async Task WriteAllLinesAsync_EncodingUtf32_LinesAppended() + { + await WriteAllLinesAsync_EncodingTest(Encoding.UTF32); + } + + [TestMethod] + public async Task WriteAllLinesAsync_EncodingUtf7_LinesAppended() + { + await WriteAllLinesAsync_EncodingTest(Encoding.UTF7); + } + + [TestMethod] + public async Task WriteAllLinesAsync_EncodingUnicode_LinesAppended() + { + await WriteAllLinesAsync_EncodingTest(Encoding.Unicode); + } + + [TestMethod] + [ExpectedException(typeof(OperationCanceledException))] + public async Task WriteAllLinesAsync_CancellationToken_LinesAppended() + { + var contents = Enumerable.Repeat("This is a test line.", 30000).ToList(); + var path = Path.Combine(TestFolder, "WriteAllLinesAsync_Default_LinesAppended"); + Directory.CreateDirectory(TestFolder); + + var cancellationTokenSource = new CancellationTokenSource(20); + await AsyncFile.WriteAllLinesAsync(path, contents, cancellationTokenSource.Token); + + var result = File.ReadAllLines(path); + + Assert.IsTrue(contents.Count > result.Length); + } + + [TestMethod] + [ExpectedException(typeof(ArgumentNullException))] + public async Task WriteAllLinesAsync_NullContent_ExceptionThrown() + { + var contents = Enumerable.Repeat("This is a test line.", 150).ToList(); + var path = Path.Combine(TestFolder, "WriteAllLinesAsync_Default_LinesAppended"); + + Directory.CreateDirectory(TestFolder); + + await AsyncFile.WriteAllLinesAsync(path, null); + } + + [TestMethod] + [ExpectedException(typeof(ArgumentNullException))] + public async Task WriteAllLinesAsync_NullEncoding_ExceptionThrown() + { + var contents = Enumerable.Repeat("This is a test line.", 150).ToList(); + var path = Path.Combine(TestFolder, "WriteAllLinesAsync_Default_LinesAppended"); + + Directory.CreateDirectory(TestFolder); + + await AsyncFile.WriteAllLinesAsync(path, contents, null); + } + + private async Task WriteAllLinesAsync_EncodingTest(Encoding encoding) + { + var contents = Enumerable.Repeat("This is a test line.", 150).ToList(); + var path = Path.Combine(TestFolder, "WriteAllLinesAsync_Encoding_LinesAppended"); + Directory.CreateDirectory(TestFolder); + + await AsyncFile.WriteAllLinesAsync(path, contents, encoding); + + var result = File.ReadAllLines(path, encoding); + + CollectionAssert.AreEqual(contents, result); + } + + #endregion + + #region WriteAllTextAsync Tests + + [TestMethod] + public async Task WriteAllTextAsync_Default_TextAppended() + { + var contents = string.Join(Environment.NewLine, Enumerable.Repeat("This is a test line.", 150)); + var path = Path.Combine(TestFolder, "WriteAllTextAsync_Default_TextAppended"); + + Directory.CreateDirectory(TestFolder); + + await AsyncFile.WriteAllTextAsync(path, contents); + + var result = File.ReadAllText(path); + + Assert.AreEqual(contents, result); + } + + [TestMethod] + public async Task WriteAllTextAsync_EncodingAscii_TextAppended() + { + await WriteAllTextAsync_EncodingTest(Encoding.ASCII); + } + + [TestMethod] + public async Task WriteAllTextAsync_EncodingUtf8_TextAppended() + { + await WriteAllTextAsync_EncodingTest(Encoding.UTF8); + } + + [TestMethod] + public async Task WriteAllTextAsync_EncodingBigEndianUnicode_TextAppended() + { + await WriteAllTextAsync_EncodingTest(Encoding.BigEndianUnicode); + } + + [TestMethod] + public async Task WriteAllTextAsync_EncodingDefault_TextAppended() + { + await WriteAllTextAsync_EncodingTest(Encoding.Default); + } + + [TestMethod] + public async Task WriteAllTextAsync_EncodingUtf32_TextAppended() + { + await WriteAllTextAsync_EncodingTest(Encoding.UTF32); + } + + [TestMethod] + public async Task WriteAllTextAsync_EncodingUtf7_TextAppended() + { + await WriteAllTextAsync_EncodingTest(Encoding.UTF7); + } + + [TestMethod] + public async Task WriteAllTextAsync_EncodingUnicode_TextAppended() + { + await WriteAllTextAsync_EncodingTest(Encoding.Unicode); + } + + [TestMethod] + [ExpectedException(typeof(ArgumentNullException))] + public async Task WriteAllTextAsync_NullContent_ExceptionThrown() + { + var path = Path.Combine(TestFolder, "WriteAllLinesAsync_Default_LinesAppended"); + + Directory.CreateDirectory(TestFolder); + + await AsyncFile.WriteAllTextAsync(path, null); + } + + [TestMethod] + [ExpectedException(typeof(ArgumentNullException))] + public async Task WriteAllTextAsync_NullEncoding_ExceptionThrown() + { + var contents = "This is a test line."; + var path = Path.Combine(TestFolder, "WriteAllLinesAsync_Default_LinesAppended"); + + Directory.CreateDirectory(TestFolder); + + await AsyncFile.WriteAllTextAsync(path, contents, null); + } + + private async Task WriteAllTextAsync_EncodingTest(Encoding encoding) + { + var contents = string.Join(Environment.NewLine, Enumerable.Repeat("This is a test line.", 150)); + var path = Path.Combine(TestFolder, "WriteAllTextAsync_Default_TextAppended"); + + Directory.CreateDirectory(TestFolder); + + await AsyncFile.WriteAllTextAsync(path, contents, encoding); + + var result = File.ReadAllText(path, encoding); + + Assert.AreEqual(contents, result); + } + + #endregion + } } \ No newline at end of file diff --git a/AsyncIO.Tests/FileSystem/PathValidatorTests.cs b/AsyncIO.Tests/FileSystem/PathValidatorTests.cs new file mode 100644 index 0000000..07b3196 --- /dev/null +++ b/AsyncIO.Tests/FileSystem/PathValidatorTests.cs @@ -0,0 +1,46 @@ +using System; +using System.IO; +using System.Linq; +using AsyncIO.FileSystem; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace AsyncIO.Tests.FileSystem +{ + [TestClass] + public class PathValidatorTests + { + [TestMethod] + public void EnsureCorrectFileSystemPath_Default_True() + { + PathValidator.EnsureCorrectFileSystemPath(Environment.CurrentDirectory); + } + + [TestMethod] + [ExpectedException(typeof (ArgumentException))] + public void EnsureCorrectFileSystemPath_Null_ExceptionThrown() + { + PathValidator.EnsureCorrectFileSystemPath(null); + } + + [TestMethod] + [ExpectedException(typeof(ArgumentException))] + public void EnsureCorrectFileSystemPath_EmptyString_ExceptionThrown() + { + PathValidator.EnsureCorrectFileSystemPath(string.Empty); + } + + [TestMethod] + [ExpectedException(typeof(ArgumentException))] + public void EnsureCorrectFileSystemPath_WhitespaceString_ExceptionThrown() + { + PathValidator.EnsureCorrectFileSystemPath(" "); + } + + [TestMethod] + [ExpectedException(typeof(ArgumentException))] + public void EnsureCorrectFileSystemPath_HasInvalidChars_ExceptionThrown() + { + PathValidator.EnsureCorrectFileSystemPath(Environment.CurrentDirectory + Path.GetInvalidPathChars().First()); + } + } +} \ No newline at end of file diff --git a/AsyncIO/FileSystem/AsyncFile.cs b/AsyncIO/FileSystem/AsyncFile.cs index c1d32ca..9dc2290 100644 --- a/AsyncIO/FileSystem/AsyncFile.cs +++ b/AsyncIO/FileSystem/AsyncFile.cs @@ -4,6 +4,7 @@ using System.Text; using System.Threading; using System.Threading.Tasks; +using JetBrains.Annotations; namespace AsyncIO.FileSystem { @@ -26,7 +27,7 @@ public static Task AppendAllLinesAsync(string path, IEnumerable contents return AppendAllLinesAsync(path, contents, Encoding.UTF8, cancellationToken); } - public static async Task AppendAllLinesAsync(string path, IEnumerable contents, Encoding encoding, CancellationToken cancellationToken) + public static async Task AppendAllLinesAsync(string path, [NotNull] IEnumerable contents, [NotNull] Encoding encoding, CancellationToken cancellationToken) { if (contents == null) throw new ArgumentNullException(nameof(contents)); @@ -57,7 +58,7 @@ public static Task AppendAllTextAsync(string path, string contents) return AppendAllTextAsync(path, contents, Encoding.UTF8); } - public static async Task AppendAllTextAsync(string path, string contents, Encoding encoding) + public static async Task AppendAllTextAsync(string path, [NotNull] string contents, [NotNull] Encoding encoding) { if (contents == null) throw new ArgumentNullException(nameof(contents)); @@ -170,9 +171,20 @@ public static Task ReadAllBytesAsync(string path) return ReadAllBytesAsync(path, CancellationToken.None); } - public static Task ReadAllBytesAsync(string path, CancellationToken cancellationToken) + public static async Task ReadAllBytesAsync(string path, CancellationToken cancellationToken) { - throw new NotImplementedException(); + PathValidator.EnsureCorrectFileSystemPath(path); + const int fileBufferSize = 4096; + using (var fileStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, fileBufferSize, true)) + { + var length = fileStream.Length; + if (length > int.MaxValue) + throw new IOException("File is greater than 2GB."); + var bytes = new byte[length]; + await fileStream.ReadAsync(bytes, 0, (int)length, cancellationToken).ConfigureAwait(false); + cancellationToken.ThrowIfCancellationRequested(); + return bytes; + } } #endregion @@ -184,7 +196,6 @@ public static Task ReadAllLinesAsync(string path) return ReadAllLinesAsync(path, Encoding.UTF8, CancellationToken.None); } - public static Task ReadAllLinesAsync(string path, Encoding encoding) { return ReadAllLinesAsync(path, encoding, CancellationToken.None); @@ -195,58 +206,52 @@ public static Task ReadAllLinesAsync(string path, CancellationToken ca return ReadAllLinesAsync(path, Encoding.UTF8, cancellationToken); } - public static Task ReadAllLinesAsync(string path, Encoding encoding, CancellationToken cancellationToken) + public static async Task ReadAllLinesAsync([NotNull] string path, [NotNull] Encoding encoding, CancellationToken cancellationToken) { - throw new NotImplementedException(); - } - - #endregion - - #region ReadAllTextAsync - - public static string ReadAllTextAsync(string path) - { - return ReadAllTextAsync(path, Encoding.UTF8, CancellationToken.None); - } - - public static string ReadAllTextAsync(string path, Encoding encoding) - { - return ReadAllTextAsync(path, encoding, CancellationToken.None); - } - - public static string ReadAllTextAsync(string path, CancellationToken cancellationToken) - { - return ReadAllTextAsync(path, Encoding.UTF8, cancellationToken); - } + if (encoding == null) + throw new ArgumentNullException(nameof(encoding)); + PathValidator.EnsureCorrectFileSystemPath(path); - public static string ReadAllTextAsync(string path, Encoding encoding, CancellationToken cancellationToken) - { - throw new NotImplementedException(); + var lines = new List(); + const int fileBufferSize = 4096; + using (var fileStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, fileBufferSize, true)) + { + using (var reader = new StreamReader(fileStream, encoding)) + { + while (!reader.EndOfStream) + { + if (cancellationToken.IsCancellationRequested) + cancellationToken.ThrowIfCancellationRequested(); + lines.Add(await reader.ReadLineAsync().ConfigureAwait(false)); + } + } + } + return lines.ToArray(); } #endregion - #region ReadLinesAsync - - public static Task> ReadLinesAsync(string path) - { - return ReadLinesAsync(path, Encoding.UTF8, CancellationToken.None); - } - + #region ReadAllTextAsync - public static Task> ReadLinesAsync(string path, Encoding encoding) + public static Task ReadAllTextAsync(string path) { - return ReadLinesAsync(path, encoding, CancellationToken.None); + return ReadAllTextAsync(path, Encoding.UTF8); } - public static Task> ReadLinesAsync(string path, CancellationToken cancellationToken) + public static async Task ReadAllTextAsync(string path, Encoding encoding) { - return ReadLinesAsync(path, Encoding.UTF8, cancellationToken); - } + if (encoding == null) + throw new ArgumentNullException(nameof(encoding)); + PathValidator.EnsureCorrectFileSystemPath(path); - public static Task> ReadLinesAsync(string path, Encoding encoding, CancellationToken cancellationToken) - { - throw new NotImplementedException(); + const int fileBufferSize = 4096; + using (var fileStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, fileBufferSize, true)) + { + using (var reader = new StreamReader(fileStream, encoding)) + { + return await reader.ReadToEndAsync().ConfigureAwait(false); + } + } } #endregion @@ -258,9 +263,15 @@ public static Task WriteAllBytesAsync(string path, byte[] bytes) return WriteAllBytesAsync(path, bytes, CancellationToken.None); } - public static Task WriteAllBytesAsync(string path, byte[] bytes, CancellationToken none) + public static async Task WriteAllBytesAsync(string path, byte[] bytes, CancellationToken cancellationToken) { - throw new NotImplementedException(); + PathValidator.EnsureCorrectFileSystemPath(path); + const int fileBufferSize = 4096; + using (var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Write, fileBufferSize, true)) + { + await fileStream.WriteAsync(bytes, 0, bytes.Length, cancellationToken).ConfigureAwait(false); + cancellationToken.ThrowIfCancellationRequested(); + } } #endregion @@ -269,22 +280,40 @@ public static Task WriteAllBytesAsync(string path, byte[] bytes, CancellationTok public static Task WriteAllLinesAsync(string path, IEnumerable contents) { - throw new NotImplementedException(); + return WriteAllLinesAsync(path, contents, Encoding.UTF8, CancellationToken.None); } public static Task WriteAllLinesAsync(string path, IEnumerable contents, Encoding encoding) { - throw new NotImplementedException(); + return WriteAllLinesAsync(path, contents, encoding, CancellationToken.None); } public static Task WriteAllLinesAsync(string path, IEnumerable contents, CancellationToken cancellationToken) { - throw new NotImplementedException(); + return WriteAllLinesAsync(path, contents, Encoding.UTF8, cancellationToken); + } - public static Task WriteAllLinesAsync(string path, IEnumerable contents, Encoding encoding, CancellationToken cancellationToken) + public static async Task WriteAllLinesAsync(string path, [NotNull] IEnumerable contents, [NotNull] Encoding encoding, CancellationToken cancellationToken) { - throw new NotImplementedException(); + if (contents == null) + throw new ArgumentNullException(nameof(contents)); + if (encoding == null) + throw new ArgumentNullException(nameof(encoding)); + PathValidator.EnsureCorrectFileSystemPath(path); + + const int fileBufferSize = 4096; + using (var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, fileBufferSize, true)) + { + using (var writer = new StreamWriter(fileStream, encoding)) + { + foreach (var content in contents) + { + cancellationToken.ThrowIfCancellationRequested(); + await writer.WriteLineAsync(content).ConfigureAwait(false); + } + } + } } #endregion @@ -293,22 +322,25 @@ public static Task WriteAllLinesAsync(string path, IEnumerable contents, public static Task WriteAllTextAsync(string path, string contents) { - return WriteAllTextAsync(path, contents, Encoding.UTF8, CancellationToken.None); + return WriteAllTextAsync(path, contents, Encoding.UTF8); } - public static Task WriteAllTextAsync(string path, string contents, Encoding encoding) + public static async Task WriteAllTextAsync(string path, [NotNull] string contents, [NotNull] Encoding encoding) { - return WriteAllTextAsync(path, contents, encoding, CancellationToken.None); - } - - public static Task WriteAllTextAsync(string path, string contents, CancellationToken cancellationToken) - { - return WriteAllTextAsync(path, contents, Encoding.UTF8, cancellationToken); - } + if (contents == null) + throw new ArgumentNullException(nameof(contents)); + if (encoding == null) + throw new ArgumentNullException(nameof(encoding)); + PathValidator.EnsureCorrectFileSystemPath(path); - public static Task WriteAllTextAsync(string path, string contents, Encoding encoding, CancellationToken cancellationToken) - { - throw new NotImplementedException(); + const int fileBufferSize = 4096; + using (var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, fileBufferSize, true)) + { + using (var writer = new StreamWriter(fileStream, encoding)) + { + await writer.WriteAsync(contents).ConfigureAwait(false); + } + } } #endregion diff --git a/AsyncIO/FileSystem/PathValidator.cs b/AsyncIO/FileSystem/PathValidator.cs index 127b1fa..b204b6c 100644 --- a/AsyncIO/FileSystem/PathValidator.cs +++ b/AsyncIO/FileSystem/PathValidator.cs @@ -1,6 +1,7 @@ using System; using System.IO; using System.Linq; +using System.Runtime.CompilerServices; namespace AsyncIO.FileSystem { diff --git a/AsyncIO/Properties/AssemblyInfo.cs b/AsyncIO/Properties/AssemblyInfo.cs index 53fbc4e..6637679 100644 --- a/AsyncIO/Properties/AssemblyInfo.cs +++ b/AsyncIO/Properties/AssemblyInfo.cs @@ -13,6 +13,7 @@ [assembly: AssemblyCopyright("Copyright © 2016")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] +[assembly: InternalsVisibleTo("AsyncIO.Tests")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from