How To Make this Code work - c#

static void Main()
{
FileStream fs = new FileStream("Scheduler.txt",FileMode.Open, FileAccess.Read);
StreamReader filereader = new StreamReader(fs);
string linevalue = "";
ArrayList items = new ArrayList();
while ((linevalue = filereader.ReadLine()) != null)
{
items.Add(linevalue);
}
filereader.Close();
items.Sort();
IEnumerator myEnumerator = items.GetEnumerator();
while (myEnumerator.MoveNext())
{
Console.WriteLine(myEnumerator.Current);
}
}
My program needs trouble shooting. This program, i actually got it from SO by a brilliant guy but i am not able to trace back. I don't know what's wrong. I want everything that is stored in my text file to be stored and displayed through the array list. Any help would be appreciated.
It get's displayed but incorrectly.
My Text File has got the following details
Names Date Time
Leon 13/10/2013 10:00AM
Jyothika 18/10/2013 12:18PM
Angelina 21/09/2000 01:45AM
Instead of displaying it in the same manner, it displays like
Angelina 21/09/2000 01:45AM
Names Dates Time
Leon 13/10/2013 10:00AM
Jyothika 18/10/2013 12:18PM

The problem is your reading linevalue again before adding to items:
You can do it in an easier way:
var lines = File.ReadAllLines("Scheduler.txt").ToList();
lines.Sort();
foreach(var line in lines) Console.WriteLine( line );

Try this:
while ((linevalue = filereader.ReadLine()) != null)
{
//linevalue = filereader.ReadLine();
items.Add(linevalue);
}
An easier way:
// store your items
ArrayList items =
new ArrayList(File.ReadAllLines("Scheduler.txt").ToArray());
// output them, eventually
items.ToArray().ToList().ForEach(item =>
{
Console.WriteLine(item);
});

static void Main()
{
FileStream fs = new FileStream("Scheduler.txt",FileMode.Open, FileAccess.Read);
StreamReader filereader = new StreamReader(fs);
string linevalue = "";
ArrayList items = new ArrayList();
while ((linevalue = filereader.ReadLine()) != null)
{
//linevalue = filereader.ReadLine();
items.Add(linevalue);
}
filereader.Close();
items.Sort();
IEnumerator myEnumerator = items.GetEnumerator();
while (myEnumerator.MoveNext())
{
Console.WriteLine(myEnumerator.Current);
}
}

