Comparing rows in a csv file - c#

I am currently using the below code to compare two csv files with each other. This code gives an output with all the rows that are not the same. But when a row is missing everything after that row is not the same. How can I fix this? Thanks in advance.
List<string> lines = new List<string>();
List<string> lines2 = new List<string>();
try
{
StreamReader reader = new StreamReader(System.IO.File.OpenRead(file1));
StreamReader read = new StreamReader(System.IO.File.OpenRead(file2));
List<string> differences = new List<string>();
string line;
string line2;
int i = 0;
while ((line = reader.ReadLine()) != null && (line2 = read.ReadLine()) != null)
{
string[] split = line.Split(Convert.ToChar("\t"));
string[] split2 = line2.Split(Convert.ToChar("\t"));
if (split[i] != split2[i])
{
differences.Add("this row is not the same:, " + line);
}
else
{
}
i++;
}
System.IO.File.WriteAllLines(differencesFile, differences);
reader.Dispose();
read.Dispose();
}
catch
{
}

After help from a friend I made it work with this code:
List<string> file1 = new List<string>();
List<string> output = new List<string>();
string differencesFile = path;
File.WriteAllText(differencesFile, "");
try
{
StreamReader readFile1 = new StreamReader(System.IO.File.OpenRead(pathfile1));
string lineFile1;
while ((lineFile1 = readFile1.ReadLine()) != null)
{
bool match = false;
string[] colums = lineFile1.Split('\t');
StreamReader readFile2 = new StreamReader(System.IO.File.OpenRead(pathfile2));
string line2;
while ((line2 = readFile2.ReadLine()) != null)
{
string[] columsFile2 = line2.Split('\t');
if (colums[0] == columsFile2[0])
{
match = true;
}
}
if (!match)
{
output.Add(colums[0] + "; doesnt exist in pathfile2");
}
}
System.IO.File.WriteAllLines(differencesFile, output);
}
catch { }

Related

Add data to CSV if string is not found

I have an application that updates data within a CSV. What I am trying to add is, if the "name" is not in the CSV, then add it. I have tried changing the while to an if/then, but that gave me no results, just a blank line within the CSV.
Code:
using (StreamReader reader = new StreamReader(path))
{
String line;
while ((line = reader.ReadLine()) != null)
{
if (line.Split(',')[0].Equals("newName"))
{
String[] split = line.Split(',');
split[1] = tPoints.ToString();
line = String.Join(",", split);
}
lines.Add(line);
}
}
using (StreamWriter writer = new StreamWriter(path))
{
foreach (String line in lines)
writer.WriteLine(line);
}
Current CSV Data:
name,734937
If item is NOT found, I am trying have it add a new row. So expected result would be something similar to below:
name,734937
newName,0
You can try something like this:
bool termFound = false;
string searchTerm = "newName";
var lines = new List<string>();
using (StreamReader reader = new StreamReader("input.csv"))
{
string line;
while ((line = reader.ReadLine()) != null)
{
lines.Add(line);
if (line.Split(',')[0].Equals(searchTerm))
termFound = true;
}
}
using (StreamWriter writer = new StreamWriter("output.csv"))
{
foreach (string line in lines)
writer.WriteLine(line);
if(termFound == false)
writer.WriteLine($"{searchTerm},0");
}

CSV update/modification

