with the following code Im trying to read a csv file that contains double values and convert it into a list. If I want to print that list The output just contains "system.collections.generic.list1 system.string". What is wrong in my code?
var filePath = #"C:\Users\amuenal\Desktop\Uni\test.csv";
var contents = File.ReadAllText(filePath).Split(';');
var csv = from line in contents
select line.Split(';').ToList();
foreach (var i in csv)
{
Console.WriteLine(i);
}
You got a couple things wrong with your code. First, you should most likely be using ReadAllLines() instead of ReadAllText(). Secondly, your LINQ query was returning a List<List<string>> which I imagine is not what you wanted. I would try something like this:
var filePath = #"C:\Users\amuenal\Desktop\Uni\test.csv";
//iterate through all the rows
foreach (var row in File.ReadAllLines(filePath))
{
//iterate through each column in each row
foreach(var col in row.Split(';'))
{
Console.WriteLine(col);
}
}
This should do good. Hope this helps.
var filePath = #"C:\Users\amuenal\Desktop\Uni\test.csv";
var contents = File.ReadAllLines(filePath);
var csv = (from line in contents
select line.Split(';')).SelectMany(x1 => x1);
foreach (var i in csv)
{
Console.WriteLine(i);
}
csv is an IEnumerable of a List of string. (in other words, each "i" is a list of string).
You need two loops:
foreach (var list in csv)
{
foreach(var str in list)
{
Console.WriteLine(str);
}
}
Related
I have a program that checks two text files for a specific field then checks to see if either file has the specified field. If it does then the number of matches is stored into another List. The problem I am having is that it is only writing the first match to the text file, when I know I have two matches. I am fairly new to C# so any help/advice would be appreciated, the code below is doing the check.
while ((lineBeingRead = fileToRead.ReadLine()) != null)
{
if (lineBeingRead.IndexOf(" :22:", 0) == 0)
{
lstTwentyOneCounter.Add(lineBeingRead.Substring(11));
lstStoreTwentyOne = lstTwentyOneCounter;
}
}
The code below is writing to the text file.
foreach (var single103 in lstStore103)
{
foreach (var single101 in lstStore101)
{
if (single101 == single103)
{
checkResults.Add(single103);
System.IO.File.WriteAllText(#"H:\Compare.txt", single103);
break;
}
}
}
Thanks,
Ryan
WriteAllText will overwrite the existing file - so only a single entry will appear to be written.
You will want to append or write all instead.
System.IO.File.Delete(#"H:\Compare.txt");
foreach (var single103 in lstStore103)
{
foreach (var single101 in lstStore101)
{
if (single101 == single103)
{
checkResults.Add(single103);
System.IO.File.AppendAllText(#"H:\Compare.txt", single103 + Environment.NewLine);
}
}
}
or (if neither lstStore103 nor lstStore101 have duplicates):
System.IO.File.Delete(#"H:\Compare.txt");
foreach (var value in lstStore103.Intersect(lstStore101))
{
checkResults.Add(value);
System.IO.File.AppendAllText(#"H:\Compare.txt", value + Environment.NewLine);
}
The break; is responsible, it will leave the loop.
But you also don't want to use WriteAllText which rewrites the whole text-file but you want to append a new line. I would use this approach:
string startPattern = " :22:";
List<string> lstStoreTwentyOne = File.ReadLines(path)
.Where(l => l.StartsWith(startPattern))
.Select(l => l.Substring(startPattern.Length))
.ToList();
This will create and fill the list. I don't know how this is related to the lstStore103-list.
However, this will write all to the text-file and replaces your loops:
var matchingItems = lstStore103.Intersect(lstStore101);
File.WriteAllLines(#"H:\Compare.txt", matchingItems);
I've been struggling with a small piece of code for a little while now. I have a CSV file with one column that contains a string of numbers. I can import that file without issues and display it.
My goal is to take the numbers in each of the tables and put it into a separate string, run that string through a function and then put the results back into my datagrid in column two. Is there a way that I should be doing this using the code below; the foreach statement is where I believe this should be done.
Edit: I tweaked the code and it now works the way that I want it to but I can't insert my result into any columns except for the first one. Is there a way that I should be targeting the results so they go in the second column?
using (var fs = File.OpenRead(Dialog.FileName))
using (var reader = new StreamReader(fs))
{
List<string> lista = new List<string>();
List<string> listb = new List<string>();
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
var values = line.Split(',');
lista.Add(values[0]);
dt1.Rows.Add(values[0]);
}
foreach (var item in lista)
{
string temp;
GetLuhnCheckDigit(item);
listb.Add(last.ToString());
temp = item + last.ToString();
dt1.Rows.Add(temp); //This only adds to the first column
}
dataGridView1.DataSource = dt1;
Without knowing what GetLuhnCheckDigit method does, it is not possible to determine what values you want the second column to contain. Looking at the posted code, there are many things missing like how many columns the data table has, where is the Dialog variable definition? What is last?
Assuming there are at least two columns in the DataTable dt1, I am not sure why you are adding the items to the first column then loop through a list of those items to set the second column. It appears adding both of the columns at the same time would be easier.
You could do all this while reading the file like below:
try {
using (var fs = File.OpenRead(Dialog.FileName)) {
using (var reader = new StreamReader(fs)) {
List<string> lista = new List<string>();
List<string> listb = new List<string>();
string temp;
while (!reader.EndOfStream) {
var line = reader.ReadLine();
var values = line.Split(',');
lista.Add(values[0]);
GetLuhnCheckDigit(values[0]); // <-- What is this method doing???
listb.Add(last.ToString());
temp = values[0] + last.ToString();
dt1.Rows.Add(values[0], temp); // <-- this adds both columns
}
dataGridView1.DataSource = dt1;
}
}
}
catch (Exception e) {
MessageBox.Show("Error: " + e.Message);
}
Let me know if I am missing something, as I am clueless as to what the GetLuhnCheckDigit method could be doing.
I've been trying to figure out how to remove elements in my ArrayList where the value contains some text string.
My Array could look like this:
[0] "\"MAERSKA.CO\",N/A,N/A,N/A,N/A,N/A,N/A"
[1] "\"GEN.COABB.ST\",N/A,N/A,N/A,N/A,N/A,N/A"
[2] "\"ARCM.ST\",\"Arcam AB\",330.00,330.50,332.00,330.50,330.00"
And my ArrayList is created like this:
string stringToRemove = "NA";
ArrayList rows = new ArrayList(csvData.Replace("\r", "").Split('\n'));
So the question is how I delete all entries that contains "NA".
I have tried the RemoveAt or RemoveAll with several combinations of Contains but i cant seem to get the code right.
I do not want to make a new Array if it can be avoided.
Regards
Flemming
If you want to reduce your ArrayList before instantiate your variable, consider using LINQ:
ArrayList rows = new ArrayList(csvData.Replace("\r", "").Split('\n').Where(r => !r.Contains(stringToRemove)).ToList());
If you want to reduce your ArrayList after instantiation, you can try this:
for (int i = 0; i < rows.Count; i++)
{
var row = (string)rows[i];
if (row.Contains(stringToRemove))
{
rows.RemoveAt(i);
i--;
}
}
The following code creates a list as output containing all strings except "N/A":
var outputs = new List<string>();
foreach (var item in input)
{
var splitted = item.Split(',');
foreach (var splt in splitted)
{
if (splt != "N/A")
{
outputs.Add(splt);
}
}
}
The input is your array.
I have the following list of stings taken from a csv file...
List<string> listOfRecords;
Each line is a string in the list...
one,bob,black
two,steve,smith
three,bill,brown
one,jill,brown
one,sue,smith
I would like to remove duplicates based on the first value on each line. Resulting in...
one,bob,black
two,steve,smith
three,bill,brown
I thought the code would look something like....
distinctlist = Select listOfRecords.split(',')[0].distinct
this is obviously wrong but I wanted to avoid making a list of lists and doing it that way. Thinking linq would be simpler.
All the posts I can find on here seem quite complex or do not address the specifics of my question. Any help would be greatly appreciated...
Simple with a GroupBy:
var distinctByFirstColumn = listOfRecords
.GroupBy(x => x.Split(',')[0])
.Select(x => x.First());
I'd rather use HashSet<String> and simple foreach loop instead of Linq (which, IMHO, is overshoot) here:
var distinctList = new List<String>();
HashSet<String> taken = new HashSet<String>();
foreach (var line in listOfRecords)
// you don't want to split all the line, but 1st item only
if (taken.Add(line.SubString(0, line.IndexOf(',')))
distinctList.Add(line);
Edit: In case of a real csv file:
private static IEnumerable<String> CsvDistinctLines(String fileName) {
HashSet<String> taken = new HashSet<String>();
foreach (var line in File.ReadLines(fileName))
if (taken.Add(line.SubString(0, line.IndexOf(',')))
yield return line;
}
...
var distinctList = CsvDistinctLines(#"C:\MyFile.csv").ToList();
At the moment I have my code to get some files from a Dir.
foreach (var file in
Directory.GetFiles(MainForm.DIRECTORY_PATH, "*.csv"))
{
//Process File
string[] values = File.ReadAllLines(file)
.SelectMany(lineRead => lineRead.Split(',')
.Select(s => s.Trim()))
.ToArray();
I want to be able to order these file by date order first before i start reading them and processing them.
I looked at a suggestion on MDSN to use DirectoryInfo:
DirectoryInfo DirInfo = new DirectoryInfo(MainForm.DIRECTORY_PATH);
var filesInOrder = from f in DirInfo.EnumerateFiles()
orderby f.CreationTime
select f;
foreach (var item in filesInOrder)
{
//Process File
string[] values = File.ReadAllLines(item )
.SelectMany(lineRead => lineRead.Split(',')
.Select(s => s.Trim()))
.ToArray();
}
this doesnt work however as the System.IO.File.ReadAllLine(file) seems to red line with the error as item is a string and not an actual file. :(
Does anyone know a solution to this or has had a similar issue? :)
Regards
J.
From MSDN File.ReadAllLines(string path) takes file path as input.
Opens a text file, reads all lines of the file, and then closes the file.
You have to pass file path:
string[] values = File.ReadAllLines(item.FullName)
your code:
foreach (var item in filesInOrder)
{
string[] values = File.ReadAllLines(item.FullName)
...............................
...............................
}
You can replace all of your chunk with following code via lambda expressions:
var values = DirInfo.EnumerateFiles().OrderBy(f => f.CreationTime)
.Select(x => File.ReadAllLines(x.FullName)
.SelectMany(lineRead => lineRead.Split(',')
.Select(s => s.Trim())).ToArray()
);
Your first code snippet reads all lines in one file, where as the second one reads from all files in the directory. So it is not very clear what you want to do.
The second code snippet cannot work, because the variable values is declared inside the loop. Its visibility scope is limited to the code block of the loop. The result will therefore never be visible outside of the loop.
var filesInOrder = from f in DirInfo.EnumerateFiles() ...;
var items = new List<string>();
foreach (FileInfo f in filesInOrder) {
using (StreamReader sr = f.OpenText()) {
while (!sr.EndOfStream) {
items.AddRange(sr.ReadLine().Split(','));
}
}
}
Here I define a List<string> before the loop that will hold all the items of all files. We need two loops: one that loops over the files (foreach) and one that reads the lines in each file and successively adds items to the list (while).