Reading x,y values from a .txt file in c# - c#

I'm trying to read x and y values from a text file into a string array where the line is being split on the ','
However, when I run this code I get an error saying the index was out of the bounds of the array on the first element. I've tried using temporary strings to store the data and then convert them but I still get the same error on the second element. here is my code I have implemented without the temporary strings.
string line;
while ((line = coordStream.ReadLine()) != null)
{
string[] temp = new string[2];
temp[0] = "";
temp[1] = "";
temp = line.Split(',');
trees[count].X = Convert.ToInt16(temp[0]);
trees[count].Y = Convert.ToInt16(temp[1]);
count++;
}
Here is the code with the temporary storage too:
string line;
while ((line = coordStream.ReadLine()) != null)
{
string[] temp = new string[2];
temp[0] = "";
temp[1] = "";
temp = line.Split(',');
string xCoord = temp[0];
string yCoord = temp[1];
trees[count].X = Convert.ToInt16(xCoord);
trees[count].Y = Convert.ToInt16(yCoord);
count++;
}
I know this seems a trivial error but I cannot seem to get this working. If I debug and step through the array manually it works but when I don't step through it(i.e let the program run) these errors are thrown
EDIT: The first 10 lines of data are as follows:
654,603
640,583
587,672
627,677
613,711
612,717
584,715
573,662
568,662
564,687
There are no empty lines in the text file.
As pointed out by Jon Skeet, removing the temp assignments seems to have fixed this error. However even with the assignments it should still have worked. The following code sample inside the while loop works:
string[] temp;
temp = line.Split(',');
trees[count].X = Convert.ToInt16(temp[0]);
trees[count].Y = Convert.ToInt16(temp[1]);
count++;
The number of trees is known but I'd like to thank everyone for their input. Expect more questions in the near future :D

Try using a List<Point> for your trees collection instead of an array. This will help if you don't know the correct count upfront.
var trees = new List<Point>();
while (...)
{
...
trees.Add(new Point(x, y));
}
The second possible issue is when the input line does not contain valid data (for example, is empty). Often the last line with data ends with a newline thus the last line is empty.
while ((line = coordStream.ReadLine()) != null)
{
var temp = line.Split(',');
if (temp.Length != 2)
continue;
....
}

var lineContents = File.ReadAllLines("").Select(line => line.Split(',')).Where(x => x.Count() == 2);
var allTrees = lineContents.Select(x => new Trees() { X = Convert.ToInt16(x[0]), Y = Convert.ToInt16(x[1]) });

Related

Multiple runtime exceptions when using string array in C# for unknown reason

I am writing a lexer, or tokenizer, for a programming language. One of the main functions is to split the line of source code into "tokens". I am achieving this by splitting on spaces to create string arrays. Therefore, when I want to preserve strings, I must temporarily change the contents to a keyword while the line is split, and then put the strings back in afterwards. This worked until I developed the variable system for the language, and I had to be able to preserve multiple strings. Then all exception hell broke loose.
Exceptions:
NullReferenceException (line 12) subStringArg[ini] = quotes[1];
IndexOutOfRangeException (line 34) value = value.Replace("STRING", subStringArg[ini]);
Minimum reproducible example:
public static string[] LexLine(string line)
{
string[] subStringArg = null;
string[] quotes = null;
string[] tokens = null;
int ini = 0; // Random name
while (line.Contains('\"'))
{
if (line.Contains('\"'))
{
quotes = line.Split('\"');
subStringArg[ini] = quotes[1];
}
if (subStringArg != null)
{
line = line.Replace(quotes[1], "STRING");
line = line.Replace("\\", "");
line = line.Replace("\"", "");
}
ini++;
}
tokens = line.Split(' ');
if (tokens[0] == "Output" && tokens[1] != "STRING")
{
tokens[1] = IO.OutputVariable(tokens[1]);
}
ini = 0;
foreach (string i in tokens)
{
if (i == "STRING" && subStringArg != null)
{
string value = i;
value = value.Replace("STRING", subStringArg[ini]);
tokens[currentArrayEntry] = value;
}
currentArrayEntry++;
ini++;
}
return tokens;
}
Source code (from my lang):
Output "Defining variables..." to Console. // Exception thrown here
New string of name "sampleStringVar" with value "sample".
Output "enter your name:" to Console.
Get input.
Output sampleStringVar to Console.
I'm asking here because I am clueless as what to do. I should not be getting a NullReferenceException from assigning values.
You set the following
string[] subStringArg = null;
then later you do this
subStringArg[ini] = quotes[1];
But you have not initialised subStringArg so it is still null, so you can't assign anything to it and you will get a NullReferenceError
You must first initialise your array before you can assign anything into it.
Also, you should not assume that you have a value in quotes[1] without first checking it. This will lead to a IndexOutOfRangeException
As another point. The first If statement inside your while loop checks for the same condition as the while loop, so it will always be true!
So the following would be better
string[] subStringArg = new String[enterKnownLengthHere_OrUseALIst];
...
while (line.Contains('\"'))
{
quotes = line.Split('\"');
if(quotes != null && quotes.Length >= 2)
subStringArg[ini] = quotes[1];
else
//Error handling here!
if (subStringArg.Length >= 1)
{
line = line.Replace(quotes[1], "STRING");
line = line.Replace("\\", "");
line = line.Replace("\"", "");
}
ini++;
}