Trying to override a single record of the following CSV:
PRODUCT,RECORD,ACCOUNT
100,200,300
using this code:
public static void UpdateCSV(string filePath, string stringToReplace, string updatedString)
{
string path = filePath;
List<string> lines = new List<string>();
if (File.Exists(path))
{
using (StreamReader reader = new StreamReader(path))
{
string line;
while ((line = reader.ReadLine()) != null)
{
if (line.Contains(","))
{
string[] split = line.Split(',');
if (split[1].Contains(stringToReplace))
{
split[1] = updatedString;
line = string.Join(",", split);
}
}
lines.Add(line);
}
}
using (StreamWriter writer = new StreamWriter(path, false))
{
foreach (string line in lines)
writer.WriteLine(line);
}
}
}
But invoking the following does not make a difference ('PRODUCT' does not change to 'MYPRODUCT'):
UpdateCSV(#"C:\Test.csv", "PRODUCT", "MYPRODUCT");
What's wrong here?

C# search all files in a directory that contain a string, then return that string

Using user input into a textbox, I want to search for which file in the directory contains that text. I would then like to parse out the information
but I can't seem to find the string or at least return the information. Any help would be greatly appreciated.
My current code:
private void btnSearchSerial_Click(object sender, EventArgs e)
{
dynamic dirScanner = #"\\mypath\";
string strSerial;
string strSID;
string strInputLine;
string strOutput;
strSerial = Convert.ToString(txtSerialSearch);
strSID = Convert.ToString(txtSID);
if (txtSerialSearch.Text != "" && txtSID.Text != "")
{
try
{
string[] allFiles = Directory.GetFiles(dirScanner);
foreach (string file in allFiles)
{
if (file.EndsWith(".txt"))
{
using (StreamReader sr = new StreamReader(file))
{
while (sr.Peek() >= 0)
{
strInputLine = sr.ReadLine();
if (strInputLine.Contains(strSerial))
{
strOutput = Convert.ToString(strInputLine);
lblOutput.Text = Convert.ToString(strOutput);
}
}
}
}
}
}
}
}
You seem quite lost. Why are you using a dynamic when a string is all that you need? Your code has too many unnecessary variables and convertions. Here's a much simpler way to do it. I don't know what you want the label to have if there are many matching lines, here I'm only placing the first one there:
string dirScanner = #"\\mypath\";
if (string.IsNullOrWhiteSpace(txtSerialSearch.Text) || string.IsNullOrWhiteSpace(txtSID.Text))
return;
string[] allFiles = Directory.GetFiles(dirScanner, "*.txt");
foreach (string file in allFiles)
{
string[] lines = File.ReadAllLines(file);
string firstOccurrence = lines.FirstOrDefault(l => l.Contains(txtSerialSearch.Text));
if (firstOccurrence != null)
{
lblOutput.Text = firstOccurrence;
break;
}
}
I have implemented the same using Regular Expressions. You need to use namespace using System.Text.RegularExpressions;
string strSerial = #"Microsoft";
Regex match = new Regex(strSerial);
string matchinglines = string.Empty;
List<string> filenames = new List<string>(Directory.GetFiles(textBox1.Text));
foreach(string filename in filenames)
{
//StreamReader strFile = new StreamReader(filename);
string fileContent = File.ReadAllText(filename);
if(match.IsMatch(fileContent))
{
label1.Text = Regex.Match(fileContent, strSerial).ToString();
break;
}
}
Use System.LINQ:
var list_of_files_that_match = Directory.EnumerateFiles(dir).Where(delegate (string t)
{
return System.IO.File.ReadAllText(t).Contains(your_text);
}).ToList();
This worked for me. Quick and simple.

Populating a dataset from a CSV file

I would like to read the contents of a CSV file and create a dataset.
I am trying like this:
var lines = File.ReadAllLines("test.csv").Select(a => a.Split(';'));
DataSet ds = new DataSet();
ds.load(lines);
but apparently this is not correct.
You need to add the reference Microsoft.VisualBasic.dll to use TextFieldParser Class.
private static DataTable GetDataTabletFromCSVFile(string csv_file_path)
{
DataTable csvData = new DataTable();
try
{
using(TextFieldParser csvReader = new TextFieldParser(csv_file_path))
{
csvReader.SetDelimiters(new string[] { "," });
csvReader.HasFieldsEnclosedInQuotes = true;
string[] colFields = csvReader.ReadFields();
foreach (string column in colFields)
{
DataColumn datecolumn = new DataColumn(column);
datecolumn.AllowDBNull = true;
csvData.Columns.Add(datecolumn);
}
while (!csvReader.EndOfData)
{
string[] fieldData = csvReader.ReadFields();
//Making empty value as null
for (int i = 0; i < fieldData.Length; i++)
{
if (fieldData[i] == "")
{
fieldData[i] = null;
}
}
csvData.Rows.Add(fieldData);
}
}
}
catch (Exception ex)
{
}
return csvData;
}
}
See this article for more info : http://www.morgantechspace.com/2013/08/how-to-read-data-from-csv-file-in-c.html
You need to run a SELECT statement against the CSV file to fill the dataset:
Edit: here's some sample code from http://carllbrown.blogspot.co.uk/2007/09/populate-dataset-from-csv-delimited_18.html
string FileName = ...
OleDbConnection conn = new OleDbConnection
("Provider=Microsoft.Jet.OleDb.4.0; Data Source = " +
Path.GetDirectoryName(FileName) +
"; Extended Properties = \"Text;HDR=YES;FMT=Delimited\"");
conn.Open();
OleDbDataAdapter adapter = new OleDbDataAdapter
("SELECT * FROM " + Path.GetFileName(FileName), conn);
DataSet ds = new DataSet("Temp");
adapter.Fill(ds);
conn.Close();
You can use Library like Fast CSV Reader then
using System.IO;
using LumenWorks.Framework.IO.Csv;
void ReadCsv()
{
// open the file "data.csv" which is a CSV file with headers
using (CsvReader csv = new CsvReader(
new StreamReader("data.csv"), true))
{
myDataRepeater.DataSource = csv;
myDataRepeater.DataBind();
}
}
Comma (,) Problem Solved in This Code
Works Even If you add Commas(,) in between a cell
Reading CSV file CODE:
public MainWindow()
{
InitializeComponent();
DataTable dtDataSource = new DataTable();
string[] fileContent = File.ReadAllLines(#"..\\Book1.csv");
if (fileContent.Count() > 0)
{
//Create data table columns dynamically
string[] columns = fileContent[0].Split(',');
for (int i = 0; i < columns.Count(); i++)
{
dtDataSource.Columns.Add(columns[i]);
}
//Add row data dynamically
for (int i = 1; i < fileContent.Count(); i++)
{
string[] rowData = fileContent[i].Split(',');
string[] realRowData = new string[columns.Count()];
StringBuilder collaboration = new StringBuilder();
int v = 0;
//this region solves the problem of a cell containing ",".
#region CommaSepProblem
for (int j = 0, K = 0; j < rowData.Count(); j++, K++)
{
if ((rowData[j].Count(x => x == '"') % 2 == 0))//checks if the string contains even number of DoubleQuotes
{
realRowData[K] = quotesLogic((rowData[j]));
}
else if ((rowData[j].Count(x => x == '"') % 2 != 0))//If Number of DoubleQuotes are ODD
{
int c = rowData[j].Count(x => x == '"');
v = j;
while (c % 2 != 0)//Go through all the next array cell till it makes EVEN Number of DoubleQuotes.
{
collaboration.Append(rowData[j] + ",");
j++;
c += rowData[j].Count(x => x == '"');
}
collaboration.Append(rowData[j]);
realRowData[K] = quotesLogic(collaboration.ToString());
}
else { continue; }
}
#endregion
dtDataSource.Rows.Add(realRowData);
}
if (dtDataSource != null)
{
//dataGridView1 = new DataGridView();
dataGrid1.ItemsSource = dtDataSource.DefaultView;
}
}
}
Method Need to be added:
string quotesLogic(string collaboration)
{
StringBuilder after = new StringBuilder(collaboration);
if (after.ToString().StartsWith("\"") && after.ToString().EndsWith("\""))//removes 1st and last quotes as those are system generated
{
after.Remove(0, 1);
after.Remove(after.Length - 1, 1);
int count = after.Length - 1;
//FACT: if you try to add DoubleQuote in a cell in excel. It'll save that quote as 2 times DoubleQuote(Like "") which means first DoubleQuote is to give instruction to CPU that the next DoubleQuote is not system generated.
while (count > 0)//This loop find twice insertion of 2 DoubleQuotes and neutralise them to One DoubleQuote.
{
if (after[count] == '"' && after[count - 1] == '"')
{
after.Remove(count, 1);
}
count--;
}
}
return after.ToString();
}
If you just want to quickly create a DataTable filled with sample data from a CSV file (or pasted directly from Excel) to play around or prototype, then you can use my fork of Shan Carter's Mr. Data Converter -- I recently added the ability to output comma- and tab-delimited data to a C# DataTable.
http://thdoan.github.io/mr-data-converter/
I have written five methods below that will turn a Csv file into a DataTable.
They have been designed to take into account optional quote marks (e.g. " symbols) and to be as versatile as possible without using other libraries:
public static DataTable GetDataTabletFromCSVFile(string filePath, bool isHeadings)
{
DataTable MethodResult = null;
try
{
using (TextFieldParser TextFieldParser = new TextFieldParser(filePath))
{
if (isHeadings)
{
MethodResult = GetDataTableFromTextFieldParser(TextFieldParser);
}
else
{
MethodResult = GetDataTableFromTextFieldParserNoHeadings(TextFieldParser);
}
}
}
catch (Exception ex)
{
ex.HandleException();
}
return MethodResult;
}
public static DataTable GetDataTableFromCsvString(string csvBody, bool isHeadings)
{
DataTable MethodResult = null;
try
{
MemoryStream MemoryStream = new MemoryStream();
StreamWriter StreamWriter = new StreamWriter(MemoryStream);
StreamWriter.Write(csvBody);
StreamWriter.Flush();
MemoryStream.Position = 0;
using (TextFieldParser TextFieldParser = new TextFieldParser(MemoryStream))
{
if (isHeadings)
{
MethodResult = GetDataTableFromTextFieldParser(TextFieldParser);
}
else
{
MethodResult = GetDataTableFromTextFieldParserNoHeadings(TextFieldParser);
}
}
}
catch (Exception ex)
{
ex.HandleException();
}
return MethodResult;
}
public static DataTable GetDataTableFromRemoteCsv(string url, bool isHeadings)
{
DataTable MethodResult = null;
try
{
HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(url);
HttpWebResponse httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse();
StreamReader StreamReader = new StreamReader(httpWebResponse.GetResponseStream());
using (TextFieldParser TextFieldParser = new TextFieldParser(StreamReader))
{
if (isHeadings)
{
MethodResult = GetDataTableFromTextFieldParser(TextFieldParser);
}
else
{
MethodResult = GetDataTableFromTextFieldParserNoHeadings(TextFieldParser);
}
}
}
catch (Exception ex)
{
ex.HandleException();
}
return MethodResult;
}
private static DataTable GetDataTableFromTextFieldParser(TextFieldParser textFieldParser)
{
DataTable MethodResult = null;
try
{
textFieldParser.SetDelimiters(new string[] { "," });
textFieldParser.HasFieldsEnclosedInQuotes = true;
string[] ColumnFields = textFieldParser.ReadFields();
DataTable dt = new DataTable();
foreach (string ColumnField in ColumnFields)
{
DataColumn DataColumn = new DataColumn(ColumnField);
DataColumn.AllowDBNull = true;
dt.Columns.Add(DataColumn);
}
while (!textFieldParser.EndOfData)
{
string[] Fields = textFieldParser.ReadFields();
for (int i = 0; i < Fields.Length; i++)
{
if (Fields[i] == "")
{
Fields[i] = null;
}
}
dt.Rows.Add(Fields);
}
MethodResult = dt;
}
catch (Exception ex)
{
ex.HandleException();
}
return MethodResult;
}
private static DataTable GetDataTableFromTextFieldParserNoHeadings(TextFieldParser textFieldParser)
{
DataTable MethodResult = null;
try
{
textFieldParser.SetDelimiters(new string[] { "," });
textFieldParser.HasFieldsEnclosedInQuotes = true;
bool FirstPass = true;
DataTable dt = new DataTable();
while (!textFieldParser.EndOfData)
{
string[] Fields = textFieldParser.ReadFields();
if(FirstPass)
{
for (int i = 0; i < Fields.Length; i++)
{
DataColumn DataColumn = new DataColumn("Column " + i);
DataColumn.AllowDBNull = true;
dt.Columns.Add(DataColumn);
}
FirstPass = false;
}
for (int i = 0; i < Fields.Length; i++)
{
if (Fields[i] == "")
{
Fields[i] = null;
}
}
dt.Rows.Add(Fields);
}
MethodResult = dt;
}
catch (Exception ex)
{
ex.HandleException();
}
return MethodResult;
}
If, like me, you're saving from reporting services then you should use it like this:
Warning[] warnings;
string[] streamids;
string mimeType;
string encoding;
string filenameExtension;
byte[] bytes = rvMain.ServerReport.Render("csv", null, out mimeType, out encoding, out filenameExtension, out streamids, out warnings);
string CsvBody = System.Text.Encoding.UTF8.GetString(bytes);
DataTable dt = GetDataTableFromCsvString(CsvBody,true);
Otherwise, all you need do is:
bool IsHeadings = true; //Does the data include a heading row?
DataTable dt = GetDataTableFromCsvString(CsvBody, IsHeadings);
Or to use directly from a csv file
bool IsHeadings = true; //Does the data include a heading row?
DataTable dt = GetDataTabletFromCsvFile(FilePath, IsHeadings)
Or to use a csv file that is stored remotely
bool IsHeadings = true; //Does the data include a heading row?
DataTable dt = GetDataTabletFromRemoteCsv(Url, IsHeadings)
A Dataset is a collection of DataTables, so create one like so:
DataSet ds = new DataSet();
ds.Tables.Add(dt);

File name from StreamReader C# - asp.net MVC3 to array

my application is MVC3 C#; I am populating two dropdownlists using json using the following:
public ActionResult CheckWord(string cword)
{
try
{
List<string[]> arrayList = new List<string[]>();
List<string[]> stateList = new List<string[]>();
//
List<string[]> fileList = new List<string[]>();
//
string[] filePaths = Directory.GetFiles(System.Web.HttpContext.Current.Server.MapPath("/Video"), "*.srt");
string[] fnList = new string[filePaths.Length];
for (int i = 0; i < fnList.Length; ++i)
{
FileInfo fi = new FileInfo(filePaths[i]);
fnList[i] = fi.Name.Substring(0, fi.Name.LastIndexOf(".srt"));
}
int nFiles = filePaths.Length;
string cacheline = "";
string line;
for (int i = 0; i < nFiles; ++i)
{
StreamReader file = new StreamReader(System.Web.HttpContext.Current.Server.MapPath("/Video/" + fnList[i] + ".srt"));
List<string> lines = new List<string>();
List<string> statments = new List<string>();
//
List<string> fnames = new List<string>();
//
while ((line = file.ReadLine()) != null)
{
if (line.Contains(cword))
{
statments.Add(line);
// fnames.Add(file);
lines.Add(cacheline);
}
cacheline = line;
}
file.Close();
var array = lines.ToArray();
arrayList.Add(array);
stateList.Add(statments.ToArray());
}
return Json(new { success = true, fnList = fnList, arrayList = arrayList.ToArray(), stateList = stateList.ToArray() });
}
catch { }
return Json(new { success = false });
}
I am checking if a word exists in a group of files; then display the names of files in one dropdownlist and the lines from each file in the other dropdownlist. It works fine, however it gives me a list of all files becasue I am sending back fnlist. However I am trying to display only the files that contain that word; I could not get the file name from the StreamReader and add it to an array fileList. I would appreciate your suggestions, thanks in advance.
Already so many lists! Why not another? You already open the file with fnList[i] within the context of the loop, so...
List<string[]> results = new List<string[]>();
....
while ((line = file.ReadLine()) != null) {
if (line.Contains(cword)) {
results.Add(fnList[i]);
break; // optional, if possible, but if you need to continue check for dupes
}
}
....
return Json(new {
success = true,
fnList = results.ToArray(),
arrayList = arrayList.ToArray(),
stateList = stateList.ToArray()
});
System.IO.StreamReader file = new System.IO.StreamReader("setup.txt");
Later on, we would like to print the name of the file being used by stream reader.
eg, if there is an error, I would like a message box that displays "error reading file: 'filename'"
MessageBox.Show("Error loading " + ((FileStream)file.BaseStream).Name);
Not sure what exactly you are looking for but since you are creating StreamReader from a file name why not have file name in a separate variable and use it later:
var fileName = System.Web.HttpContext.Current.Server.MapPath(
"/Video/" + fnList[i] + ".srt");
StreamReader file = new StreamReader(fileName);

Categories

Resources