< Summary

Information
Class: ArturRios.Util.IO.FileReader
Assembly: ArturRios.Util
File(s): /home/runner/work/dotnet-util/dotnet-util/src/IO/FileReader.cs
Line coverage
100%
Covered lines: 13
Uncovered lines: 0
Coverable lines: 13
Total lines: 106
Line coverage: 100%
Branch coverage
100%
Covered branches: 4
Total branches: 4
Branch coverage: 100%
Method coverage
100%
Covered methods: 5
Fully covered methods: 5
Total methods: 5
Method coverage: 100%
Full method coverage: 100%

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
Read(...)100%11100%
ReadAsDictionary(...)100%11100%
ReadLines(...)100%11100%
ReadAndDeserialize(...)100%11100%
ValidatePath(...)100%44100%

File(s)

/home/runner/work/dotnet-util/dotnet-util/src/IO/FileReader.cs

#LineLine coverage
 1using System.Text.Json;
 2
 3namespace ArturRios.Util.IO;
 4
 5/// <summary>
 6/// Provides synchronous helper methods for reading and deserializing file contents.
 7/// </summary>
 8/// <remarks>
 9/// All methods validate the provided path and throw <see cref="ArgumentException"/> for null/whitespace and <see cref="
 10/// See <see cref="FileReaderAsync"/> for the asynchronous equivalents, which behave identically.
 11/// </remarks>
 12public static class FileReader
 13{
 14    /// <summary>
 15    /// Reads the entire contents of a text file.
 16    /// </summary>
 17    /// <param name="path">Absolute or relative path to the file.</param>
 18    /// <returns>File content as a string.</returns>
 19    /// <exception cref="ArgumentException">Path is null or whitespace.</exception>
 20    /// <exception cref="FileNotFoundException">File does not exist.</exception>
 21    public static string Read(string path)
 22    {
 623        ValidatePath(path);
 24
 225        return File.ReadAllText(path);
 26    }
 27
 28    /// <summary>
 29    /// Reads a delimited text file (e.g. CSV) mapping each header to its column values.
 30    /// </summary>
 31    /// <param name="path">Path to the file.</param>
 32    /// <param name="separator">Delimiter separating fields (e.g. <c>','</c>).</param>
 33    /// <returns>A dictionary keyed by column header mapping to arrays of its values.</returns>
 34    /// <exception cref="ArgumentException">Path is null or whitespace.</exception>
 35    /// <exception cref="FileNotFoundException">File does not exist.</exception>
 36    /// <exception cref="InvalidOperationException">
 37    /// The file has fewer than two lines, or the header row repeats a name, which would silently drop a
 38    /// column from the result.
 39    /// </exception>
 40    /// <remarks>
 41    /// This is a plain split on <paramref name="separator"/>, not an RFC 4180 parser: quoting is not
 42    /// interpreted, so a quoted field containing the separator or a line break is split like any other.
 43    /// Use a dedicated CSV library when the data can contain either. Rows shorter than the header are
 44    /// padded with empty strings, and values beyond the last header are discarded.
 45    /// </remarks>
 46    public static Dictionary<string, string[]> ReadAsDictionary(string path, char separator)
 47    {
 1548        ValidatePath(path);
 49
 1150        return DelimitedText.ToDictionary(File.ReadAllLines(path), separator);
 51    }
 52
 53    /// <summary>
 54    /// Reads all lines of a text file into an array.
 55    /// </summary>
 56    /// <param name="path">Path to the file.</param>
 57    /// <returns>Array of lines.</returns>
 58    /// <exception cref="ArgumentException">Path is null or whitespace.</exception>
 59    /// <exception cref="FileNotFoundException">File does not exist.</exception>
 60    public static string[] ReadLines(string path)
 61    {
 662        ValidatePath(path);
 63
 264        return File.ReadAllLines(path);
 65    }
 66
 67    /// <summary>
 68    /// Reads a JSON file and deserializes its content into the specified type.
 69    /// </summary>
 70    /// <typeparam name="T">Target type.</typeparam>
 71    /// <param name="path">Path to the JSON file.</param>
 72    /// <returns>
 73    /// The deserialized object, or <c>null</c> when the file contains the JSON literal <c>null</c>.
 74    /// </returns>
 75    /// <exception cref="ArgumentException">Path is null or whitespace.</exception>
 76    /// <exception cref="FileNotFoundException">File does not exist.</exception>
 77    /// <exception cref="JsonException">
 78    /// The file is empty, holds only whitespace, or does not contain JSON matching
 79    /// <typeparamref name="T"/>. An unreadable file is reported rather than silently turned into
 80    /// <c>null</c>, which would be indistinguishable from a genuine null payload.
 81    /// </exception>
 82    public static T? ReadAndDeserialize<T>(string path)
 83    {
 1084        ValidatePath(path);
 85
 686        return JsonSerializer.Deserialize<T>(File.ReadAllText(path));
 87    }
 88
 89    /// <summary>
 90    /// Rejects an unusable path before any I/O is attempted.
 91    /// </summary>
 92    /// <exception cref="ArgumentException">Path is null or whitespace.</exception>
 93    /// <exception cref="FileNotFoundException">File does not exist.</exception>
 94    internal static void ValidatePath(string path)
 95    {
 7896        if (string.IsNullOrWhiteSpace(path))
 97        {
 2498            throw new ArgumentException("Path cannot be null or whitespace", nameof(path));
 99        }
 100
 54101        if (!File.Exists(path))
 102        {
 8103            throw new FileNotFoundException($"The file at path '{path}' does not exist", path);
 104        }
 46105    }
 106}