The problem is that the Title Line is a line, so it gets sorted with the other lines. There are various ways to solve this problem... Read the Title Line separately in another variable and not adding to the ArrayList, remove from the ArrayList the first row before sorting, sort only the rows after the first... I chose the last one and wrote some variants that show how the code could be written.
First level, not sort the first row, and using the using keyword, instead of manually closing the files.
ArrayList items = new ArrayList();
using (FileStream fs = new FileStream("Scheduler.txt", FileMode.Open, FileAccess.Read))
using (StreamReader filereader = new StreamReader(fs))
{
string linevalue = string.Empty;
while ((linevalue = filereader.ReadLine()) != null)
{
items.Add(linevalue);
}
}
Console.WriteLine(items[0]);
items.Sort(1, items.Count - 1, StringComparer.CurrentCulture);
IEnumerator myEnumerator = items.GetEnumerator();
myEnumerator.MoveNext(); // skip the first row
while (myEnumerator.MoveNext())
{
Console.WriteLine(myEnumerator.Current);
}
Second level, please forget of ArrayList... It's a child of a pre-literate world... I hope one day we will be able to forget that world. And using the GetEnumerator manually? There is the foreach (or the for, being the collection an ArrayList/List<string> for these things. The for is better, because we must skip the first row.
var items = new List<string>();
using (FileStream fs = new FileStream("Scheduler.txt", FileMode.Open, FileAccess.Read))
using (StreamReader filereader = new StreamReader(fs))
{
string linevalue = string.Empty;
while ((linevalue = filereader.ReadLine()) != null)
{
items.Add(linevalue);
}
}
Console.WriteLine(items[0]);
items.Sort(1, items.Count - 1, StringComparer.CurrentCulture);
for (int i = 1; i < items.Count; i++)
{
Console.WriteLine(items[i]);
}
Then we could remove the FileStream, because the StreamReader has a good-enough constructor...
using (StreamReader filereader = new StreamReader("Scheduler.txt"))
Or we could directly use the File.ReadAllLines that returns an array of string[].
string[] items = File.ReadAllLines("Scheduler.txt");
Console.WriteLine(items[0]);
Array.Sort(items, 1, items.Length - 1, StringComparer.CurrentCulture);
for (int i = 1; i < items.Length; i++)
{
Console.WriteLine(items[i]);
}
or, instead of the for, we could use a little LINQ:
foreach (string item in items.Skip(1))
{
Console.WriteLine(item);
}
and use the Skip method to skip the first row (these lines of LINQ are compatible with all the versions that don't use ArrayList)

Related

asp.net MVC Seed a database from a .TXT file with code first (over 10000 words) [duplicate]

I am using a list to limit the file size since the target is limited in disk and ram.
This is what I am doing now but is there a more efficient way?
readonly List<string> LogList = new List<string>();
...
var logFile = File.ReadAllLines(LOG_PATH);
foreach (var s in logFile) LogList.Add(s);
var logFile = File.ReadAllLines(LOG_PATH);
var logList = new List<string>(logFile);
Since logFile is an array, you can pass it to the List<T> constructor. This eliminates unnecessary overhead when iterating over the array, or using other IO classes.
Actual constructor implementation:
public List(IEnumerable<T> collection)
{
...
ICollection<T> c = collection as ICollection<T>;
if( c != null) {
int count = c.Count;
if (count == 0)
{
_items = _emptyArray;
}
else {
_items = new T[count];
c.CopyTo(_items, 0);
_size = count;
}
}
...
}
A little update to Evan Mulawski answer to make it shorter
List<string> allLinesText = File.ReadAllLines(fileName).ToList()
Why not use a generator instead?
private IEnumerable<string> ReadLogLines(string logPath) {
using(StreamReader reader = File.OpenText(logPath)) {
string line = "";
while((line = reader.ReadLine()) != null) {
yield return line;
}
}
}
Then you can use it like you would use the list:
var logFile = ReadLogLines(LOG_PATH);
foreach(var s in logFile) {
// Do whatever you need
}
Of course, if you need to have a List<string>, then you will need to keep the entire file contents in memory. There's really no way around that.
You can simple read this way .
List<string> lines = System.IO.File.ReadLines(completePath).ToList();
[Edit]
If you are doing this to trim the beginning of a log file, you can avoid loading the entire file by doing something like this:
// count the number of lines in the file
int count = 0;
using (var sr = new StreamReader("file.txt"))
{
while (sr.ReadLine() != null)
count++;
}
// skip first (LOG_MAX - count) lines
count = LOG_MAX - count;
using (var sr = new StreamReader("file.txt"))
using (var sw = new StreamWriter("output.txt"))
{
// skip several lines
while (count > 0 && sr.ReadLine() != null)
count--;
// continue copying
string line = "";
while ((line = sr.ReadLine()) != null)
sw.WriteLine(line);
}
First of all, since File.ReadAllLines loads the entire file into a string array (string[]), copying to a list is redundant.
Second, you must understand that a List is implemented using a dynamic array under the hood. This means that CLR will need to allocate and copy several arrays until it can accommodate the entire file. Since the file is already on disk, you might consider trading speed for memory and working on disk data directly, or processing it in smaller chunks.
If you need to load it entirely in memory, at least try to leave in an array:
string[] lines = File.ReadAllLines("file.txt");
If it really needs to be a List, load lines one by one:
List<string> lines = new List<string>();
using (var sr = new StreamReader("file.txt"))
{
while (sr.Peek() >= 0)
lines.Add(sr.ReadLine());
}
Note: List<T> has a constructor which accepts a capacity parameter. If you know the number of lines in advance, you can prevent multiple allocations by preallocating the array in advance:
List<string> lines = new List<string>(NUMBER_OF_LINES);
Even better, avoid storing the entire file in memory and process it "on the fly":
using (var sr = new StreamReader("file.txt"))
{
string line;
while ((line = sr.ReadLine()) != null)
{
// process the file line by line
}
}
Don't store it if possible. Just read through it if you are memory constrained. You can use a StreamReader:
using (var reader = new StreamReader("file.txt"))
{
var line = reader.ReadLine();
// process line here
}
This can be wrapped in a method which yields strings per line read if you want to use LINQ.
//this is only good in .NET 4
//read your file:
List<string> ReadFile = File.ReadAllLines(#"C:\TEMP\FILE.TXT").ToList();
//manipulate data here
foreach(string line in ReadFile)
{
//do something here
}
//write back to your file:
File.WriteAllLines(#"C:\TEMP\FILE2.TXT", ReadFile);
List<string> lines = new List<string>();
using (var sr = new StreamReader("file.txt"))
{
while (sr.Peek() >= 0)
lines.Add(sr.ReadLine());
}
i would suggest this... of Groo's answer.
string inLine = reader.ReadToEnd();
myList = inLine.Split(new string[] { "\r\n" }, StringSplitOptions.None).ToList();
I also use the Environment.NewLine.toCharArray as well, but found that didn't work on a couple files that did end in \r\n. Try either one and I hope it works well for you.
string inLine = reader.ReadToEnd();
myList = inLine.Split(new string[] { "\r\n" }, StringSplitOptions.None).ToList();
This answer misses the original point, which was that they were getting an OutOfMemory error. If you proceed with the above version, you are sure to hit it if your system does not have the appropriate CONTIGUOUS available ram to load the file.
You simply must break it into parts, and either store as List or String[] either way.

How do I show my data via a loop outside of a StreamReader

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.

Output not correctly being written to CSV

So I am having an issue with my output being written to a CSV file. The output to this code is in the correct format when being written to the CSV file but it is only entering a single row in the file. There should be much more. Around 150 lines. Current out put is:
(859.85 7N830127 185)
Which is correct, but there should be more of these. It seems like to me that it is only writing the first line of the parsed EDI file and then stopping. I need to find a way to make sure it writes all data that is being parsed can anyone help me?
static void Main(string[] args)
{
StreamReader sr = new StreamReader("edifile.txt");
string[] ediMapTemp = sr.ReadLine().Split('|');
List<string[]> ediMap = new List<string[]>();
List<object[]> outputMatrix = new List<object[]>();
foreach (var line in ediMapTemp)
{
ediMap.Add(line.Split('~'));
}
DetailNode node = new DetailNode(0, null, 0);
int hierarchicalDepth = 0;
int hierarchicalIdNumber;
int hierarchicalParentIdNumber;
int hierarchicalLevelCode;
int hierarchicalChildCode = 0;
for (int i = 0; i < ediMap.Count; i++)
{
string segmentHeader = ediMap[i][0];
if (segmentHeader == "HL")
{
hierarchicalIdNumber = Convert.ToInt32(ediMap[i][1]);
hierarchicalParentIdNumber = Convert.ToInt32(ediMap[i][2]);
hierarchicalLevelCode = Convert.ToInt32(ediMap[i][3]);
hierarchicalChildCode = Convert.ToInt32(ediMap[i][4]);
List<string[]> levelDetails = new List<string[]>();
for (int v = i + 1; v < ediMap.Count; v++)
{
if (ediMap[v][0] == "HL") break;
levelDetails.Add(ediMap[v]);
}
DetailNode getNode = node.Find(node, hierarchicalParentIdNumber);
getNode.headList.Add(new DetailNode(hierarchicalIdNumber, levelDetails, getNode.depth + 1));
}
}
node.Traversal(new VID(), node);
foreach (var vid in VIDList.vidList)
using (StreamWriter writer = new StreamWriter("Import.csv"))
{
//probably a loop here
writer.WriteLine(String.Join(",", vid.totalCurrentCharges, vid.assetId, vid.componentName, vid.recurringCharge));
}
}
Quick Review, should the code be the following:
using (StreamWriter writer = new StreamWriter("Import.csv"))
{
//a loop here
foreach (var vid in VIDList.vidList)
{
writer.WriteLine(String.Join(",", vid.totalCurrentCharges, vid.assetId, vid.componentName, vid.recurringCharge));
}
}
You would open the file once and then loop thru your collection, writing each one.
It looks to me like you're re-opening the output file for each line you're trying to write, so you're overwriting the output file with a new file for each line. That would mean only the last entry remains in the file. Try moving this line
using (StreamWriter writer = new StreamWriter("Import.csv"))
Outside the foreach loop.

c# Remove rows from csv

I have two csv files. In the first file i have a list of users, and in the second file i have a list of duplicate users. Im trying to remove the rows in the first file that are equal to the second file.
Heres the code i have so far:
StreamWriter sw = new StreamWriter(path3);
StreamReader sr = new StreamReader(path2);
string[] lines = File.ReadAllLines(path);
foreach (string line in lines)
{
string user = sr.ReadLine();
if (line != user)
{
sw.WriteLine(line);
}
File 1 example:
Modify,ABAMA3C,Allpay - Free State - HO,09072701
Modify,ABCG327,Processing Centre,09085980
File 2 Example:
Modify,ABAA323,Group HR Credit Risk & Finance
Modify,ABAB959,Channel Sales & Service,09071036
Any suggestions?
Thanks.
All you'd have to do is change the following file paths in the code below and you will get a file back (file one) without the duplicate users from file 2. This code was written with the idea in mind that you want something that is easy to understand. Sure there are other more elegant solutions, but I wanted to make it as basic as possible for you:
(Paste this in the main method of your program)
string line;
StreamReader sr = new StreamReader(#"C:\Users\J\Desktop\texts\First.txt");
StreamReader sr2 = new StreamReader(#"C:\Users\J\Desktop\texts\Second.txt");
List<String> fileOne = new List<string>();
List<String> fileTwo = new List<string>();
while (sr.Peek() >= 0)
{
line = sr.ReadLine();
if(line != "")
{
fileOne.Add(line);
}
}
sr.Close();
while (sr2.Peek() >= 0)
{
line = sr2.ReadLine();
if (line != "")
{
fileTwo.Add(line);
}
}
sr2.Close();
var t = fileOne.Except(fileTwo);
StreamWriter sw = new StreamWriter(#"C:\Users\justin\Desktop\texts\First.txt");
foreach(var z in t)
{
sw.WriteLine(z);
}
sw.Flush();
If this is not homework, but a production thing, and you can install assemblies, you'll save 3 hours of your life if you swallow your pride and use a piece of the VB library:
There are many exceptions (CR/LF between commas=legal in quotes; different types of quotes; etc.) This will handle anything excel will export/import.
Sample code to load a 'Person' class pulled from a program I used it in:
Using Reader As New Microsoft.VisualBasic.FileIO.TextFieldParser(CSVPath)
Reader.TextFieldType = Microsoft.VisualBasic.FileIO.FieldType.Delimited
Reader.Delimiters = New String() {","}
Reader.TrimWhiteSpace = True
Reader.HasFieldsEnclosedInQuotes = True
While Not Reader.EndOfData
Try
Dim st2 As New List(Of String)
st2.addrange(Reader.ReadFields())
If iCount > 0 Then ' ignore first row = field names
Dim p As New Person
p.CSVLine = st2
p.FirstName = st2(1).Trim
If st2.Count > 2 Then
p.MiddleName = st2(2).Trim
Else
p.MiddleName = ""
End If
p.LastNameSuffix = st2(0).Trim
If st2.Count >= 5 Then
p.TestCase = st2(5).Trim
End If
If st2(3) > "" Then
p.AccountNumbersFromCase.Add(st2(3))
End If
While p.CSVLine.Count < 15
p.CSVLine.Add("")
End While
cases.Add(p)
End If
Catch ex As Microsoft.VisualBasic.FileIO.MalformedLineException
MsgBox("Line " & ex.Message & " is not valid and will be skipped.")
End Try
iCount += 1
End While
End Using
this to close the streams properly:
using(var sw = new StreamWriter(path3))
using(var sr = new StreamReader(path2))
{
string[] lines = File.ReadAllLines(path);
foreach (string line in lines)
{
string user = sr.ReadLine();
if (line != user)
{
sw.WriteLine(line);
}
}
}
for help on the real logic of removal or compare, answer the comment of El Ronnoco above...
You need to close the streams or utilize using clause
sw.Close();
using(StreamWriter sw = new StreamWriter(#"c:\test3.txt"))
You can use LINQ...
class Program
{
static void Main(string[] args)
{
var fullList = "TextFile1.txt".ReadAsLines();
var removeThese = "TextFile2.txt".ReadAsLines();
//Change this line if you need to change the filter results.
//Note: this assume you are wanting to remove results from the first
// list when the entire record matches. If you want to match on
// only part of the list you will need to split/parse the records
// and then filter your results.
var cleanedList = fullList.Except(removeThese);
cleanedList.WriteAsLinesTo("result.txt");
}
}
public static class Tools
{
public static IEnumerable<string> ReadAsLines(this string filename)
{
using (var reader = new StreamReader(filename))
while (!reader.EndOfStream)
yield return reader.ReadLine();
}
public static void WriteAsLinesTo(this IEnumerable<string> lines, string filename)
{
using (var writer = new StreamWriter(filename) { AutoFlush = true, })
foreach (var line in lines)
writer.WriteLine(line);
}
}
using(var sw = new StreamWriter(path3))
using(var sr = new StreamReader(path))
{
string []arrRemove = File.ReadAllLines(path2);
HashSet<string> listRemove = new HashSet<string>(arrRemove.Count);
foreach(string s in arrRemove)
{
string []sa = s.Split(',');
if( sa.Count < 2 ) continue;
listRemove.Add(sa[1].toUpperCase());
}
string line = sr.ReadLine();
while( line != null )
{
string []sa = line.Split(',');
if( sa.Count < 2 )
sw.WriteLine(line);
else if( !listRemove.contains(sa[1].toUpperCase()) )
sw.WriteLine(line);
line = sr.ReadLine();
}
}

How to skip first line and start reading file from second line in C#

How to start reading file from 2nd line skipping 1st line. This seems to work but is it best way to do so?
using (StreamReader sr = new StreamReader(varFile, Encoding.GetEncoding(1250))) {
string[] stringSeparator = new string[] { "\",\"" };
int i = 0;
while (!sr.EndOfStream) {
string line = sr.ReadLine(); //.Trim('"');
if (i > 0) {
string[] values = line.Split(stringSeparator, StringSplitOptions.None);
for (int index = 0; index < values.Length; index++) {
MessageBox.Show(values[index].Trim('"'));
}
}
i++;
}
}
If the file is not very large and can fit in memory:
foreach (var line in File.ReadAllLines(varFile, Encoding.GetEncoding(1250)).Skip(1))
{
string[] values = line.Split(',');
...
}
If not write an iterator:
public IEnumerable<string> ReadAllLines(string filename, Encoding encoding)
{
using (var reader = new StreamReader(filename, encoding))
{
string line;
while ((line = reader.ReadLine()) != null)
{
yield return line;
}
}
}
and then consume it:
foreach (var line in ReadAllLines(varFile, Encoding.GetEncoding(1250)).Skip(1))
{
string[] values = line.Split(',');
...
}
Could you not just read the first line outside of the loop without assigning it to a variable?
using (StreamReader sr = new StreamReader(varFile, Encoding.GetEncoding(1250))) {
string[] stringSeparator = new string[] { "\",\"" };
if (!sr.EndOfStream)
sr.ReadLine();
while (!sr.EndOfStream) {
string line = sr.ReadLine(); //.Trim('"');
string[] values = line.Split(stringSeparator, StringSplitOptions.None);
for (int index = 0; index < values.Length; index++) {
MessageBox.Show(values[index].Trim('"'));
}
}
}
I'm sorry but I see no problem with the way you are doing it though. I couldn't add comment.
So just for the sake of answering, you probably could have try to call ReadLine() once before the loop. Might not be the best way as I don't know whats the behavior of running ReadLine() if its already end of stream, but it nothing is gonna happen then thats gonna save you some checks.
Updated:
To give a more complete answer, calling ReadLine() when the stream is at its end will return a null.
Reference: http://msdn.microsoft.com/en-us/library/system.io.streamreader.readline.aspx
Remember to check the return for null value.

Categories