Streamreading text files - c#

I have a piece of code that is supposed to streamread this text file:
1.1.1.1.1.1.1.1.1.1.1.1.1.1.1
1.1.1.2.2.2.2.1.1.1.2.2.1.1.1
1.2.2.2.2.2.2.2.2.2.2.2.2.1.1
1.1.2.2.2.2.2.2.2.2.2.2.2.1.1
1.1.2.2.2.2.2.2.2.2.2.2.1.1.1
1.1.1.1.2.2.2.2.2.2.2.2.1.1.1
1.1.1.1.2.2.2.2.2.2.1.1.1.1.1
1.1.1.1.1.1.2.2.2.1.1.1.1.1.1
1.1.1.1.1.1.1.2.1.1.1.1.1.1.1
1.1.1.1.1.1.1.1.1.1.1.1.1.1.1
1.1.1.1.1.1.1.1.1.1.2.2.1.1.1
1.1.1.1.1.1.1.1.1.1.1.1.1.1.1
Everything is going fine, kinda of. My purpose was to rummage through all the characters one by one, then after that's done start on a new line. This is where my little problem occurs, which I've been trying to fix all night.
It reads the first line nicely, but then it doesn't read the second line...
Here is the code:
System.IO.StreamReader file = new System.IO.StreamReader(#"C:\Text\TextFile.txt");
int loadX = 0;
int loadY = 0;
string line;
while (true)
{
if (loadX <= 12)
{
loadX++;
while ((line = file.ReadLine()) != null)
{
System.Threading.Thread.Sleep(500);
string[] entries = line.Split('.');
System.Console.Write(entries[loadX]);
loadY++;
}
}
System.Threading.Thread.Sleep(500);
Console.Write($" Finished {loadX}");
loadX = 0;
}

var lines = File.ReadAllLines(#"C:\Text\TextFile.txt");
var points = lines.SelectMany((l, x) => l.Split('.').Select((s, y) => new {X = x, Y = y, Value = s}));
foreach (var point in points)
{
Console.WriteLine($"({point.X}, {point.Y})={point.Value}");
}

Using a while loop and StremReader seems so silly when you have easier and more readable ways of handling this.
You can easily simplify your code by doing File.ReadAllLines()
//lines will be a string array
var lines = File.ReadAllLines(#"C:\Text\TextFile.txt");
for(int x = 0; x < lines .Length; x++)
{
var cols = lines [x].Split('.');
for(int y = 0; y < cols.Length; x++)
{
//Here you have access to the value, and the x and y position
Console.WriteLine("x: {0}, y: {1} value: {2}", x, y, cols[y]);
}
}
Demo here

If you want to go through every number in this file with X and Y then this is an example how you can do so:
string[] lines = File.ReadAllLines(#"C:\Text\TextFile.txt");
for(int indexY = 0; indexY < lines.Length; indexY++){
string[] lineEntries = lines[indexY].Split('.');
for(int indexX = 0; indexX < lineEntries; indexX++){
// here you have one number by accessing
// it with lineEntries[indexX]
Console.Write(lineEntries[indexX]);
}
Console.WriteLine();
}

You are mistaken to think it is reading the first line. In fact, your current code reads the first value of each line. Due to your input this just happens to be a similar output to what the first line would be, which has lead to your confusion.
Your main loop should be looping through each line, then you can process the line and loop through each value. Which you can then use however you want.
Here is an example:
using(System.IO.StreamReader file = new System.IO.StreamReader(#"C:\Text\TextFile.txt"))
{
int loadX = 0;
int loadY = 0;
string line;
// Loop through each line as you read it.
while ((line = file.ReadLine()) != null)
{
// Split the line to get an array of values.
string[] entries = line.Split('.');
// Loop through each value and process.
for(int i = 0; i < entries.length; i++)
{
string entry = entries[i];
// TODO: Do something with entry.
loadY++;
}
loadX++;
}
}
Obviously in this example loadX and loadY are not being used, but this demonstrates how to correctly increment them so you can use them as needed.
TIP: When using a SteamReader you should ensure you dispose of it correctly, this is best done by including it in a using block.

Related

C# store file lines into array, then save chosen lines

I am trying to make code, that will basically open desired file, store all lines into array, and then, if line does fulfill condition, line will be save into new text file. When running program, I get error message to line reader, that index is outside of array. Please help, I am new to C#
int NumLines = new StreamReader(OpenFile.FileName).ReadToEnd().Split(new char[] { '\n' }).Length;
StreamReader Data = new StreamReader(OpenFile.FileName);
string[] arr = new string[NumLines];
for (int i = 0; i <= NumLines; i++)
{
StreamWriter File = new StreamWriter("C://Users//Tomas//Desktop//BC//tmp//Data.txt");
arr[i] = Data.ReadLine();
Index should be less than array size:
for (int i = 0; i < NumLines; i++)
^
But you don't need to put lines into array in order to write them to other file. E.g. if you want to write only some lines by condition:
File.WriteAllLines(newFileName, File.ReadLines(OpenFile.FileName).Where(condition));
Where condition is a delegate which checks whether line should be written. E.g. if you want to write only lines which start with "Foo":
.Where(line => line.StartsWith("Foo"))
NOTE: If you want to write all lines to new file without condition, then you simply can copy original file:
File.Copy(OpenFile.FileName, newFileName);
UPDATE: From your comments, it's clear that you need to find line which matches some condition and also write to output 6th and 8th lines after that line. You still can do that without dumping all source file into memory:
private static IEnumerable<string> GetVertexCoordinates(string fileName)
{
var enumerator = File.ReadLines(fileName).GetEnumerator();
while (enumerator.MoveNext())
{
if (enumerator.Current == "VERTEX")
{
yield return enumerator.Current;
for (var i = 0; i < 6; i++) enumerator.MoveNext(); // skip 6 lines
yield return enumerator.Current;
for (var i = 0; i < 2; i++) enumerator.MoveNext(); // skip 2 more lines
yield return enumerator.Current;
}
}
}
And usage is still one-liner
File.WriteAllLines(newFileName, GetVertexCoordinates(OpenFile.FileName));
Try this way:
string[] lines = File.ReadAllLines(filepath);
Then, if you need to compare all lines of this file with some YOUR line, you can do this way:
string targetFilePath = "C://Users//Tomas//Desktop//BC//tmp//Data.txt";
string specificLine = "line, which you try to find";
foreach (var line in lines)
if (line.Equals(specificLine))
File.WriteAllText(targetFilePath, line);
Your code could be shortcutted this way...
/// Disposal of your reader when unused is essential to close your file
using(var reader = new StreamReader(OpenFile.FileName))
{
var lines = reader.ReadToEnd().Split(new char[] { '\n' });
int NumLines = lines.Length;
for (int i = 0; i < NumLines; i++)
{
... do something here
}
}

How to restart StreamReader to start reading from the beginning of a file

So i have to write a program that reads values (numbers) from Values.txt file and store them into array of integers (at the beginning i dont know the number of values in file so i dont know the length of array).
First i loop through the file and use counter variable to get the number of values to store into array. Then comes the problem, i dont know how to start from the beginning of file to catch values and store them into array.
When i run it i get 0 0 0 0 0 as a result.
If instead of
myReader.DiscardBufferedData();
myReader.BaseStream.Seek(0, SeekOrigin.Begin);
myReader.BaseStream.Position = 0;
I use the myReader.Close() and then myReader = new StreamReader("Values.txt), the result is correct, can somebody please explain why this is happening and howcan i fix this code :)
string lineOfText = "";
int counter = 0;
int[] intArray;
StreamReader myReader = new StreamReader("Values.txt");
while(lineOfText != null)
{
lineOfText = myReader.ReadLine();
if(lineOfText != null)
{
counter++;
}
}
intArray = new int[counter];
myReader.DiscardBufferedData();
myReader.BaseStream.Seek(0, SeekOrigin.Begin);
myReader.BaseStream.Position = 0;
counter = 0;
while(lineOfText != null)
{
lineOfText = myReader.ReadLine();
if (lineOfText != null)
{
intArray[counter] = int.Parse(lineOfText);
}
counter++;
}
myReader.Close();
for (int j = 0; j < intArray.Length; j++)
{
Console.WriteLine(intArray[j]);
}
This explains how to reset the stream if you want to do it in one pass Return StreamReader to Beginning.
Are you required to use an array? A list would be perfect for what your doing, you can then later push that list into an array or just work directly from the list. Code example below:
List<string> ints = new List<string>();
using (StreamReader sr = new StreamReader("example.txt"))
{
ints.Add(sr.ReadLine());
}

unable to convert string to int when using streamreader

I am having trouble converting a string to an int. Ive looked around and have been told to use the int.Parse but it isn't helping.
I have created an object Winner that has a int WinnerScore and string WinnerName.
I am trying to add these values to an array Winner[] before sorting them.
When I run this code it says:
NullReferenceException was unhandled
Object reference not set to an instance of an object.
Any idea why this is happening?
StreamReader sr = new StreamReader("highscores.txt");
for (int u = 0; u < nWinners; u++)
{
unsortedList[u].WinnerScore = int.Parse(sr.ReadLine());
unsortedList[u].WinnerName = sr.ReadLine();
}
sr.Close();
With a certain confidence I can suppose that you have declared the array unsortedList but you haven't initialized the objects of Winner class that you want to store in that array.
Simply declaring
Winner[] unsortedList = new Winner[100];
creates an array that could store 100 instances of Winner but this array is empty, there are no instances of a Winner class in the 100 slots available, they are all null. You should create every single Winner instances that you want to store in the 100 slots of the array.
So, as an example, your code could be rewritten as
Winner[] unsortedList = new Winner[nWinners];
using(StreamReader sr = new StreamReader("highscores.txt"))
{
for (int u = 0; u < nWinners; u++)
{
Winner w = new Winner();
w.WinnerScore = int.Parse(sr.ReadLine());
w.WinnerName = sr.ReadLine();
unsortedList[u] = w;
}
sr.Close();
}
However, this has the drawback that you need to know, before entering the loop, the exact number of Winner objects required to dimension your array, If, for some reason, you fail to count them correctly, you fall in another problem (Index Out Of Range).
In this case it is always better to use a List<Winner> where you don't need to know before hand the exact number of elements
List<Winner> unsortedList = new List<Winner>();
using(StreamReader sr = new StreamReader("highscores.txt"))
{
while((line = sr.ReadLine()) != null))
{
Winner w = new Winner();
w.WinnerScore = int.Parse(line);
w.WinnerName = sr.ReadLine();
unsortedList.Add(w);
}
sr.Close();
}
You've left creation as well as initialization:
// My suggestion of unsortedList generic type
public struct Winner {
public int WinnerScore;
public String WinnerName;
}
...
// 1. You shoud create unsortedList:
List<Winner> unsortedList = new List<Winner>();
// 2. You should also initialize the list with Winner instances
for (int u = 0; u < nWinners; ++u)
unsortedList.Add(new Winner());
// 3. Only that you can fill unsortedList from file.
// And you original code becames the correct one
using (StreamReader sr = new StreamReader("highscores.txt")) {
for (int u = 0; u < nWinners; ++u) {
unsortedList[u].WinnerScore = int.Parse(sr.ReadLine());
unsortedList[u].WinnerName = sr.ReadLine();
}
}
var unsortedList = new List<Winner>();
var nWinners = 100;
using (StreamReader sr = new StreamReader("highscores.txt"))
{
for (int i = 0; i < nWinners; i++)
{
var winer = new Winner();
winer.WinnerScore = int.Parse(sr.ReadLine());
winer.WinnerName = sr.ReadLine();
unsortedList.Add(winer);
}
sr.Close();
}

C# Split not working

I'm trying to read data from a file, split the data and save to array. The code works fine except for the split. It is returning a NullException.
Any help would be greatly appreciated.
public static void LoadHandData(CurrentHand[] handData, string fileName)
{
string input = ""; //temporary variable to hold one line of data
string[] cardData; //temporary array to hold data split from input
StreamReader readHand = new StreamReader(fileName);
for (int counter = 0; counter < handData.Length; counter++)
{
input = readHand.ReadLine(); //one record
cardData = input.Split(' '); //split record into fields
int index = 0;
handData[counter].cardSuit = Convert.ToChar(cardData[index++]);
handData[counter].cardValue = Convert.ToInt16(cardData[index++]);
}
readHand.Close();
}
As per the comments, you've only got one line of data. But look at your loop:
for (int counter = 0; counter < handData.Length; counter++)
{
input = readHand.ReadLine(); //one record
cardData = input.Split(' '); //split record into fields
int index = 0;
handData[counter].cardSuit = Convert.ToChar(cardData[index++]);
handData[counter].cardValue = Convert.ToInt16(cardData[index++]);
}
That's trying to read one line per hand. On the second iteration, ReadLine will return null, so when you call input.Split() you'll end up with the NullReferenceException you're seeing.
You need to read the line once and split it. Given that you've only got one line of text, you can just use File.ReadAllText to simplify things:
string input = File.ReadAllText(fileName);
string[] cardData = input.Split(' ');
for (int counter = 0; counter < handData.Length; counter++)
{
handData[counter].cardSuit = Convert.ToChar(cardData[counter * 2]);
handData[counter].cardValue = Convert.ToInt16(cardData[counter * 2 + 1]);
}

Use looped array to take in string inputs

I am looking to find a way to take assign the value of user inputs to the variables I have, but to use a loop to take this entry and position it on the screen. Is there a way to do this?
Below is my non-working code but hopefully it should provide an idea of what I am trying to achieve.
public void StudentDetailInput()
{
const int startpoint = 2;
string[] takeinput = new string[] {FirstName, Surname, MiddleName, StudentId, Subject, AddressLine1, AddressLine2, Town, Postcode, Telephone, Email };
for (int x = 0; x < takeinput.Length; x++)
{
Console.SetCursorPosition(30, startpoint + x);
[x] = Console.ReadLine();
}
}
You might want to use a Dictionary:
private Dictionary<string, string> _answers = new Dictionary<string, string>();
public void StudentDetailInput()
{
string[] takeinput = new string[] {
"FirstName",
"Surname",
"MiddleName",
"StudentId",
"Subject",
"AddressLine1",
"AddressLine2",
"Town",
"Postcode",
"Telephone",
"Email"
};
_answers.Clear();
for (int x = 0; x < takeinput.Length; x++)
{
Console.Write(takeinput[x] + ": ");
var answer = Console.ReadLine();
_answers.Add(takeinput[x], answer);
}
}
So you can display the answers like this:
for(var i = 0; i < _answers.Count; i++)
{
Console.WriteLine("{0}: {1}", _answers.Keys[i], _answers.Values[i]);
}
If your concern is that you do not want to use this many lines on the console you could keep track of the length of the answers and try to put the cursor right behind the answers so far. The problem with this is that you'll need to take the screen's width (which can be adjusted by the user) into account to calculate the correct line and position.
Another issue with this construction will be that users will expect the cursor to go one line down (that is what enter does) so the user experience might suffer.
An alternative would be to clear the screen after each input, display all answers so far starting at line 2 of the console and positioning the next question on line one:
for (int x = 0; x < takeinput.Length; x++)
{
Console.Clear();
for(y = 0; y < x; y++)
{
Console.SetCursorPosition(0, y + 1);
Console.WriteLine("{0}: {1}", _answers.Keys[y], _answers.Values[y]);
}
Console.SetCursorPosition(0, 0);
Console.Write(takeinput[x] + ": ");
var answer = Console.ReadLine();
_answers.Add(takeinput[x], answer);
}
This might go horribly wrong when the number of questions is more than the number of lines on the console.
Your string array definition is not clear, but I think you are looking for something like this:
public void StudentDetailInput()
{
const int startpoint = 2;
string[] takeinput = new string[11];
for (int x = 0; x < takeinput.Length; x++)
{
Console.SetCursorPosition(30, startpoint + x);
takeinput[x] = Console.ReadLine();
}
}
Now
// FirstName = takeinput[0]
// Surname = takeinput[1]
// ...
This line is wrong.
[x] = Console.ReadLine();
If you want to assign to your elements of array, what you read with ReadLine() method, you should use
takeinput[x] = Console.ReadLine();
If you just want to assign the counter what you read, you should use;
x = Convert.Int32(Console.ReadLine());
EDIT: If I understand your question clearly, you just want to this;
List<string> list = new List<string>();
string input = "";
do
{
input = Console.ReadLine();
list.Add(input);
}
while (input != "exit");
list.Remove("exit");
foreach (var item in list)
{
Console.WriteLine(item);
}

Categories