I want to open the csv file and read each line into an index of an array using LINQ in C#.
So let's split it into three separate parts:
- Given a filename, open the file and read a sequence of lines
- given a sequence of lines, change it into a sequence of [index, line]
- given a sequence of [index, line] change it to the string format you want
And of course we want to do this all very LINQ-like, because we like LINQ (pun intended)
Let's do this writing extension functions. See Extension Methods Demystified
static class MyExtensionMethods
{
// TODO add the extension methods
}
The first one: input a string fileName, output a sequence of lines (= strings)
public static IEnumerable<string> ReadLines(this string fileName)
{
// TODO: check fileName not null, empty; check file exists
FileInfo file = new FileInfo(fileName);
using (TextReader reader = file.OpenText())
{
string line = reader.ReadLine();
while (line != null)
{
yield return line;
line = reader.ReadLine();
}
}
Convert a sequence of Lines into a sequence of [index, line]
IEnumerable<KeyValuePair<int, string>> ToIndexedLines(this IEnumerable<string> lines)
{
return lines.Select( (line, index) => new KeyValuePair<int, string>(index, line));
}
And the third function: given a sequence of [index, line] convert it to a sequence of strings.
To make this re-usable I'll use a format string, so the caller can decide how to print his output. The format string has indexes {0}
and {1}
IEnumerable<string> ToString(this IEnumerable<KeyValuePair<int, string>> indexLines,
string formatString)
{
// TODO: check input not null
return indexLines.Select(keyValuePair =>
String.Format(formatString, keyValuePair.Key, keyValuePair.Value);
}
After three one-liner functions we are able to read your file in a LINQ like fashion
const string fileName = "MyFile.Csv";
const string myFormatString = "{1} //array[{0}]";
IEnumerable<string> myRequestedOutput = fileName.ReadLines()
.ToIndexedLines()
.ToString(myFormatString);
Simple comme bonjour!