Converting a list of "word,word\n" in a txt file to an array [,] - getting error

I have a list of postal codes and the cities the codes are for in a text file. The data looks like this:
2450,København SV
2500,Valby
2600,Glostrup
2605,Brøndby
2610,Rødovre
2625,Vallensbæk
2630,Taastrup
2635,Ishøj
2640,Hedehusene
There are 580 lines of text there.
I started by converting the text to jagged array[][] but that's not really meeting my needs farther along in my code. So a simple array[,] is preferable.
Unfortunately I'm apparently too new in c# to be able to get there myself.
string testing = File.ReadAllText(#"U:\Testing.txt");
int i = 0, j = 0;
string[,] result = new string[580, 2];
foreach (var row in testing.Split('\n'))
{
j = 0;
foreach (var col in row.Trim().Split(','))
{
result[i, j] = col.Trim();
j++; //Line 26 - this is where I get the exception error
}
i++;
}
I can't figure out why I'm getting the following error and I've begun tearing out my hair. Any ideas??
System.IndexOutOfRangeException
HResult=0x80131508
Message=Index was outside the bounds of the array.
Source=Testing
StackTrace:
at Testing.Analysis.Main() in U:\Uddannelse\Testing\Testing\Program.cs:line 26
You are getting the error because somewhere in your file, some rows have a comma in the city name.
If you want to get the whole name, try something like this -
var row = "2450,København, SV"
var values = row.Split(new[] {','}, 2);
//With the extra int param to the Split function, you are saying no matter how many substrings you can form , only give me this specific number of substrings.
//With a value of 2, you are essentially splitting at the first instance of the comma.
This will give you two values, the first being "2450" and the second "København, SV"
This is assuming that every row has atleast a comma, if not, you'll need to put in a check for it as well.
You can try this that corrects the indexing.
static void Test()
{
var testing = File.ReadAllLines(#"c:\Testing.txt");
string[,] result = new string[testing.Length, 2];
int i = 0, j = 0;
foreach ( var line in testing )
{
j = 0;
foreach ( var col in line.Trim().Split(',') )
result[i, j++] = col.Trim();
i++;
}
for ( int index = result.GetLowerBound(0); index < result.GetUpperBound(0); index++ )
Console.WriteLine($"Code = {result[index, 0]}, Name = {result[index,1]}");
}
Here is one way you can approach this:
string file_path = "...";
//read all lines from the file
var lines = File.ReadAllLines(file_path);
//You could also use StreamReader to read the file in line by line
string[,] result = new string[lines.Length, 2];
string line;
char[] separator = new char[] { ',' };
//loop over the lines until the end of the file
for(int current_line = 0; current_line < lines.Length; current_line++)
{
//second argument limits you to two parts, so additional commas will not cause issues
var parts = line.Trim().Split(separator, 2);
//make sure the data was in your expected format (i.e. two parts)
if(parts.Length == 2)
{
result[current_line, 0] = parts[0];
result[current_line, 1] = parts[1];
}
}

C# Check EOF in text file to fix array

I have a code to read text file and save the data into a double array to plot graph:
string filename = openFileDialog1.FileName;
var lineCount = 0;
using (var reader = File.OpenText(#filename))
{
string line;
while ((line = reader.ReadLine()) != null)
{
var data = line.Split(',');
GlobalDataClass.dDataArray[lineCount, 0] = double.Parse(data[0]);
GlobalDataClass.dDataArray[lineCount, 1] = double.Parse(data[1]);
lineCount++;
}
ShowGraphData(lineCount);
}
And I have created a public class that initiate the array to [2000,2]:
static class GlobalDataClass
{
public static double[,] dDataArray = new double[2000, 2];
public static long iTotalReadingPoint;
}
My text file will be like:
0,29
1,31
2,32
3,32
4,30
However I want my program to detect the EOF so that the text file can contain random rows and still able to plot the graph not restricted to 2000 rows. Is it possible?please advice.TQ
If you want to use same class then try given code. This is not most optimum memory usage wise but still this should work.
string filename = openFileDialog1.FileName;
var lineCount = 0;
while ((line = reader.ReadLine()) != null)
{
if (GlobalDataClass.dDataArray.GetLength(0) == lineCount)
{
double[,] newTemp = GlobalDataClass.dDataArray;
int increaseLenght = newTemp.Length + 1000;
GlobalDataClass.dDataArray = new double[increaseLenght, 2];
Array.Copy(newTemp, GlobalDataClass.dDataArray, newTemp.LongLength);
}
var data = line.Split(',');
GlobalDataClass.dDataArray[lineCount, 0] = double.Parse(data[0]);
GlobalDataClass.dDataArray[lineCount, 1] = double.Parse(data[1]);
lineCount++;
}
The StreamReader class has a boolean property named EndOfStream that is essentially EoF for FileStream objects, and there's the Peek() method which is usually the standard way of reading until EoF.
var reader = File.OpenText( ... );
while( reader.Peek() != -1 ) //Peek() returns -1 on EoF or if the stream is not seekable.
{
var line = reader.ReadLine();
...
}
However reading from the file isn't really the problem if you don't want to be restricted to 2,000 lines. You might consider using a generic container of some flavour. For example:
using System.Collections.Generic;
string line = "12,34";
var dDataList = new List<KeyValuePair<double, double>>();
string[] parts = line.Split( ',' );
dDataList.Add( new KeyValuePair<double, double>( Double.Parse( parts[0] ), Double.Parse( parts[1] ) ) );
...
foreach( var pair in dDataList )
Console.WriteLine( "{0} => {1}", pair.Key, pair.Value ); // 12 => 34
Will let you add as many pairs of doubles as you want, within reason, without having to fiddle with array resizing/copying or any of that nasty business. It's generally considered good practice to use a container like List<T> when dealing with an unknown amount of data, and to use arrays when you know exactly how much data you're going to have or the absolute maximum amount of data you can have.
I think you're asking your question a bit wrong; The problem you have is that you are declaring an array of 2000 unit fixed length, but you actually want it to be dynamic length. As Abhinav said, a list may work for you:
firstly, you might consider creating a class/struct for your coordinates:
public class Coordinate
{
public double x;
public double y;
}
Then, create a list of coordinates (of 0 length initially)...
static class GlobalDataClass
{
public static List<Coordinate> dDataArray = new List<Coordinate>();
public static long iTotalReadingPoint;
}
And then add Coordinate objects to your list as you find new lines..
string filename = openFileDialog1.FileName;
var lineCount = 0;
using (var reader = File.OpenText(#filename))
{
string line;
while ((line = reader.ReadLine()) != null)
{
var data = line.Split(',');
Coordinate coord = new Coordinate();
coord.x = double.Parse(data[0]);
coord.y = double.Parse(data[1]);
GlobalDataClass.dDataArray.Add(coord);
lineCount++;
}
ShowGraphData(lineCount);
}

How to edit specific lines in a text document? [duplicate]

This question already has answers here:
Edit a specific Line of a Text File in C#
(6 answers)
Closed 8 years ago.
Could anyone tell me how to edit a specific line in a text document?
For instance, lets say that my document contains two phone numbers:
"0889367882
0887343160"
I want to delete the second number and write a new phone number, how can I do that?
I am printing the text in the document, but i don't know how to choose which line to edit
and how to do that.
string path = #"C:\Users\...\text1.txt";
string[] lines = File.ReadAllLines(path);
int i = 0;
foreach (var line in lines)
{
i++;
Console.WriteLine("{0}. {1}", i, line);
}
Thanks!
Simply use string.replace.
Like this:
if(line.Contains("0887343160")
line = line.Replace("0887343160", "0889367882");
and after replacing, write all lines back in the file.
A better version would be to iterate the lines in the file rather than loading the whole file lines to memory. Hence using an iterator would do best here.
We do a MoveNext() on the iterator object and write the current line pointed by the iterator to the file after executing the necessary replace logic.
StreamWriter wtr = new StreamWriter("out.txt");
var e = File.ReadLines(path).GetEnumerator();
int lineno = 12; //arbitrary
int counter = 0;
string line = string.Empty;
while(e.MoveNext())
{
counter++;
if(counter == lineno)
line = replaceLogic(e.Current);
else
line = e.Current;
wtr.WriteLine(line);
}
wtr.Close();
Solution 1: if you want to remove the Line based on user input String (matches with one of the line from file) you can try this.
string path = #"C:\Data.txt";
string[] lines = File.ReadAllLines(path);
String strRemove = "8971820518";
List<String> lst = new List<String>();
for(int i=0;i<lines.Length;i++)
{
if (!lines[i].Equals(strRemove)) //if string is part of line use Contains()
{
lst.Add(lines[i]);
}
}
File.WriteAllLines(path,lst.ToArray());
Solution 2: if you want to remove the Line based on user input LineNO (matched with exact line no in file) you can try this
string path = #"C:\Data.txt";
string[] lines = File.ReadAllLines(path);
int iRemoveLineNo = 6;
List<String> lst = new List<String>();
for(int i=0;i<lines.Length;i++)
{
if (iRemoveLineNo-1!=i)
{
lst.Add(lines[i]);
}
}
File.WriteAllLines(path,lst.ToArray());

How to edit and replace a group of lines of a text file using c#?

I have a large text file(20MB), and I'm trying to change every 4th & 5th line to 0,0
I've tried with the following code but I will be interested to know if theres any better way of doing it..
EDIT:
Power = new List<float>();
Time = new List<float>();
string line;
float _i =0.0f;
float _q =0.0f;
int counter = 0;
StreamReader file = new StreamReader(iqFile2Open);
while ((line = file.ReadLine()) != null)
{
if (Regex.Matches(line, #"[a-zA-Z]").Count == 0)
{
string[] IQ = line.Split(',');
if (IQ.Length == 2)
{
_i = float.Parse(IQ[0]);
_q = float.Parse(IQ[1]);
double _p = 10 * (Math.Log10((_i * _i) + (_q * _q)));
if((counter%4)==0 || (counter%5)==0)
sw.WriteLine("0,0");
else
sw.WriteLine(string.Format("{0},{1}", _i, _q));
counter++;
}
}
}
Thanks in advance.!
You can read in all of the lines, map each line to what it should be based on it's position, and then write them all out:
var lines = File.ReadLines(inputFile)
.Select((line, i) => ComputeLine(line, i + 1));
File.WriteAllLines(outputFile, lines);
As for the actual mapping, you can mod the line number by 5 to get an "every 5th item" result, and then just compare the result to the two mod values you care about. Note that since you don't want the first item wiped out it's important that the index is 1-indexed, not zero indexed.
private static string ComputeLine(string line, int i)
{
if (i % 5 == 4 || i % 5 == 0)
return "0,0";
else
return line;
}
This streams through each line in the file, rather than loading the entire file into memory. Because of this it's important that the input and output files be different. You can copy the output file to the input file if needed, or you could instead use ReadAllLines to bring the entire file into memory (assuming the file stays suitably small) thus allowing you to write to the same file you read from.
What exactly are you trying to replace? Are you replacing by specific LINE or specific TEXT?
If you are looking to replace specific text you can easily do a string.Replace() method...
StreamReader fileIn = new StreamReader("somefile");
string fileText = fileIn.Readlines();
fileText = fileText.Replace("old", "new");
//Repeat last line for all old strings.
//write file...

Categories

Resources