< Summary

Information
Class: ArturRios.Util.IO.FileReader
Assembly: ArturRios.Util
File(s): /home/ci/agent/workspace/dotnet-util-docs_main/app/src/IO/FileReader.cs
Line coverage
100%
Covered lines: 13
Uncovered lines: 0
Coverable lines: 13
Total lines: 112
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/ci/agent/workspace/dotnet-util-docs_main/app/src/IO/FileReader.cs

#LineLine coverage
 1using System.Text.Json;
 2using ArturRios.Util.Http;
 3
 4namespace ArturRios.Util.IO;
 5
 6/// <summary>
 7/// Provides synchronous helper methods for reading and deserializing file contents.
 8/// </summary>
 9/// <remarks>
 10/// All methods validate the provided path and throw <see cref="ArgumentException"/> for null/whitespace and <see cref="
 11/// See <see cref="FileReaderAsync"/> for the asynchronous equivalents, which behave identically.
 12/// </remarks>
 13public static class FileReader
 14{
 15    /// <summary>
 16    /// Reads the entire contents of a text file.
 17    /// </summary>
 18    /// <param name="path">Absolute or relative path to the file.</param>
 19    /// <returns>File content as a string.</returns>
 20    /// <exception cref="ArgumentException">Path is null or whitespace.</exception>
 21    /// <exception cref="FileNotFoundException">File does not exist.</exception>
 22    public static string Read(string path)
 23    {
 624        ValidatePath(path);
 25
 226        return File.ReadAllText(path);
 27    }
 28
 29    /// <summary>
 30    /// Reads a delimited text file (e.g. CSV) mapping each header to its column values.
 31    /// </summary>
 32    /// <param name="path">Path to the file.</param>
 33    /// <param name="separator">Delimiter separating fields (e.g. <c>','</c>).</param>
 34    /// <returns>A dictionary keyed by column header mapping to arrays of its values.</returns>
 35    /// <exception cref="ArgumentException">Path is null or whitespace.</exception>
 36    /// <exception cref="FileNotFoundException">File does not exist.</exception>
 37    /// <exception cref="InvalidOperationException">
 38    /// The file has fewer than two lines, or the header row repeats a name, which would silently drop a
 39    /// column from the result.
 40    /// </exception>
 41    /// <remarks>
 42    /// This is a plain split on <paramref name="separator"/>, not an RFC 4180 parser: quoting is not
 43    /// interpreted, so a quoted field containing the separator or a line break is split like any other.
 44    /// Use a dedicated CSV library when the data can contain either. Rows shorter than the header are
 45    /// padded with empty strings, and values beyond the last header are discarded.
 46    /// </remarks>
 47    public static Dictionary<string, string[]> ReadAsDictionary(string path, char separator)
 48    {
 1549        ValidatePath(path);
 50
 1151        return DelimitedText.ToDictionary(File.ReadAllLines(path), separator);
 52    }
 53
 54    /// <summary>
 55    /// Reads all lines of a text file into an array.
 56    /// </summary>
 57    /// <param name="path">Path to the file.</param>
 58    /// <returns>Array of lines.</returns>
 59    /// <exception cref="ArgumentException">Path is null or whitespace.</exception>
 60    /// <exception cref="FileNotFoundException">File does not exist.</exception>
 61    public static string[] ReadLines(string path)
 62    {
 663        ValidatePath(path);
 64
 265        return File.ReadAllLines(path);
 66    }
 67
 68    /// <summary>
 69    /// Reads a JSON file and deserializes its content into the specified type.
 70    /// </summary>
 71    /// <typeparam name="T">Target type.</typeparam>
 72    /// <param name="path">Path to the JSON file.</param>
 73    /// <returns>
 74    /// The deserialized object, or <c>null</c> when the file contains the JSON literal <c>null</c>.
 75    /// </returns>
 76    /// <exception cref="ArgumentException">Path is null or whitespace.</exception>
 77    /// <exception cref="FileNotFoundException">File does not exist.</exception>
 78    /// <exception cref="JsonException">
 79    /// The file is empty, holds only whitespace, or does not contain JSON matching
 80    /// <typeparamref name="T"/>. An unreadable file is reported rather than silently turned into
 81    /// <c>null</c>, which would be indistinguishable from a genuine null payload.
 82    /// </exception>
 83    /// <remarks>
 84    /// Property names are matched without regard to case, exactly as <see cref="HttpOutput{TBody}"/>
 85    /// binds a response body, so the same JSON document binds the same way whether it arrives over HTTP or is
 86    /// read from disk.
 87    /// </remarks>
 88    public static T? ReadAndDeserialize<T>(string path)
 89    {
 1190        ValidatePath(path);
 91
 792        return JsonSerializer.Deserialize<T>(File.ReadAllText(path), JsonDefaults.Options);
 93    }
 94
 95    /// <summary>
 96    /// Rejects an unusable path before any I/O is attempted.
 97    /// </summary>
 98    /// <exception cref="ArgumentException">Path is null or whitespace.</exception>
 99    /// <exception cref="FileNotFoundException">File does not exist.</exception>
 100    internal static void ValidatePath(string path)
 101    {
 80102        if (string.IsNullOrWhiteSpace(path))
 103        {
 24104            throw new ArgumentException("Path cannot be null or whitespace", nameof(path));
 105        }
 106
 56107        if (!File.Exists(path))
 108        {
 8109            throw new FileNotFoundException($"The file at path '{path}' does not exist", path);
 110        }
 48111    }
 112}