Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 58 additions & 5 deletions LINQtoCSV.Tests/CsvContextReadTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public void GoodFileUsingOutputFormatForParsingDatesCharUSEnglish()
{
SeparatorChar = ';',
FirstLineHasColumnNames = false,
UseOutputFormatForParsingCsvValue = true,
UseOutputFormatForParsingCsvValue = true,
EnforceCsvColumnAttribute = true, // default is false
FileCultureName = "en-US" // default is the current culture
};
Expand Down Expand Up @@ -216,7 +216,7 @@ two newlines
and a quoted """"string""""""
dog house, ""45,230,990"",29 Feb 2004, , -56, True,"""", FF10, ""12,008""";

var expected = new [] {
var expected = new[] {
new ProductData {
name = "moonbuggy", weight = 34.184, startDate = new DateTime(2008, 5, 23), launchTime = new DateTime(2009, 5, 5, 16, 11, 0),
nbrAvailable = 1205, onsale = true, shopsAvailable = "Paris, New York", hexProductCode = 31, retailPrice = 540.12M,
Expand Down Expand Up @@ -333,16 +333,17 @@ and a quoted ""string"""
}

[TestMethod()]
public void FileWithUnknownColumns_ShouldDiscardColumns() {
public void FileWithUnknownColumns_ShouldDiscardColumns()
{
var description = new CsvFileDescription
{
SeparatorChar = ',',
FirstLineHasColumnNames = true,
IgnoreUnknownColumns = true,
};

//The following input has 5 columns: Id | Name | Last Name | Age | City. Only the Name, Last Name and Age will be read.

string input =
@"Id,Name,Last Name,Age,City
1,John,Doe,15,Washington
Expand All @@ -367,5 +368,57 @@ public void FileWithUnknownColumns_ShouldDiscardColumns() {
AssertRead(input, description, expected);

}

[TestMethod()]
public void GoodFileWithIgnoringCaseOnColumnNames()
{ // Arrange

CsvFileDescription fileDescription_namesUs = new CsvFileDescription
{
SeparatorChar = ',', // default is ','
FirstLineHasColumnNames = true,
EnforceCsvColumnAttribute = false, // default is false
FileCultureName = "en-US", // default is the current culture
IgnoreCaseOnColumnNames = true,
IgnoreTrailingSeparatorChar = true

};

string testInput =
@"nAME, Weight, startDate, LAunchTime, nbrAVAILABLE,onsalE,shopsAVAilable, CODE, Price, Description,
moonbuggy, 34.184, 5/23/08, 5-May-2009 4:11 pm, 1205, true, ""Paris, New York"", 1F, $540.12, newly launched product,
""mouse trap"",45E-5, 1/2/1985, ""7 August 1988, 0:00 am"", ""4,030"", FALSE, ""This field has
a newline"", 100, ""$78,300"", ""This field has quotes(""""), and
two newlines
and a quoted """"string""""""
dog house, ""45,230,990"",29 Feb 2004, , -56, True,"""", FF10, ""12,008"",";

var expected = new[] {
new ProductData {
name = "moonbuggy", weight = 34.184, startDate = new DateTime(2008, 5, 23), launchTime = new DateTime(2009, 5, 5, 16, 11, 0),
nbrAvailable = 1205, onsale = true, shopsAvailable = "Paris, New York", hexProductCode = 31, retailPrice = 540.12M,
description = "newly launched product"
},
new ProductData {
name = "mouse trap", weight = 45E-5, startDate = new DateTime(1985, 1, 2), launchTime = new DateTime(1988, 8, 7, 0, 0, 0),
nbrAvailable = 4030, onsale = false, shopsAvailable = @"This field has
a newline", hexProductCode = 256, retailPrice = 78300M,
description = @"This field has quotes(""), and
two newlines
and a quoted ""string"""
},
new ProductData {
name = "dog house", weight = 45230990, startDate = new DateTime(2004, 2, 29), launchTime = default(DateTime),
nbrAvailable = -56, onsale = true, shopsAvailable = "", hexProductCode = 65296, retailPrice = 12008M,
description = null
}
};

// Act and Assert

AssertRead(testInput, fileDescription_namesUs, expected);


}
}
}
6 changes: 6 additions & 0 deletions LINQtoCSV/CsvFileDescription.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@ public int MaximumNbrExceptions
/// </summary>
public bool IgnoreUnknownColumns { get; set; }

/// <summary>
/// If set to true, will read the column names while ignoring the case
/// </summary>
public bool IgnoreCaseOnColumnNames { get; set; }

// ---------------

public CsvFileDescription()
Expand All @@ -112,6 +117,7 @@ public CsvFileDescription()
UseFieldIndexForReadingData = false;
UseOutputFormatForParsingCsvValue = false;
IgnoreUnknownColumns = false;
IgnoreCaseOnColumnNames = false;
}
}
}
4 changes: 3 additions & 1 deletion LINQtoCSV/FieldMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,8 @@ public FieldMapper(CsvFileDescription fileDescription, string fileName, bool wri
m_fileDescription = fileDescription;
m_fileName = fileName;

m_NameToInfo = new Dictionary<string, TypeFieldInfo>();
//if case insensitive set then declare dictionary with ignorecase
m_NameToInfo = m_fileDescription.IgnoreCaseOnColumnNames ? new Dictionary<string, TypeFieldInfo>(StringComparer.InvariantCultureIgnoreCase) : new Dictionary<string, TypeFieldInfo>();

AnalyzeType(
typeof(T),
Expand Down Expand Up @@ -410,6 +411,7 @@ public void ReadNames(IDataRow row)

int currentNameIndex = 0;
for (int i = 0; i < row.Count; i++) {

if (!m_NameToInfo.ContainsKey(row[i].Value)) {
//If we have to ignore this column
if (m_fileDescription.IgnoreUnknownColumns) {
Expand Down
99 changes: 89 additions & 10 deletions article.htm
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ <h3>Reading from a file</h3>
Create a <code>CsvFileDescription</code> object, and initialize it with details about the file that you're going to read. It will look like this:
<pre lang="cs">CsvFileDescription inputFileDescription = new CsvFileDescription
{
SeparatorChar = ',',
SeparatorChar = ',',
FirstLineHasColumnNames = true
};</pre>

Expand Down Expand Up @@ -147,7 +147,7 @@ <h3>Reading from a file</h3>

<pre lang="cs">CsvFileDescription inputFileDescription = new CsvFileDescription
{
SeparatorChar = ',',
SeparatorChar = ',',
FirstLineHasColumnNames = true
};
CsvContext cc = new CsvContext();
Expand Down Expand Up @@ -268,7 +268,7 @@ <h3><a id="WriteAnonymous">Writing an IEnumerable of anonymous type</a></h3>
// Write contents of productsNetherlands to file
cc.Write(
productsNetherlands,
&quot;products-Netherlands.csv&quot;,
&quot;products-Netherlands.csv&quot;,
outputFileDescription);</pre>

<p>Here, a LINQ query selects all products for &quot;Netherlands&quot; from the variable <code>products</code>, and returns an <code>IEnumerable</code> holding objects of some anonymous type that has the fields <code>Name</code>, <code>LaunchDate</code>, <code>Price</code>, and <code>Description</code>. The <code>Write</code> method then writes those objects to the file <em>products-Netherlands.csv</em>.</p>
Expand Down Expand Up @@ -452,6 +452,8 @@ <h2>CsvFileDescription<a id="CsvFileDescription"></a></h2>
<li><a href="#IgnoreTrailingSeparatorChar"><code>IgnoreTrailingSeparatorChar</code></a> </li>

<li><a href="#IgnoreUnknownColumns"><code>IgnoreUnknownColumns</code></a> </li>

<li><a href="#IgnoreCaseOnColumnNames"><code>IgnoreCaseOnColumnNames</code></a> </li>
</ul>

<h3><a id="SeparatorChar">SeparatorChar</a></h3>
Expand Down Expand Up @@ -879,7 +881,7 @@ <h4>Example:</h4>
<br>
Suppose you have the following class:
<pre lang="cs">
class Person
class Person
{
[CsvColumn(Name = "Name")]
public string Name { get ; set; }
Expand All @@ -898,6 +900,80 @@ <h4>Example:</h4>
then the columns &quot;Id&quot; and &quot;City&quot; will be ignored without an exception.
</p>

<h3><a id="IgnoreCaseOnColumnNames"></a>IgnoreCaseOnColumnNames</h3>

<table cellpadding="3">
<tbody>
<tr>
<td><strong>Type:</strong></td>

<td><code lang="cs">bool</code></td>
</tr>

<tr>
<td><strong>Default:</strong></td>

<td>false</td>
</tr>

<tr>
<td><strong>Applies to:</strong></td>

<td>Reading only</td>
</tr>
</tbody>
</table>

<h4>Example:</h4>
<p>
If you dont want your class property name cases to match with the column names in the csv and do not want to use the additional name attribute just to match column names, you can set this attribute to true which will ignore casing in column name:
</p>
<table cellspacing="5" cellpadding="0" border="0">
<tbody>
<tr>
<th>id</th>
<th>name</th>
<th>last Name</th>
<th>age</th>
<th>CITY</th>
</tr>
<tr>
<td>1</td>
<td>John</td>
<td>Doe</td>
<td>15</td>
<td>Washington</td>
</tr>
<tr>
<td>2</td>
<td>Jane</td>
<td>Doe</td>
<td>20</td>
<td>New York</td>
</tr>
</tbody>
</table>
<br>
Suppose you have the following class:
<pre lang="cs">
class Person
{
[CsvColumn]
public string Name { get ; set; }
[CsvColumn]
public string LastName { get; set; }
[CsvColumn]
public int Age { get; set; }
}
</pre>
<p>
Note that the input file has different case for column names than the class members. This discrepancy would normally cause an exception.
</p>
<p>
However, if you set <pre lang="cs">fd.IgnoreCaseOnColumnNames = true;</pre>

then the columns will match without an exception.
</p>


<h2>CsvColumn Attribute<a id="CsvColumn_Attribute"></a></h2>
Expand Down Expand Up @@ -1820,6 +1896,15 @@ <h2><a id="History"></a>History</h2>
Courtesy of <a href="https://github.com/omederos" target="_blank">Oscar Mederos</a>.
</td>
</tr>
<tr>
<td valign="top">1.6</td>
<td valign="top">29 April 2016</td>
<td valign="top">
Introduced option to ignore case on column names in the input file.
Courtesy of <a href="https://github.com/woodenarmadillo" target="_blank">Shahzad Ahmad</a>.
</td>
</tr>

</tbody>
</table>

Expand All @@ -1829,9 +1914,3 @@ <h2><a id="Contribute"></a>New Features and Bug Fixes</h2>
Details:
<a href="github.com/mperdeck/LINQtoCSV">https://github.com/mperdeck/LINQtoCSV</a>
</p>