I recently started work on a project that searches a CSV file for duplicate entries and present the user the option to delete one or both entries.
Simple enough it would seem, however I am having an issue with the function that actually parses the CSV file into memory.
Here is the code in question...
using System;
using System.IO;
using Microsoft.VisualBasic.FileIO;
using System.Collections.Generic;
using System.Windows.Forms;
public List<string[]> parseCSV(string path)
{
List<string[]> parsedData = new List<string[]>();
string[] fields;
TextFieldParser parser = null;
string line = parser.ReadLine();
try
{
/*TextFieldParser*/ parser = new TextFieldParser(#"c:\temp\test.csv");
parser.TextFieldType = FieldType.Delimited;
parser.SetDelimiters(",");
while (!parser.EndOfData)
{
fields = parser.ReadFields();
parsedData.Add(fields);
//Did more stuff here with each field.
}
parser.Close();
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
return parsedData;
}
For some reason in VS2017 parseCSV is underlined in red in the function declaration.
I can't figure out why this is. I've tried the obvious fixes such as changing the function name from parseCSV to something else but that obviously didn't.
In C# everything is contained in a class, you can't just declare a method within a namespace directly.
using System;
using System.IO;
using Microsoft.VisualBasic.FileIO;
using System.Collections.Generic;
using System.Windows.Forms;
class MyLearningOnlyCsvParser {
public List<Customer_Data> parseCSV(string path)
{
List<Customer_Data> parsedData = new List<Customer_Data>();
string[] fields;
TextFieldParser parser = null;
string line = parser.ReadLine();
try
{
/*TextFieldParser*/ parser = new TextFieldParser(#"c:\temp\test.csv");
parser.TextFieldType = FieldType.Delimited;
parser.SetDelimiters(",");
while (!parser.EndOfData)
{
fields = parser.ReadFields();
// assume the CSV is always with 11 columns
if(fields.length == 11) {
Customer_Data newData = new Customer_Data();
newData.name = fields[0];
newData.company = fields[1];
// assign to the rest of the customer data properties with each fields
parsedData.Add(newData);
}
else {
// error handling of not well formed CSV
}
}
parser.Close();
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
return parsedData;
}
}
Related
I want to read csv file and save to list or array or anything, but CsvHelper demands to save it as collection of specific type. Problem is my csv has so many columns, that mapping it to custom class will take a few weeks.
How can I just read it without saving as specific type? Accessing specific values with thing like row[1][2] is more than enough for me.
Add it to a datatable
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Data;
namespace ConsoleApplication23
{
class Program
{
const string FILENAME = #"c:\temp\test.csv";
static void Main(string[] args)
{
StreamReader reader = new StreamReader(FILENAME);
string line = "";
DataTable dt = new DataTable();
int rowCount = 0;
while((line = reader.ReadLine()) != null)
{
line = line.Trim();
if (line.Length > 0)
{
string[] splitArray = line.Split(new char[] { ',' });
if (rowCount == 0)
{
foreach (string col in splitArray)
{
dt.Columns.Add(col, typeof(string));
}
}
else
{
dt.Rows.Add(splitArray);
}
}
}
}
}
}
This question already has answers here:
Reading CSV files using C#
(12 answers)
Closed 3 years ago.
The code below reads a CSV file and looks for a line containing the serial number which is the first column of the file. Then copies that line to another file. The code works fine.
I need to read the text in the second and third fields of the row (there are 12 fields) and assign them to string variables (for other uses).
Can you help me, Please.
I am a novice.
List<string> found = new List<string>();
string line;
using(StreamReader file = new StreamReader(input_filename))
{
while((line=file.ReadLine())!=null)
{
if(line.Contains("XA2345")) // Serial Number
{
found.Add(line);
using(StreamWriter w = File.AppendText(output_filename))
{
// Console.WriteLine(line);
w.WriteLine(line);
w.Flush();
}
}
}
}
I'd start with some best practices for parsing CSV files with the post Parsing CSV files in C#, with header.
I've also noticed you've got that "found" variable. Are you trying to avoid duplicate lines in your output file but the code is incomplete? I've written the following code under that assumption.
Here are the using statements:
using Microsoft.VisualBasic.FileIO;
using System.Collections.Generic;
using System.IO;
using System.Linq;
Here's the main code:
List<string> foundLines = new List<string>();
using (TextFieldParser parser = new TextFieldParser(inputFilename))
{
// Set up the parser for CSV files
parser.TextFieldType = FieldType.Delimited;
parser.SetDelimiters(",");
using (StreamWriter writer = new StreamWriter(outputFilename, false))
{
while (!parser.EndOfData)
{
string[] values = parser.ReadFields();
string serialNumber = values[0];
if (string.Equals(serialNumber, "XA2345"))
{
string line = string.Join(",", values.Select(Escape));
if (foundLines.Contains(line))
continue; // Skip writing this line more than once
else
foundLines.Add(line); // Remember this line for later
writer.WriteLine(line);
// Do what you need to with the individual column values
string secondValue = values[1];
string thirdValue = values[2];
// ... Etc. ...
}
}
}
}
And here's a CSV helping method for escaping values as needed at Good CSV writer for C#:
static private string Escape(string s)
{
const string QUOTE = "\"";
const string ESCAPED_QUOTE = "\"\"";
char[] CHARACTERS_THAT_MUST_BE_QUOTED = { ',', '"', '\n' };
if (s.Contains(QUOTE))
s = s.Replace(QUOTE, ESCAPED_QUOTE);
if (s.IndexOfAny(CHARACTERS_THAT_MUST_BE_QUOTED) > -1)
s = QUOTE + s + QUOTE;
return s;
}
I have a homework assignment to create a C# console program. It should create a text file with 2 phrases:
Hello, World!
Goodbye, Cruel World!
Then I also must create a program to read the 2 phrases from the file.
After two hours this is what I have. It works, but I want to rewrite the program to be more efficient. I am mainly struggling on how to output the file into a .cs file capable of running.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace ConsoleApplication3
{
class Program
{
static void Main(string[] args)
{
//structure.txt contains the program we will enter our values into.
String filePath = "Structure.txt";
WriteToFile(filePath);
}
public static void WriteToFile(string filePath)
{
//create a string array to gather our text file information.
StreamReader reader = new StreamReader(filePath);
StreamReader info = new StreamReader("Structure.txt");
StreamWriter writer = new StreamWriter("Hello.cs", true);
String temp = String.Empty;
while (!info.EndOfStream)
{
String tempstring = String.Empty;
tempstring = reader.ReadLine();
while (!reader.EndOfStream)
{
temp = reader.ReadLine();
writer.WriteLine(temp);
if (temp == "//break")
{
writer.WriteLine("String1 = {}", tempstring);
}
}
}
reader.Close();
info.Close();
writer.Close();
}
}
}
More efficient? sure
// write
string[] lines = new [] {"Hello, World!", "Goodbye, Cruel World!"};
File.WriteAllLines("c:\\myFile.txt", lines);
// read
string[] lines = File.ReadAllLines("c:\\myFile.txt");
This is all. . .
I am currently trying to make an .exe in c# that I can drag and drop a .txt file onto to remove lines of text that contain the keywords "CM" and/or "Filling". It must be able to overwrite the existing data so there are no new files created. The filename is different every time except for the extension. The data is tab delimited if that has any bearing. I'm aware that there are similar questions to this but I haven't managed to adapt them to suit my needs. Also, I'm very new to this and I've been trying for about a week with no luck.
if (args.Length == 0)
return; // return if no file was dragged onto exe
string text = File.ReadAllText("*.txt");
text = text.Replace("cm", "");
string path = Path.GetDirectoryName(args[0])
+ Path.DirectorySeparatorChar
+ Path.GetFileNameWithoutExtension(args[0])
+ "_unwrapped" + Path.GetExtension(args[0]);
File.WriteAllText("*.txt", text);
\\attempt 1
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Text.RegularExpressions;
namespace ConsoleApp4
{
class Program
{
static void Main(string[] args)
{
string concrete = "CM";
string line;
using (StreamReader reader = new StreamReader(#"C:\\Users\drocc_000\Desktop\1611AN24T99-041805221704.txt"))
{
using (StreamWriter writer = new StreamWriter(#"C:\\Users\drocc_000\Desktop\1611AN24T99-041805221704NEW.txt"))
{
while ((line = reader.ReadLine()) != null)
{
// if (String.Compare(line, yourName) == 0)
// continue;
writer.WriteLine(line.Replace(concrete, ""));
}
}
}
\\attempt 2
Thanks for your time.
Regards,
Danny
You can create a console application with the code below and then drag and drop your text file into the .exe file without opening it.
class Program
{
static void Main(string[] args)
{
if (args.Length > 0 && File.Exists(args[0]))
{
string path = args[0];
EditFile(new List<string>() { "CM", "Filling" }, path);
}
Console.Read();
}
public static void EditFile(List<string> keyWords, string filename)
{
List<string> lines = new List<string>();
using (StreamReader sr = new StreamReader(filename))
{
while (sr.Peek() >= 0)
{
lines.Add(sr.ReadLine());
}
sr.Close();
}
int removedLinesCount = 0;
bool writeline;
using (StreamWriter sw = new StreamWriter(filename))
{
foreach (var line in lines)
{
writeline = true;
foreach (var str in keyWords)
{
if (line.Contains(str))
{
writeline = false;
removedLinesCount++;
break;
}
}
if (writeline)
sw.WriteLine(line);
}
Console.WriteLine(removedLinesCount + " lines removed from the file " + filename);
sw.Close();
}
}
}
Something like this?
using System;
using System.IO;
using System.Linq;
namespace ConsoleApp1
{
internal static class Program
{
private static void Main(string[] args)
{
try
{
// Get the filename from the applications arguments
string filename = args[0];
// Read in all lines in the file.
var linesInFile = File.ReadLines(filename);
// Filter out the lines we don't need.
var linesToKeep = linesInFile.Where(line => !line.Contains("CM") && !line.Contains("Filling")).ToArray();
// Overwrite the file.
File.WriteAllLines(filename, linesToKeep);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
}
}
I am working on a CSV parser using C# TextFieldParser class.
My CSV data is deliminated by , and the string is enclosed by a " character.
However, sometimes the data row cell can also have a " which appears to be making the parser throw an exception.
This is my C# code so far:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Microsoft.VisualBasic.FileIO;
namespace CSV_Parser
{
class Program
{
static void Main(string[] args)
{
// Init
string CSV_File = "test.csv";
// Proceed If File Is Found
if (File.Exists(CSV_File))
{
// Test
Parse_CSV(CSV_File);
}
// Finished
Console.WriteLine("Press any to exit ...");
Console.ReadKey();
}
static void Parse_CSV(String Filename)
{
using (TextFieldParser parser = new TextFieldParser(Filename))
{
parser.TextFieldType = FieldType.Delimited;
parser.SetDelimiters(",");
parser.TrimWhiteSpace = true;
while (!parser.EndOfData)
{
string[] fieldRow = parser.ReadFields();
foreach (string fieldRowCell in fieldRow)
{
// todo
}
}
}
}
}
}
This is the content of my test.csv file:
" dummy test"s data", b , c
d,e,f
gh,ij
What is the best way to deal with " in my row cell data?
UPDATE
Based on Tim Schmelter's answer, I have modified my code to the following:
static void Parse_CSV(String Filename)
{
using (TextFieldParser parser = new TextFieldParser(Filename))
{
parser.TextFieldType = FieldType.Delimited;
parser.SetDelimiters(",");
parser.HasFieldsEnclosedInQuotes = false;
parser.TrimWhiteSpace = true;
while (parser.PeekChars(1) != null)
{
var cleanFieldRowCells = parser.ReadFields().Select(
f => f.Trim(new[] { ' ', '"' }));
Console.WriteLine(String.Join(" | ", cleanFieldRowCells));
}
}
}
Which appears to produce the following (correctly):
Is this is the best way to deal with string enclosed by quotes, having quotes?
Could you omit the quoting-character by setting HasFieldsEnclosedInQuotes to false?
using (var parser = new TextFieldParser(#"Path"))
{
parser.HasFieldsEnclosedInQuotes = false;
parser.Delimiters = new[]{","};
while(parser.PeekChars(1) != null)
{
string[] fields = parser.ReadFields();
}
}
You can remove the quotes manually:
var cleanFields = fields.Select(f => f.Trim(new[]{ ' ', '"' }));