<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>LINQ to TEXT and LINQ to CSV</title><link>http://blogs.msdn.com/ericwhite/archive/2008/09/30/linq-to-text-and-linq-to-csv.aspx</link><description>[Blog Map] LINQ is a great tool for writing ad-hoc queries and transforms, and occasionally I need to write queries or transforms on text files. And sometimes I receive CSV files, and need to do something with them. I wrote a blog post on LINQ to Text</description><dc:language>en</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>re: LINQ to TEXT and LINQ to CSV</title><link>http://blogs.msdn.com/ericwhite/archive/2008/09/30/linq-to-text-and-linq-to-csv.aspx#8970740</link><pubDate>Wed, 01 Oct 2008 00:29:43 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8970740</guid><dc:creator>Jeffrey L. Whitledge</dc:creator><description>&lt;p&gt;If I'm reading that code correctly, quoted strings in your CSV files cannot contain backslashes unless they are escaping quotes?&lt;/p&gt;
&lt;p&gt;I find it very interesting that you decided against a functional approach, because when I wrote a CSV parsing method back in the nineties using VB4, I decided that the easiest way to do it would be a recursive function that parsed the first value, then passed the rest of the string to itself. It was not efficient, but it was easy to write. That was back before all the functional programming stuff appeared on my radar screen.&lt;/p&gt;
</description></item><item><title>re: LINQ to TEXT and LINQ to CSV</title><link>http://blogs.msdn.com/ericwhite/archive/2008/09/30/linq-to-text-and-linq-to-csv.aspx#8971957</link><pubDate>Wed, 01 Oct 2008 20:45:05 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8971957</guid><dc:creator>EricWhite</dc:creator><description>&lt;p&gt;Hi Jeffrey,&lt;/p&gt;
&lt;p&gt;You are absolutely right, quoted strings could not contain backslashes unless escaping quotes. &amp;nbsp;I've updated the code so that backslashes can escape any character, including backslash.&lt;/p&gt;
&lt;p&gt;Regarding writing this using the functional approach, your idea is interesting. &amp;nbsp;However, given that I only take CSV files under duress, and then only for a quick and dirty solution to data transformation (generally, I immediately convert to an XML document), this is probably something I'm not going to do in the near future. &amp;nbsp;:-)&lt;/p&gt;
&lt;p&gt;But this raises the point - til now, I think that pattern matching of certain types is one of the areas where it is harder to use LINQ. &amp;nbsp;I'm still thinking about this area - what would a regex replacement look like using LINQ? &amp;nbsp;What are the appropriate LINQ patterns to use when you have items in a collection that depend on their context, which in turn depends on an enclosing context? &amp;nbsp;Grammars and recursive descent parsers are the cannonical way to do this - to write lexical parsers, for instance. &amp;nbsp;But what about just looking for patterns in a string?&lt;/p&gt;
&lt;p&gt;I've been thinking about approaches to specify patterns to match, and then having a method that yields up matches, but the implementation of the method that yields matches is an area that I haven't finalized. &amp;nbsp;I have ideas about how to do this with queries, but haven't fully developed them. &amp;nbsp;This is going to require more research. &amp;nbsp;(I'm sure that some of the FP experts out there have solved this problem; I just don't know the solution.)&lt;/p&gt;
&lt;p&gt;-Eric&lt;/p&gt;
</description></item><item><title>re: LINQ to TEXT and LINQ to CSV</title><link>http://blogs.msdn.com/ericwhite/archive/2008/09/30/linq-to-text-and-linq-to-csv.aspx#8996704</link><pubDate>Sun, 12 Oct 2008 20:10:26 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8996704</guid><dc:creator>Francis</dc:creator><description>&lt;p&gt;Other sample in codeproject web site&lt;/p&gt;
</description></item><item><title>re: LINQ to TEXT and LINQ to CSV</title><link>http://blogs.msdn.com/ericwhite/archive/2008/09/30/linq-to-text-and-linq-to-csv.aspx#9510578</link><pubDate>Thu, 26 Mar 2009 14:57:44 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9510578</guid><dc:creator>MarkJ</dc:creator><description>&lt;p&gt;&amp;quot;Stop rolling your own CSV parser&amp;quot;? And use a free one instead.&lt;/p&gt;
&lt;p&gt; &lt;a rel="nofollow" target="_new" href="http://www.secretgeek.net/csv_trouble.asp"&gt;http://www.secretgeek.net/csv_trouble.asp&lt;/a&gt;&lt;/p&gt;
</description></item><item><title>re: LINQ to TEXT and LINQ to CSV</title><link>http://blogs.msdn.com/ericwhite/archive/2008/09/30/linq-to-text-and-linq-to-csv.aspx#9617030</link><pubDate>Thu, 14 May 2009 23:39:43 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9617030</guid><dc:creator>jim b</dc:creator><description>&lt;p&gt;Great post, It helped out immensely. &amp;nbsp;One question, would it be possible to make the&lt;/p&gt;
&lt;p&gt;return new {&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp;Person = split[0],&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp;Quote = split[1]&lt;/p&gt;
&lt;p&gt;};&lt;/p&gt;
&lt;p&gt;dynamic in nature, ie use a configuration file to control the property and the location in the string to get the value from.&lt;/p&gt;
&lt;p&gt;thanks,&lt;/p&gt;
&lt;p&gt;jim&lt;/p&gt;
</description></item><item><title>re: LINQ to TEXT and LINQ to CSV</title><link>http://blogs.msdn.com/ericwhite/archive/2008/09/30/linq-to-text-and-linq-to-csv.aspx#9617085</link><pubDate>Fri, 15 May 2009 00:15:16 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9617085</guid><dc:creator>EricWhite</dc:creator><description>&lt;p&gt;Hi Jim, it certainly would be possible - with .NET 3.5, one way to do this is using a Dictionary&amp;lt;T&amp;gt; per row. &amp;nbsp;With .NET 4.0, there will be dynamic types that will enable this in a very clean way.&lt;/p&gt;
&lt;p&gt;-Eric&lt;/p&gt;
</description></item><item><title>re: LINQ to TEXT and LINQ to CSV</title><link>http://blogs.msdn.com/ericwhite/archive/2008/09/30/linq-to-text-and-linq-to-csv.aspx#9618679</link><pubDate>Fri, 15 May 2009 17:56:31 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9618679</guid><dc:creator>jbutler</dc:creator><description>&lt;p&gt;thanks for the tip, we are using 3.5 now and i am anxiously awaiting 4.0 for quite a few things now :)&lt;/p&gt;
</description></item><item><title>re: LINQ to TEXT and LINQ to CSV</title><link>http://blogs.msdn.com/ericwhite/archive/2008/09/30/linq-to-text-and-linq-to-csv.aspx#9805453</link><pubDate>Fri, 26 Jun 2009 16:48:51 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9805453</guid><dc:creator>Attila</dc:creator><description>&lt;p&gt;Hi Eric!&lt;/p&gt;
&lt;p&gt;Thanks for this post it's quite useful.&lt;/p&gt;
&lt;p&gt;There is one thing that I encountered when I used this for the first time, there is no whitespace (or at least space) support in the code.&lt;/p&gt;
&lt;p&gt;Because I'm writing much code, I did my sample file like this:&lt;/p&gt;
&lt;p&gt;Alias,Display Name,Email&lt;/p&gt;
&lt;p&gt;alias1, &amp;quot;test, me&amp;quot;, asd@asd.com&lt;/p&gt;
&lt;p&gt;For the 2nd row you'll parse it into 4 parts:&lt;/p&gt;
&lt;p&gt;alias1&lt;/p&gt;
&lt;p&gt;test&lt;/p&gt;
&lt;p&gt;me&lt;/p&gt;
&lt;p&gt;asd@asd.com&lt;/p&gt;
&lt;p&gt;which is &amp;quot;wrong&amp;quot;.&lt;/p&gt;
&lt;p&gt;In my opinion, (white)spaces are allowed around a quoted string. For regular data I'm not sure, but if someone wants to use spaces in the data itself, then enclose the string in quotes like: &amp;quot; &amp;nbsp; spaces around me &amp;nbsp; &amp;quot;.&lt;/p&gt;
&lt;p&gt;So for the regular data spaces are allowed too, but they must be trimmed, and quoted strings should be trimmed only outside of the quotes.&lt;/p&gt;
&lt;p&gt;It was quite easy to add support spaces as I described above.&lt;/p&gt;
&lt;p&gt;I added this as the last check in the AtBeginningOfToken state:&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;if (sourceCharArray[i] == ' ')&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;{&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;continue;&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;}&lt;/p&gt;
&lt;p&gt;and this as the FIRST check in the ExpectingComma state:&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;if (sourceCharArray[i] == ' ')&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;{&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;continue;&lt;/p&gt;
&lt;p&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;}&lt;/p&gt;
&lt;p&gt;The following enhancements could make it more generic:&lt;/p&gt;
&lt;p&gt;- Add support for parameterized quote identifier(s)&lt;/p&gt;
&lt;p&gt;- Add support for parameterized separator&lt;/p&gt;
&lt;p&gt;- Add support for number parsing, based on number format (I know it's not definitely a split function, but can be :-))&lt;/p&gt;
&lt;p&gt;Thanks,&lt;/p&gt;
&lt;p&gt;Attila&lt;/p&gt;
</description></item></channel></rss>