/* * 2006 - 2018 Ted Spence, http://tedspence.com * License: http://www.apache.org/licenses/LICENSE-2.0 * Home page: https://github.com/tspence/csharp-csv-reader */ using System; using System.Collections.Generic; using System.Text; namespace CSVNET { /// /// Defines the behavior of CSV serialization when a nested array is encountered /// public enum ArrayOptions { /// /// Use built-in string conversion, which renders arrays as `MyNamespace.MyObject[]` /// ToString, /// /// Convert any array columns that are array types into nulls (either blanks or null tokens) /// TreatAsNull, /// /// Render the number of items in the array /// CountItems, /// /// Serialize child arrays recursively using the same settings /// RecursiveSerialization, } /// /// Defines the behavior of CSV Serialization when a nested object (class) is encountered /// public enum ObjectOptions { /// /// Use built-in string conversion, which renders as `MyNamespace.MyObject` /// ToString, /// /// Serialize child objects recursively using the same settings /// RecursiveSerialization, } /// /// Settings to configure how a CSV file is parsed /// public class CSVSettings { /// /// The character used to delimit individual fields in the CSV. /// public char FieldDelimiter { get; set; } = ','; /// /// The character used to enclose fields that contain the delimiter character. /// public char TextQualifier { get; set; } = '"'; /// /// The separator used to indicate the end of a line in the CSV file. /// public string LineSeparator { get; set; } = Environment.NewLine; /// /// Set this value to true to enclose all fields in the text qualifier character. /// public bool ForceQualifiers { get; set; } /// /// Set this value to true to allow nulls to be rendered in CSV files when serializing /// and deserializing. /// /// CSV files by default do not have a mechanism for differentiating between null fields /// and empty fields. If this field is set to false, both `null` and empty string will /// render as an empty string. /// /// If this field is set to true, all non-null fields will be enclosed by the text qualifier, /// and fields that are null will be represented as `NullToken`. /// public bool AllowNull { get; set; } /// /// If AllowNull is set to true, this token will be used to represent NULL values. /// public string NullToken { get; set; } /// /// The first line of the CSV file will include the names of each field. /// public bool HeaderRowIncluded { get; set; } = true; /// /// When reading a CSV file, if the first line contains the instruction `sep=`, use this /// to determine the separator for the file. /// /// The "sep" line is a feature exclusive to Microsoft Excel, which permits CSV files to /// more easily handle European files where the comma character is often a separator between /// numeric values rather than a field delimiter. /// /// If this flag is set to true, when you parse a CSV, the first line of the parsing can override /// the field separator logic for each individual instance of parsing, but it will not change /// the `FieldDelimiter` in your settings object. /// /// More information: /// * [Original Issue Report](https://github.com/tspence/csharp-csv-reader/issues/28) /// * [Superuser Article](https://superuser.com/questions/773644/what-is-the-sep-metadata-you-can-add-to-csvs) /// * [Tjitjing Blog](https://blog.tjitjing.com/index.php/2016/07/set-separator-delimiter-in-csv-file-to-open-correctly-in-excel.html) /// public bool AllowSepLine { get; set; } = true; /// /// If `HeaderRowIncluded` is false, use these values for the headers /// public string[] AssumedHeaders { get; set; } /// /// Set this value to true to allow parsing for files where each row has a different number of fields /// public bool IgnoreDimensionErrors { get; set; } = true; /// /// Set this value to true to ignore header errors when deserializing /// public bool IgnoreHeaderErrors { get; set; } /// /// Set this flag to true to ignore read-only properties during serialization /// public bool IgnoreReadOnlyProperties { get; set; } /// /// Expect headers to be case sensitive during deserialization /// public bool HeadersCaseSensitive { get; set; } /// /// Exclude these columns during serialization and deserialization /// public string[] ExcludedColumns { get; set; } /// /// A list of data types that require text qualifiers during serialization. /// public Type[] ForceQualifierTypes { get; set; } /// /// Some CSV files contain an empty line at the end. If you set this flag to true, deserialization will /// not throw an error for empty lines and will instead ignore it. /// public bool IgnoreEmptyLineForDeserialization { get; set; } /// /// When reading data from a stream, this is the block size to read at once. /// public int BufferSize { get; set; } = DEFAULT_BUFFER_SIZE; internal static readonly int DEFAULT_BUFFER_SIZE = 65536; /// /// The encoding for converting streams of bytes to strings /// public Encoding Encoding { get; set; } = Encoding.UTF8; /// /// The format to use for serializing date time objects, by default, ISO 8601 /// public string DateTimeFormat { get; set; } = "o"; /// /// The behavior to use when serializing a column that is an array or enumerable type /// public ArrayOptions NestedArrayBehavior { get; set; } = ArrayOptions.ToString; /// /// The behavior to use when serializing a column that is a class /// public ObjectOptions NestedObjectBehavior { get; set; } = ObjectOptions.ToString; /// /// Standard comma-separated value (CSV) file settings /// public static readonly CSVSettings CSV = new CSVSettings(); /// /// Standard comma-separated value (CSV) file settings that permit rendering of NULL values /// public static readonly CSVSettings CSV_PERMIT_NULL = new CSVSettings() { AllowNull = true, NullToken = "NULL" }; /// /// Standard tab-separated value (TSV) file settings /// public static readonly CSVSettings TSV = new CSVSettings() { FieldDelimiter = '\t' }; /// /// Clone the existing settings, but with a different field delimiter. /// /// Used for parsing of "sep=" lines so that the original object is immutable. /// /// The new delimiter for the cloned settings /// The newly cloned settings with the updated delimiter public CSVSettings CloneWithNewDelimiter(char newDelimiter) { var newSettings = (CSVSettings)this.MemberwiseClone(); newSettings.FieldDelimiter = newDelimiter; return newSettings; } /// /// Retrieve the list of risky characters according to this settings definition /// /// public char[] GetRiskyChars() { var riskyChars = new List(); riskyChars.Add(FieldDelimiter); riskyChars.Add(TextQualifier); foreach (var c in LineSeparator) { riskyChars.Add(c); } // CRLF is always considered risky riskyChars.Add('\n'); riskyChars.Add('\r'); return riskyChars.ToArray(); } /// /// Retrieve a hashset containing the list of types that require text qualifiers, or null if this /// feature is not used in this settings definition /// /// /// public Dictionary GetForceQualifierTypes() { if (ForceQualifierTypes == null) return null; var hashSet = new Dictionary(); foreach (var type in ForceQualifierTypes) { hashSet.Add(type, 1); } return hashSet; } } }