How to read CSV file group by group - c#

I want to read a .csv file which has some repeated lines. I want to read between this repeated line. For example a is the repeated line and before the second a, I have lines such as 1,2,3.
I want to read write these values between a values. Can you help me?

It was a bit unclear. But perhaps this will do:
var lines = new List<string>(File.ReadLines("input.csv"));
foreach (string line in lines)
{
if (line.StartsWith("a")) continue;
// insert code to modify the other lines
}
// ... and later
File.WriteAllLines("output.csv", lines);

Related

Read a CSV file and writer into a file without " " using C#

I am trying to read a CSV file and stored all the values in the single list.CSV file contains credentials as uid(userid) and pass(password) and separated by','I have successfully read all the lines and write it in the file.but when it writes in the file, it write the value in between " "(double quotes) like as("abcdefgh3 12345678")what i want actually to remove this "" double quotes sign when i write it in to the files.i am pasting my code here:
static void Main(string[] args)
{
var reader = new StreamReader(File.OpenRead(#"C:\Desktop\userid1.csv"));
List<string> listA = new List<string>();
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
var values = line.Split(',');
listA.Add(values[0]);
listA.Add(values[1]);
}
foreach (string a in listA)
{
TextWriter tr = new StreamWriter(#"E:\newfiless",true);
tr.Write(a);
tr.Write(tr.NewLine);
tr.Close();
}
}
and the resulted output is like this:
"uid
pass"
"Martin123
123456789"
"Damian
91644"
but i want in this form:
uid
pass
Martin123
123456789
Damian
91644
Thanking you all in advance.
The original file clearly has quotes, which makes it a CSV file with only one colum and in that column there are two values. Not usual, but it happens.
To actually remove quotes you can use Trim, TrimEnd or TrimStart.
You can remove the quotes while reading, or while writing, in this case it doesn't really matter.
var line = reader.ReadLine().Trim('"');
This will remove the quotes while reading. Note that this assumes the CSV is of this "broken" variant.
tr.WriteLine(a.Trim('"'));
This will handle it on write. This will work even if the file is "correct" CSV having two columns and values in quotes.
Note that you can use WriteLine to add the newline, no need for two Write calls.
Also as others have commented, don't create a TextWriter in the loop for every value, create it once.
using (TextWriter tr = new StreamWriter(#"E:\newfiless"))
{
foreach (string a in listA)
{
tr.WriteLine(a.Trim('"'));
}
}
The using will take care of closing the file and other possible resources even if there is an exception.
I assume that all you need to read the input file, strip out all starting/ending quotation marks, then split by comma and write it all to another file. You can actually accomplish it in a one-liner using SelectMany, which will produce a "flat" collection:
File.WriteAllLines(
#"c:\temp\output.txt",
File
.ReadAllLines(#"c:\temp\input.csv")
.SelectMany(line => line.Trim('"').Split(','))
);
It's not quite clear from your example where quotation marks are located in the file. For a typical .CSV file some comma-separated field might be wrapped in quotation marks to allow commas to be a part of the content. If it's the case, then parsing will be more complex.
You can use
tr.Write(a.Substring(1, line.Length - 2));
Edited
Please use Trim
tr.Write(a.TrimEnd('"').TrimStart('"'));

reading and copying lines of text in a specific way

I have five lines of text in a text file that I want to read and write in the following way:
read 1st line and copy it to new text file 1.
read 1st and 2nd line and copy them to new text file 2.
read 1st, 2nd and 3rd line and copy them to new text file 3.
read 1st, 2nd, 3rd and 4th line and copy them to new text file 4.
read all lines and copy them to new text file 5.
I have tried something with loops, but I just get confused. Or maybe to use recursion....?
Something like that (just Linq with Take)
// ..Or ReadAllLines to cache the file lines
var source = File.ReadLines(#"C:\MyText.txt");
File.WriteAllLines(#"C:\target1.txt", source.Take(1));
File.WriteAllLines(#"C:\target2.txt", source.Take(2));
File.WriteAllLines(#"C:\target3.txt", source.Take(3));
File.WriteAllLines(#"C:\target4.txt", source.Take(4));
// not 5 lines, but entire file
File.WriteAllLines(#"C:\target5.txt", source);
I created a basic solution for you.. Please check for the rest, this is just for help you out.
List<String> lines = File.ReadLines(#"C:\Users\m\Desktop\te\source.txt").ToList();
string basicPath = #"C:\Users\m\Desktop\te\";
int i = 1;
foreach (string line in lines)
{
File.WriteAllLines(basicPath + i + ".txt", lines.GetRange(0, i));
i++;
}

C# so I need to split out a string, I think

so I have this application that I have inherited from someone that is long gone. The gist of the application is that it reads in a .cvs file that has about 5800 lines in it, copies it over to another .cvs, which it creates new each time, after striping out a few things , #, ', &. Well everything works great, or it has until about a month ago. so I started checking into it, and what I have found so far is that there are about 131 items missing from the spreadsheet. Now I read someplace that the maximun amount of data a string can hold is over 1,000,000,000 chars, and my spreadsheet is way under that, around 800,000 chars, but the only thing I can think is doing it is the string object.
So anyway, here is the code in question, this piece appears
to both read in from the existing field, and output to the new file:
StreamReader s = new StreamReader(File);
//Read the rest of the data in the file.
string AllData = s.ReadToEnd();
//Split off each row at the Carriage Return/Line Feed
//Default line ending in most windows exports.
//You may have to edit this to match your particular file.
//This will work for Excel, Access, etc. default exports.
string[] rows = AllData.Split("\r\n".ToCharArray(), System.StringSplitOptions.RemoveEmptyEntries);
//Now add each row to the DataSet
foreach (string r in rows)
{
//Split the row at the delimiter.
string[] items = r.Split(delimiter.ToCharArray());
//Add the item
result.Rows.Add(items);
}
If anyone can help me I would really appreciate it. I either need to figure out how to split the data better, or I need to figure out why it is cutting out the last 131 lines from the existing excel file to the new excel file.
One easier way to do this, since you're using "\r\n" for lines, would be to just use the built-in line reading method: File.ReadLines(path)
foreach(var line in File.ReadLines(path))
{
var items = line.Split(',');
result.Rows.Add(items);
}
You may want to check out the TextFieldParser class, which is part of the Microsoft.VisualBasic.FileIO namespace (yes, you can use this with C# code)
Something along the lines of:
using(var reader = new TextFieldParser("c:\\path\\to\\file"))
{
//configure for a delimited file
reader.TextFieldType = FieldType.Delimited;
//configure the delimiter character (comma)
reader.Delimiters = new[] { "," };
while(!reader.EndOfData)
{
string[] row = reader.ReadFields();
//do stuff
}
}
This class can help with some of the issues of splitting a line into its fields, when the field may contain the delimiter.

Reading a specific line from a csv file and letting the line vary

I need to take 1 line from a CSV file and need the line number to be able to vary. I can make an int, double, string etc. and I can change the value from an outer program easily but I don't know how make a file reader script take one of those as the input for the line number.
string GetLine(string lineresults, int LineNumber)
{
using (var sr = new StreamReader(lineresults)) {
for (int i = 1; i < line; i++)
sr.ReadLine();
return sr.ReadLine();
}
}
And I get errors on the GetLine part for semicolons and closeparens expected
If you want random access you can read all lines and store them in an array, so File.ReadAllLines (remember that your variable LineNumber starts at 0):
string[] allLines = File.ReadAllLines(pathToFile);
string line = allLines[LineNumber]; // error if less lines, check allLines.Length
Another more efficient approach is to use File.ReadLines which lazy loads the lines, then use Enumerable.ElementAt or ElementAtOrDefault to access the line number:
var lines = File.ReadLines(pathToFile);
string line = lines.ElementAtOrDefault(LineNumber); // null if there are less lines
It is worth noting that it reads the file until the line number or the end of the file was reached.
MSDN:
The ReadLines and ReadAllLines methods differ as follows: When you use
ReadLines, you can start enumerating the collection of strings before
the whole collection is returned; when you use ReadAllLines, you must
wait for the whole array of strings be returned before you can access
the array. Therefore, when you are working with very large files,
ReadLines can be more efficient
As #Alex K commented simply read all the lines into an Array and then get the line you are after.
var lines = System.IO.File.ReadAllLines( filename);
var line = lines[ lineIndex ];
This NuGet package is super-duper helpful for working with CSVs. You can grab individual lines from it, and individual columns by either name or index. Check out info here:
[Josh Close - CsvHelper][1]

txt file read/overwrite/append. Is this feasible? (Visual C#)

I'm writing a program for some data entry I have to periodically do. I have begun testing a few things that the program will have to do but i'm not sure about this part.
What i need this part to do is:
read a .txt file of data
take the first 12 characters from each line
take the first 12 characters from each line of the data that has been entered in a multi-line text box
compare the two lists line by line
if one of the 12 character blocks from the multi-line text box match one of the blocks in the .txt file then overwrite that entire line (only 17 characters in total)
if one of the 12 character blocks from the multi-line text box DO NOT match any of the blocks in the.txt file then append that entire line to the file
thats all it has to do.
i'll do an example:
TXT FILE:
G01:78:08:32 JG05
G08:80:93:10 JG02
G28:58:29:28 JG04
MULTI-LINE TEXT BOX:
G01:78:08:32 JG06
G28:58:29:28 JG03
G32:10:18:14 JG01
G32:18:50:78 JG07
RESULTING TXT FILE:
G01:78:08:32 JG06
G08:80:93:10 JG02
G28:58:29:28 JG03
G32:10:18:14 JG01
G32:18:50:78 JG07
as you can see lines 1 and 3 were overwriten, line 2 was left alone as it did not match any blocks in the text box, lines 4 and 5 were appended to the file.
thats all i want it to do.
How do i go about this?
Thanks in advance
Edit
The code i'm using is this:
private void WriteToFile()
{
// Read all lines from file into memory
System.IO.StreamReader objReader = new System.IO.StreamReader("Jumpgate List.JG");
List<String> fileTextList = new List<String>();
do
{
fileTextList.Add(objReader.ReadLine());
}
while (objReader.Peek() != -1);
objReader.Close();
// Read all lines from the Input textbox into memory
System.IO.StringReader objReaderi = new System.IO.StringReader(txtInput.Text);
List<String> inputTextList = new List<String>();
do
{
inputTextList.Add(objReaderi.ReadLine());
}
while (objReaderi.Peek() != -1);
objReaderi.Close();
for(int i=0;i<fileTextList.Count;i++)
{
for(int j=0;j<inputTextList.Count;j++)
//compare the first 12 characters of each string
if (String.Compare(fileTextList[i], 0, inputTextList[j], 0, 12) == 0) // strings are equal
{
//replace the fileTextList string with the inputTextList string
fileTextList[i] = inputTextList[j];
// now that you have matched you inputTextList line you remember not to append it at the end
inputTextList[j] = String.Empty; // or nothing
}
}
for(int i=0;i<inputTextList.Count;i++)
{
if (!string.IsNullOrEmpty(inputTextList[i])) fileTextList.Add(inputTextList[i]);
}
System.IO.StreamWriter objWriter = new System.IO.StreamWriter("Jumpgate List.JG");
// Overwrite the Jumpgate List.JG file using the updated fileTextList
objWriter.Write(fileTextList);
objWriter.Close();
}
However, when i open the txt file all i get is: System.Collections.Generic.List`1[System.String]
I'm not going to write the whole code for doing this but it would be something like this:
Disclaimer: I have not used a code editor to try the code, just wrote it here, hopefully you'll get the idea and fill in the missing pieces :)
1) get all the lines in the file in a list. Something like this
StreamReader rd = new StreamReader("sadasd");
List<String> llist = new List<String>();
do
{
llist.Add(rd.ReadLine());
} while (rd.Peek() != -1);
2) get all the lines in your multiline text box (the procedure should be similar to the one above): multiTextList
3) now that you can compare the content of the 2 lists iterating through them
for(int i=0;i<fileTextList.Count;i++)
{
for(int j=0;j<multiTextList.Count;j++)
//compare the first 12 characters of each string
if String.Compare(fileTextList[i], 0, multiTextList[j], 0, 12) == 0 // strings are equal
{
//replace the initial line with whatever you want
fileTextList[i] = //whatever
// now that you have matched you multiTextList line you remember not to append it at the end
multiTextList[j] = String.empty // or nothing
}
}
4) at the end you will have in fileTextList the initial rows, modified where necessary
In multiTextList you will have only the lines that were not matched so we add them to the initial file rows
for(int i=0;i<multiTextList.Count;i++)
{
if !string.isnullorempty(multitextlist[i]) fileTextList.add(multitextlist[i])
}
5) now in fileTextList you have all the rows you require so you can print them one by one in a file and you have your result
StringBuilder lSb = new StringBuilder();
for (int i = 0; i < fileTextList.Count; i++)
{
lSb.AppendLine(fileTextList[i]);
}
File.WriteAllText(#"C:/test2.txt",lSb.ToString());
In C:/test2.txt you should have the results.
Hope this helps!
// this variable maps the timestamps to complete lines
var dict = new Dictionary<string, string>();
// create the map of stamp => line for the original text file
string fileLine = file.ReadLine();
string fileStamp = fileLine.Substring(0, 12);
dict[fileStamp] = fileLine;
// now update the map with results from the text input. This will overwrite text
// strings that already exist in the file
foreach (string inputLine in textInputString.Split('\n'))
{
string inputStamp = inputLine.Substring(0, 12);
dict[inputStamp] = inputLine;
}
// write out the new file with the updated lines
foreach (string line in dict.Values)
{
outputFile.WriteLine(line);
}
if the file is large, loading the entire file into a dictionary to update a handful of lines from a textfield is probably excessive.
In pseudocode I would probably:
Create a list of booleans or other structure to track if a line was matched.
open the file in read/write mode.
For each line in file
{
for each unmatched line in text field
{
If stamps match
Update file
record that it was matched
}
}
for each unmatched line in text field
{
append to file
}
If the lines are fixed width, you can probably optimize by only reading the stamp rather than the whole line. If they match your file pointer is in the right spot to start writing, if not you move to the next line.

Categories