When I read a CSV (smicolon separated) with this method:
public List<string> LoadCSV()
{
List<string> displayName = new List<string>();
List<string> groupName = new List<string>();
using (StreamReader reader = new StreamReader(#"\\aPath\to\aFile.csv"))
{
while (!reader.EndOfStream)
{
String line = reader.ReadLine();
String[] values = line.Split(';');
displayName.Add(values[0]);
groupName.Add(values[6]);
}
}
return displayName;
}
The blanks in displayName get deleted.
One line in the file:
Adobe Acrobat Standard - (Win XP);16477;2;3657;AD Group;1233xxoo_AcrobatStd;1835
For my understanding, this should give for the line above this result:
Adobe Acrobat Standard - (Win XP)
But it's this:
AdobeAcrobatStandard-(WinXP)
Can somebody help?
It's an OutlookAddin. This is how I run the method:
string bodyText = "RealNames:\n";
foreach (string s in LoadCSV()) {
bodyText += s +"\n";
}
openMail.Body = bodyText;
Related
I want to compare two csv files and print the differences in a file. I currently use the code below to remove a row. Can I change this code so that it compares two csv files or is there a better way in c# to compare csv files?
List<string> lines = new List<string>();
using (StreamReader reader = new StreamReader(System.IO.File.OpenRead(path)))
{
string line;
while ((line = reader.ReadLine()) != null)
{
if (line.Contains(csvseperator))
{
string[] split = line.Split(Convert.ToChar(scheidingsteken));
if (split[selectedRow] == value)
{
}
else
{
line = string.Join(csvseperator, split);
lines.Add(line);
}
}
}
}
using (StreamWriter writer = new StreamWriter(path, false))
{
foreach (string line in lines)
writer.WriteLine(line);
}
}
Here is another way to find differences between CSV files, using Cinchoo ETL - an open source library
For the below sample CSV files
sample1.csv
id,name
1,Tom
2,Mark
3,Angie
sample2.csv
id,name
1,Tom
2,Mark
4,Lu
METHOD 1:
Using Cinchoo ETL, below code shows how to find differences between rows by all columns
var input1 = new ChoCSVReader("sample1.csv").WithFirstLineHeader().ToArray();
var input2 = new ChoCSVReader("sample2.csv").WithFirstLineHeader().ToArray();
using (var output = new ChoCSVWriter("sampleDiff.csv").WithFirstLineHeader())
{
output.Write(input1.OfType<ChoDynamicObject>().Except(input2.OfType<ChoDynamicObject>(), ChoDynamicObjectEqualityComparer.Default));
output.Write(input2.OfType<ChoDynamicObject>().Except(input1.OfType<ChoDynamicObject>(), ChoDynamicObjectEqualityComparer.Default));
}
sampleDiff.csv
id,name
3,Angie
4,Lu
Sample fiddle: https://dotnetfiddle.net/nwLeJ2
METHOD 2:
If you want to do the differences by id column,
var input1 = new ChoCSVReader("sample1.csv").WithFirstLineHeader().ToArray();
var input2 = new ChoCSVReader("sample2.csv").WithFirstLineHeader().ToArray();
using (var output = new ChoCSVWriter("sampleDiff.csv").WithFirstLineHeader())
{
output.Write(input1.OfType<ChoDynamicObject>().Except(input2.OfType<ChoDynamicObject>(), new ChoDynamicObjectEqualityComparer(new string[] { "id" })));
output.Write(input2.OfType<ChoDynamicObject>().Except(input1.OfType<ChoDynamicObject>(), new ChoDynamicObjectEqualityComparer(new string[] { "id" })));
}
Sample fiddle: https://dotnetfiddle.net/t6mmJW
If you only want to compare one column you can use this code:
List<string> lines = new List<string>();
List<string> lines2 = new List<string>();
try
{
StreamReader reader = new StreamReader(System.IO.File.OpenRead(pad));
StreamReader read = new StreamReader(System.IO.File.OpenRead(pad2));
string line;
string line2;
//With this you can change the cells you want to compair
int comp1 = 1;
int comp2 = 1;
while ((line = reader.ReadLine()) != null && (line2 = read.ReadLine()) != null)
{
string[] split = line.Split(Convert.ToChar(seperator));
string[] split2 = line2.Split(Convert.ToChar(seperator));
if (line.Contains(seperator) && line2.Contains(seperator))
{
if (split[comp1] != split2[comp2])
{
//It is not the same
}
else
{
//It is the same
}
}
}
reader.Dispose();
read.Dispose();
}
catch
{
}
So I am trying display my data from a StreamReader outside of the using portion. I am able to display it all INSIDE of the StreamReader however showing it OUTSIDE of the StreamReader is proving more complicated.
I understand that my while loop inside the StreamReader will show all the data I need (and it is). But I need it to show from the for loop that I have at the bottom. (While loop was left in just as a reference).
When I run it through the for loop I either get
"end
end
end
end"
or
"end
of
record
indicator"
I get the "Ends" when i use the array index number in the for loop, and the "end of record indicator" when i use the "i".
How can I get it to display what my while loop is displaying?
class Program
{
static void Main(string[] args)
{
string[] lineOutVar;
using (StreamReader readerOne = new StreamReader("../../FileIOExtraFiles/DataFieldsLayout.txt"))
{
string lineReader = readerOne.ReadLine();
string[] lineOutput = lineReader.Split('\n');
lineOutVar = lineOutput;
while (readerOne.EndOfStream == false)
{
lineOutVar = readerOne.ReadLine().Split();
Console.WriteLine(lineOutVar[0]);
}
}
for (int i = 0; i < lineOutVar.Length; i++)
{
Console.WriteLine(lineOutVar[0]);
}
Use List class.
List<string> lineOutVar = new List<string>();
using (System.IO.StreamReader readerOne = new System.IO.StreamReader("../../FileIOExtraFiles/DataFieldsLayout.txt"))
{
while(readerOne.EndOfStream == false)
{
string lineReader = readerOne.ReadLine();
lineOutVar.Add(lineReader); //add the line to the list of string
}
}
foreach(string line in lineOutVar) //loop through each of the line in the list of string
{
Console.WriteLine(line);
}
to get the content:
string[] lineOutVar;
List<string[]> lst_lineOutVar = new List<string[]>();
using (StreamReader readerOne = new StreamReader("E:\\TEST\\sample.txt"))
{
string lineReader = readerOne.ReadLine();
string[] lineOutput = lineReader.Split('\n');
lineOutVar = lineOutput;
while (readerOne.EndOfStream == false)
{
lineOutVar = new string[1];
lineOutVar = readerOne.ReadLine().Split();
lst_lineOutVar.Add(lineOutVar);
//Console.WriteLine(lineOutVar[0]);
}
String getcontent = string.Empty;
foreach (var getLst in lst_lineOutVar)
{
getcontent = getcontent + "," + getLst[0].ToString();
}
Console.WriteLine(getcontent);
}
You could also just skip the StreamReader and use File.ReadAllLines:
string[] lineOutVar = File.ReadAllLines("../../FileIOExtraFiles/DataFieldsLayout.txt");
Now you have an array of the file lines, and you can loop over them and split them however you like.
I am trying to figure out how to tokenize a StreamReader of a text file. I have been able to separate the lines, but now I am trying to figure out how to break down those lines by a tab delimiter as well. This is what I have so far.
string readContents;
using (StreamReader streamReader = new StreamReader(#"File.txt"))
{
readContents = streamReader.ReadToEnd();
string[] lines = readContents.Split('\r');
foreach (string s in lines)
{
Console.WriteLine(s);
}
}
Console.ReadLine();
string readContents;
using (StreamReader streamReader = new StreamReader(#"File.txt"))
{
readContents = streamReader.ReadToEnd();
string[] lines = readContents.Split('\r');
foreach (string s in lines)
{
string[] lines2 = s.Split('\t');
foreach (string s2 in lines2)
{
Console.WriteLine(s2);
}
}
}
Console.ReadLine();
not really sure if that is what you want, but... it breaks (tab) the already broken (return) lines
Just call Split() on each of the lines and keep them in a List. If you need an array you can always call ToArray() on the list:
string readContents;
using (StreamReader streamReader = new StreamReader(#"File.txt"))
{
readContents = streamReader.ReadToEnd();
string[] lines = readContents.Split('\r');
List<string> pieces = new List<string>();
foreach (string s in lines)
{
pieces.AddRange(s.Split('\t'));
Console.WriteLine(s);
}
}
Console.ReadLine();
Based on Prakash's answer here, I thought I'd try something like this to remove the oldest lines in a file prior to adding a new line to it:
private ExceptionLoggingService()
{
_fileStream = File.OpenWrite(GetExecutionFolder() + "\\Application.log");
_streamWriter = new StreamWriter(_fileStream);
}
public void WriteLog(string message)
{
const int MAX_LINES_DESIRED = 1000;
StringBuilder formattedMessage = new StringBuilder();
formattedMessage.AppendLine("Date: " + DateTime.Now.ToString());
formattedMessage.AppendLine("Message: " + message);
// First, remove the earliest lines from the file if it's grown too much
List<string> logList = File.ReadAllLines(_fileStream).ToList();
while (logList.Count > MAX_LINES_DESIRED)
{
logList.RemoveAt(0);
}
File.WriteAllLines(_fileStream, logList.ToArray());
_streamWriter.WriteLine(formattedMessage.ToString());
_streamWriter.Flush();
}
...but in my version of .NET (Compact Framework, Windows CE C# project in VS 2008), neither ReadAllLines() nor WriteAllLines() are available.
What is the ReadAllLines/WriteAllLines-challenged way of accomplishing the same thing?
UPDATE
This is doubtless kludgy, but it seems like it should work, and I'm going to test it out. I moved the "shorten the log file" code from the WriteLog() method to the constructor:
private ExceptionLoggingService()
{
const int MAX_LINES_DESIRED = 1000;
string uriPath = GetExecutionFolder() + "\\Application.log";
string localPath = new Uri(uriPath).LocalPath;
if (!File.Exists(localPath))
{
File.Create(localPath);
}
_fileStream = File.OpenWrite(localPath);
// First, remove the earliest lines from the file if it's grown too much
StreamReader reader = new StreamReader(_fileStream);
List<String> logList = new List<String>();
while (!reader.EndOfStream)
{
logList.Add(reader.ReadLine());
}
while (logList.Count > MAX_LINES_DESIRED)
{
logList.RemoveAt(0);
}
if (logList.Count > MAX_LINES_DESIRED)
{
_fileStream.Close();
File.Delete(GetExecutionFolder() + "\\Application.log");
File.Create(GetExecutionFolder() + "\\Application.log");
_fileStream = File.OpenWrite(GetExecutionFolder() + "\\Application.log");
}
_streamWriter = new StreamWriter(_fileStream);
foreach (String s in logList)
{
_streamWriter.WriteLine(s);
_streamWriter.Flush();
}
}
public void WriteLog(string message)
{
StringBuilder formattedMessage = new StringBuilder();
formattedMessage.AppendLine("Date: " + DateTime.Now.ToString());
formattedMessage.AppendLine("Message: " + message);
_streamWriter.WriteLine(formattedMessage.ToString());
_streamWriter.Flush();
}
ReadAllLines and WriteAllLines are just hiding a loop from you. Just do:
StreamReader reader = new StreamReader(_fileStream);
List<String> logList = new List<String>();
while (!reader.EndOfStream)
logList.Add(reader.ReadLine());
Note that this is nearly identical to the implementation of File.ReadAllLines (from MSDN Reference Source)
String line;
List<String> lines = new List<String>();
using (StreamReader sr = new StreamReader(path, encoding))
while ((line = sr.ReadLine()) != null)
lines.Add(line);
return lines.ToArray();
WriteAllLines is simialr:
StreamWriter writer = new StreamWriter(path, false); //Don't append!
foreach (String line in logList)
{
writer.WriteLine(line);
}
I would write simple extension methods for this, that do the job lazily without loading whole file to memory.
Usage would be something like this:
outfile.MyWriteLines(infile.MyReadLines().Skip(1));
public static class Extensions
{
public static IEnumerable<string> MyReadLines(this FileStream f)
{
var sr = new StreamReader(f);
var line = sr.ReadLine();
while (line != null)
{
yield return line;
line = sr.ReadLine();
}
}
public static void MyWriteLines(this FileStream f, IEnumerable<string> lines)
{
var sw = new StreamWriter(f);
foreach(var line in lines)
{
sw.WriteLine(line);
}
}
}
I'm having a question about writing data to a CSV file.
I have a file named test.csv in which are 2 fields > accountnumber and relation ID.
Now I want to add another field next to it: IBAN.
The IBAN is the data from the first row which is validated by the SOAP function BBANtoIBAN.
How can I keep the 2 rows of data accountnumbers and relation IDs in the CSV and add the IBAN in the 3rd row?
This is my code so far:
using (var client = new WebService.BANBICSoapClient("IBANBICSoap"))
{
List<List<string>> dataList = new List<List<string>>();
TextFieldParser parser = new TextFieldParser(#"C:\CSV\test.csv");
parser.TextFieldType = FieldType.Delimited;
parser.SetDelimiters(";");
while (!parser.EndOfData)
{
List<string> data = new List<string>();
string row = parser.ReadLine();
try
{
string resultIBAN = client.BBANtoIBAN(row);
if (resultIBAN != string.Empty)
data.Add(resultIBAN);
else
data.Add("Accountnumber is not correct.");
}
catch (Exception msg)
{
Console.WriteLine(msg);
}
dataList.Add(data);
}
}
I see it as:
StreamReader sr = new StreamReader(#"C:\CSV\test.csv")
StreamWriter sw = new StreamWriter(#"C:\CSV\testOut.csv")
while (sr.Peek() >= 0)
{
string line = sr.ReadLine();
try
{
string[] rowsArray = line.Split(';');
string row = rowsArray[0];
string resultIBAN = client.BBANtoIBAN(row);
if (resultIBAN != string.Empty)
{
line +=";"+ resultIBAN;
}
else
{
line +=";"+"Accountnumber is not correct.";
}
}
catch (Exception msg)
{
Console.WriteLine(msg);
}
sw.WriteLine(line)
}
sr.Close();
sw.Close();
I would do something like this to parse the csv file, and add an extra item to the data list:
List<List<string>> dataList = new List<List<string>>();
string filename = #"C:\CSV\test.csv";
using (StreamReader sr = new StreamReader(filename))
{
string fileContent = sr.ReadToEnd();
foreach (string line in fileContent.Split(new string[] {Environment.NewLine},StringSplitOptions.RemoveEmptyEntries))
{
List<string> data = new List<string>();
foreach (string field in line.Split(';'))
{
data.Add(field);
}
try
{
string resultIBAN = client.BBANtoIBAN(data[0]);
if (resultIBAN != string.Empty)
{
data.Add(resultIBAN);
}
else
{
data.Add("Accountnumber is not correct.");
}
}
catch (Exception msg)
{
Console.WriteLine(msg);
}
dataList.Add(data);
}