I have some problems with StreamReader. Firstly, below, is my simple code:
using (StreamReader reader = new StreamReader("Content/Levels/" + mapName + ".txt"))
{
for (int i = 0; i < 20; i++)
for (int j = 0; j < 36; j++)
{
string[] objLoc = reader.ReadLine().Split(',');
map[i, j] = Convert.ToInt32(objLoc[j]);
}
}
So, I have a text file which has rows and columns, just like an array. Each position holds an integer. Those integers are delimited by , chars.
I want to read each character from the position within the text file, and then convert it to an actual integer and add it to a separate array. I'll read from that array to build the map after the code I've shown you.
Being new to C# and programming, I assume that my code actually reads every position from a line using that Split method, and then I use the read char to insert it in the map array.
Am I doing it right? At the moment, I'm getting an exception:
NullReferenceException was unhandled: Object reference not set to an instance of an object.
I've read the documentation from MS also. Stumbled upon numerous similar problems, but none fixed my issue.
Any help would be highly appreciated!
You are reading a whole new line in your inner loop, which means you run out of lines fast. You need to read a new line in the outer loop, and loop throught the result of the split (the inidividual elements) in the inner loop
Try something like
using (StreamReader reader = new StreamReader("Content/Levels/" + mapName + ".txt"))
{
for (int i = 0; i < 20; i++) {
string[] objLoc = reader.ReadLine().Split(',')
for (int j = 0; j < 36; j++) {
map[i, j] = Convert.ToInt32(objLoc[j]);
}
}
}
Note: you will need to check for errors in case the line does not contain enough elements or the file is too short. The conversion to int might fail as well
Related
I've made a neural network and now I need to save the results of the training process into a local file. In total, there are 7,155,264 values. I've tried with a loop like this
string weightsString = "";
string biasesString = "";
for (int l = 1; l < layers.Length; l++)
{
for (int j = 0; j < layers[l].Length; j++)
{
for (int k = 0; k < layers[l - 1].Length; k++)
{
weightsString += weights[l][j, k] + "\n";
}
biasesString += biases[l][j] + "\n";
}
}
File.WriteAllText(#"path", weightsString + "\n" + biasesString);
But it literally takes forever to go through all of the values. Is there no way to write the contents directly without having to write them in a string first?
(Weights is a double[][,] while biases is a double[][])
First of writing down 7 million datasets will obviously take a lot of time.
I'd suggest you split up weights and biases into two files and write them on the fly, no need to store them all in memory until you are done.
using StreamWriter weigthStream = new("weigths.txt", append: true);
using StreamWriter biasStream = new("biases.txt", append: true);
for (int l = 1; l < layers.Length; l++)
{
for (int j = 0; j < layers[l].Length; j++)
{
for (int k = 0; k < layers[l - 1].Length; k++)
{
await weightStream.WriteLineAsync(weights[l][j, k]);
}
await biasStream.WriteLineAsync(biases[l][j]);
}
}
But it literally takes forever to go through all of the values. Is there no way to write the contents directly without having to write them in a string first?
One option would be to save it as binary data. This makes it much harder to read by humans, but for large amount of data this would really be preferable since it will save a lot of time both when reading and writing. For example using BinaryWriter and using unsafe code.
myBinaryWriter.Write(myArray.GetLength(0));
myBinaryWriter.Write(myArray.GetLength(1));
fixed (double* ptr = myArray)
{
var span = new ReadOnlySpan<byte>(ptr, myArray.GetLength(0) *myArray.GetLength(1) * 8);
myBinaryWriter.Write(span);
}
You might also consider using a binary serialization library like protbuf.net that can just take a object an and serialize it to a stream. Note that some libraries may need attributes to be added to classes and properties. Some libraries may also have issues with multidimensional and/or jagged arrays. Because of this it can sometimes be useful to define your own 2D array that uses a 1D array as the backing storage, this can make things like serialization or passing data to other components much simpler.
Another somewhat common practice is to store metadata, like height, width, etc in a simple human readable text-file using something like json or xml. While keeping the actual data in a separate raw binary file.
Bad variant - you can use json serialization
So-so variant - write in file immediately. Use File.AppendText
IMHO the best variant - use DB
IMHO good variant - use BinaryFormatter (you will not be able to read that by yourself, but application will)
Working variant - use StringBuilder
StringBuilder weightsSB = new StringBuilder();
StringBuilder biasesSB = new StringBuilder();
for (int l = 1; l < layers.Length; l++)
{
for (int j = 0; j < layers[l].Length; j++)
{
for (int k = 0; k < layers[l - 1].Length; k++)
{
weightsSB.Append(weights[l][j, k] + "\n");
}
biasesSB.Append(biases[l][j] + "\n");
}
}
As suggested in the comments, I used a StringBuilder instead. Works like a charm.
I am trying to create a code in C# to read some numbers in a file and add them to a matrix, so I can work with them.
This is some of the content of the file:
ID X Y Z U Eps 100 V Eps 100 W Eps 100
1204 101.25 0 0 0 0 0
1205 101.25 0.0321000840330112 4.473425 0.00200077306900823 -0.00292669254354999 -0.00514929334513621
1206 101.25 0.0642001680660224 8.94685 0.0065549384905434 -
So, I basically use StreamReader ReadLine to get the lines in the file, and then for each line I split it and store in the matrix, this is the code:
// Get the path of the file
string path = dlg.FileName;
tb.Text = path;
// Get the lenght of the file
string[] allFile = File.ReadAllLines(path);
int lenght = allFile.Length;
MessageBox.Show(File.ReadAllText(path));
// Initialize reading
StreamReader sr = new StreamReader(path);
string line = sr.ReadLine(); // Read first line, discarted
line = sr.ReadLine();
// Array of numbers in a line
string[] bits = line.Split();
// Matrix containing all the points
float[,] points = new float[lenght, 7];
for (int i = 0; i < lenght; i++)
{
for (int j = 0; j < 7; j++)
{
points[i, j] = float.Parse(bits[j]);
}
line = sr.ReadLine();
bits = line.Split();
}
So, this code wasn't working, and after some tests I have realized that the sr.ReadLine inside the for loops is returning an empty string, so the next line catches an exception.
I have seen similar questions here, but none of them helped me figure out what is wrong with my code specifically, so if you guys have any help, it would be much appreciated.
So I want to recreate this process with a for loop. What's the simplest way of doing this. I can do 1 to 10 but let's say you have 3 as your start value I can't get the first line to start with 3 symbols.
Thanks in advance.
Since you haven't shared any code, I'll give you an idea as to how you can print the values. I've used 2 for loops to print the value. Although there maybe better and shorter algorithms to do the same
Just edit my code below to suit your needs.
public static void Main()
{
var start = 3; //StartTextBox.Text
var end = 10; //EndTextBox.Text
var symbol = "#"; //SymbolTextBox.Text
for (var i = start; i < end; i++)
{
var toPrint = string.Empty;
for (var j = 0; j < i; j++) toPrint += symbol;
Console.WriteLine(toPrint); //LabelX.Text = toPrint;
}
Console.ReadLine();
}
You can see in the above code that if you change the value of start to any number, the value gets printed properly.
Another option assuming some of your object names...
for (int i = int.Parse(txtStart.Text); i <= int.Parse(txtEnd.Text); i++)
{
lblOutput.Text += new String(txtSymbol.Text.ToCharArray()[0], i) + Environment.NewLine;
}
I am trying to print a jagged array with a some kind of 'constant row spacing' to make it more clear to read. Here's default output which I receive :
And I wish to receive something similar to this :
Here is my array printing code :
for (int i = 0; i < level; i++)
{
for (int j = 0; j < level; j++)
Console.Write(string.Format("{0} ", matrix[i][j].ToString("0.00")));
Console.Write(Environment.NewLine + Environment.NewLine);
}
Any quick and simple way to reach this?
Here's an example for padding with width of 5 to the left
string.Format("{0:-5}", matrix[i][j].ToString("0.00"))
You can see here more options how you can pad with spaces
I'm doing my homework. I am assigned to create a Tic Tac Toe application, I've finished it but there's a small error, and I think I'm overlooking something, but I can't figure it out and need some new eyes to check it out because I think I'm looking at it for too long and missing a big concept.
Random r = new Random();//Creates the number generator.
int [][] numbers = new int [3][3]; //creates a 3x3 integer grid.
for (int i = 0; i< numbers.Length; i++){
for (int j=0;j<numbers[i].Length;j++){
numbers[i][j] = r.Next(2);//Traverses the array and inputs a number between 0 and 1 here.
}
}
Console.WriteLine("%d|%d|%d\n",numbers[0][0],numbers[0][1],numbers[0][2]);
Console.WriteLine("------");
Console.WriteLine("%d|%d|%d\n",numbers[1][0],numbers[1][1],numbers[1][2]);
Console.WriteLine("------");
Console.WriteLine("%d|%d|%d\n",numbers[2][0],numbers[2][1],numbers[2][2]);
The error is in the second line. Maybe I did the int [][] numbers = new int [][]; format wrong? Please help me identify what's wrong it. Thank you.
Try this when declaring your array:
int [,] numbers = new int[3,3];
You need to change your accesses to the array also fx:
numbers[i,j] = r.Next(2);
To iterate the array you can use numbers.GetLength(index) method instead of numbers.Length and numbers[i].Length.
In your case it would be something like this:
for (int i = 0; i < numbers.GetLength(0); i++)
{
for (int j = 0; j < numbers.GetLength(1); j++)
{
...
EDIT: If you really want to stay with your array of arrays (also called jagged arrays) you can initialize it like this:
int[][] numbers = new int[3][]
{
new int[3],
new int[3],
new int[3]
};