Cant read text file of integers into an integer array - c#

This is driving me literally insane for some reason my code to read a simple text file of ints into an int array wont work.
private void HardButton_Click(object sender, EventArgs e)
{
int[] hard1 = { };
int counter = 0;
using (StreamReader inFile = new StreamReader("h1.txt"))
{
string str = null;
while ((str = inFile.ReadLine()) != null)
{
hard1[counter] = Convert.ToInt32(str);
counter++;
}
}
hard1 is an array of ints that i need to hold each integer placed into it by reading the text file. My error is that my array is out of bounds even though I'm iterating each time through the loop. I am at a loss.
EDIT: Here is the txt file input
0502090
6070203
0502010
5020101
0503010
4020905
0608070
7582391
6478283
8592914
5628191
6573812
4728915
3648271

C#/.Net has real arrays, not the psuedo-array collections you see in so many other languages (it has those, too, it just doesn't try to pass them off as arrays). One attribute of real arrays is a fixed size.
So when you declare the array like this:
int[] hard1 = { };
what you have is an array fixed at size 0, and therefore assigning to the array later on like this:
hard1[counter] = Convert.ToInt32(str);
is assigning to nowhere.
You have many options to fix this. Here is one of them:
private void HardButton_Click(object sender, EventArgs e)
{
var result = File.ReadLines("h1.txt").
Where(line => !string.IsNullOrWhitespace(line)).
Select(line => int.Parse(line)).
ToArray();
}

If you don't know the length in advance... use a list.
private void HardButton_Click(object sender, EventArgs e)
{
var hard1 = new List<int>();
int counter = 0;
using (StreamReader inFile = new StreamReader("h1.txt"))
{
string str = null;
while ((str = inFile.ReadLine()) != null)
{
hard1.Add(Convert.ToInt32(str));
counter++;
}
}
...
If you don't have complete control over the file it might be necessary to do extra controls before converting to int as well.
Is every line exactly one integer?
Do I need to trim?
Can there be empty lines?

Use this:
private void button1_Click(object sender, EventArgs e)
{
int[] hard1 = { };
var lines = File.ReadAllLines("h1.txt");
var lineWithoutEmptySpace = lines.Where(x => !string.IsNullOrEmpty(x)).ToArray();
hard1 = new Int32[lineWithoutEmptySpace.Length];
for (var i = 0; i < lineWithoutEmptySpace.Length; i++)
{
hard1[i] = Convert.ToInt32(lineWithoutEmptySpace[i]);
}
}

Related

C# array available outside function

private void frmExecute_Load(object sender, EventArgs e)
{
string[] data = File.ReadAllLines("c:\\toyotoconsole\\tssetup.txt");
// Loop through each line, split, add if server
for (int i = 0; i < data.Length; i++)
{
var serverValues = data[i].Split('|');
}
}
Okay first C# windows project, which is cool since I have never really touched this beyond the odd debugging foray.
My problem is the array serverValues is built in a function, how do I make this array available for all functions (not sure if using the right term here) in the same form script (probably the wrong word there as well). Is there a public declaration?
Technically, you should turn local variable serverValues into a field (or property):
private string[] serverValues = new string[0];
private void frmExecute_Load(object sender, EventArgs e) {
...
serverValues = data[i].Split('|');
...
}
However, as one can see, you rewrite serverValues within the loop; that's why serverValues will contain the last line splitted only. Another issue is mixing Business logic (ServerValues) and UI (form loading).
It seems you want something like this:
using System.Linq;
...
private string[] m_ServerValues = null;
// Pure buiness logic: ServerValues without any UI (form)
public string[] ServerValues {
get {
// If we have the array we return it
if (m_ServerValues != null)
return m_ServerValues;
// otherwise we compute it
m_ServerValues = File
.ReadLines("c:\\toyotoconsole\\tssetup.txt")
.SelectMany(line => line.Split('|'))
.ToArray();
// And return it
return m_ServerValues;
}
}
// UI: form loading
private void frmExecute_Load(object sender, EventArgs e) {
// If you want to prefetch (it's not necessary)
var values = ServerValues;
}
// Declare a private property in you class
private serverValues = Array.Empty<string>();
And then use within any event
private void frmExecute_Load(object sender, EventArgs e)
{
string[] data = File.ReadAllLines("c:\\toyotoconsole\\tssetup.txt");
// Loop through each line, split, add if server
for (int i = 0; i < data.Length; i++)
{
serverValues = data[i].Split('|');
}
}

generate multiple class objects

I'm trying to generate multiple class objects but I get a "System.ArgumentOutOfRangeException: 'Index was out of range." message at this line: clients[i] = new IRCClient(credentials, textEdit1.Text);
public void FileRead()
{
if (File.Exists(AccountsFile))
{
Account.Clear();
using (StreamReader Reader = new StreamReader(AccountsFile))
{
string line;
while ((line = Reader.ReadLine()) != null)
{
Account.Add(new Accounts { Username = line.Split(':')[0], Password = line.Split(':')[1] });
}
}
}
else
{
File.Create(AccountsFile);
}
}
private void simpleButton1_Click(object sender, EventArgs e)
{
clients = new List<IRCClient>();
int num = 7;
foreach (var acc in Account)
{
for (int i = 0; i < num; i++)
{
credentials = new ConnectionCredentials(acc.Username, acc.Password);
clients[i] = new IRCClient(credentials, textEdit1.Text); //exception thrown
clients.Add(clients[i]);
foreach (var c in clients)
{
c.Connect();
}
}
}
}
List<T> is not the same as T[]. Ie Lists are not the same as arrays and have some different behaviours.
myarray[i] = someValue;
with arrays this will add some value to position i of the array. But remember arrays are initiliased up front
myarray = new object[10];
so as long as i >= 0 and < 10 the above code is fine.
Lists however are different and can (and in your case) are initialised empty. And then they get made bigger as and when needed. Its one of the benefits (but can also be a performance hit)
So when you do this:
clients = new List<IRCClient>();
you are creating an empty list, that has nothing in it so it has no indexes so when you do:
clients[i]
There is nothing at position 'i' so you get that exception.
The correct use would be
clients.Add(new IRCClient(credentials, textEdit1.Text))

Text file to two string arrays in wpf using streamreader

I'm trying to read a text file to two string arrays. Array1 is to be all the odd lines, array2 all the even lines. I then add all the items of array1 to a combobox and when that is selected, or as it gets typed, outputs array2 to a textbox.
So far, I have tried a few methods from here, but the big issue seems to be creating the arrays. I tried to get help here before, but the answers didn't actually answer my question. They must be arrays, not lists (which I tried and worked well). I am really confused by this whole thing and my attempted code is now rubbish:
private void ReadFile(string filePath, string customerPhone, string customerName)
{
string line = string.Empty;
var fileSR = new StreamReader(filePath);
bool number = true;
while((line = fileSR.ReadLine()) != null)
{
if (number)
{
customerPhone(line);
number = false;
}
else
{
customerName(line);
number = true;
}
}
fileSR.Close();
}
I'm losing confidence in this whole process, but I need to find a way to make it work, then I can learn why it does.
You are almost there, just use the List<string>.
private void ReadFile(string filePath, string customerPhone, string customerName)
{
string line = string.Empty;
using (var fileSR = new StreamReader(filePath))
{
bool number = true;
List<string> customerPhone = new List<string>();
List<string> customerName = new List<string>();
while((line = fileSR.ReadLine()) != null)
{
if (number)
{
customerPhone.Add(line);
number = false;
}
else
{
customerName.Add(line);
number = true;
}
}
fileSR.Close();
}
}
If you are interested only in Arrays, you could simply call customerName.ToArray() to convert it to an array.
Linq Solution
Alternatively you could use Linq and do this.
var bothArrays = File.ReadLines("filepath") // Read All lines
.Select((line,index) => new {line, index+1}) // index each line
.GroupBy(x=> x/2) // Convert into two groups
.SelectMany(x=> x.Select(s=>s.line).ToArray()) // Convert it to array
.ToArray();
You should use collections to return data, say IList<String>:
private static void ReadFile(String filePath,
IList<String> oddLines,
IList<String> evenLines) {
oddLines.Clear();
evenLines.Clear();
int index = 1; //TODO: start with 0 or with 1
foreach (String line in File.ReadLines(filePath)) {
if (index % 2 == 0)
evenLines.Add(line);
else
oddLines.Add(line);
index += 1;
}
}
using
List<String> names = new List<String>();
List<String> phones = new List<String>();
ReadFile(#"C:\MyDate.txt", names, phones);
// If you want array representation
String[] myNames = names.ToArray();
String[] myPhones = phones.ToArray();
// Let's print out names
Console.Write(String.Join(Envrironment.NewLine, names));
Please, notice, that using File.ReadLines usually more convenient than StreamReader which should be wrapped in using:
// foreach (String line in File.ReadLines(filePath)) equals to
using (var fileSR = new StreamReader(filePath)) {
while ((line = fileSR.ReadLine()) != null) {
...
}
}
This worked! I have these class level strings:
string cFileName = "customer.txt";
string[] cName = new string[0];
string[] cPhone = new string[0];
And then this in the Window Loaded event, but could be used in it's own method:
private void Window_Loaded_1(object sender, RoutedEventArgs e)
{
//read file on start
int counter = 0;
string line;
StreamReader custSR = new StreamReader(cFileName);
line = custSR.ReadLine();
while (custSR.Peek() != -1)
{
Array.Resize(ref cPhone, cPhone.Length + 1);
cPhone[cPhone.Length - 1] = line;
counter++;
line = custSR.ReadLine();
Array.Resize(ref cName, cName.Length + 1);
cName[cName.Length - 1] = line;
counter++;
line = custSR.ReadLine();
phoneComboBox.Items.Add(cPhone[cPhone.Length - 1]);
}
custSR.Close();
//focus when program starts
phoneComboBox.Focus();
}

Foreach going out of bounds while searching through array c#

The purpose of my program is to take a data txt file and edit it, and/or make additions and subtractions to it.
The text file format is like this:
Name|Address|Phone|# of people coming|isRSVP
The code I have seems to be doing it's job all the way up until I try to click one of the names within a listbox and it needs to search through the multidimensional array to pull information out and place within a set of textboxes where they can be edited. The problem is that the foreach loop I use gives me an out of bounds exception. I tried to do a step into debug to make sure the data is correct in the array and see the process. Everything seems to do correctly but for some reason in the conditional statement person[0]==listbox1.selectedIndex isn't returning true even though both are the same as I seen through the step into process. Any help would be greatly appreciated.
This is my code:
StringBuilder newFile = new StringBuilder();
static string txtList= "guest_list.txt";
static string[] file = File.ReadAllLines(txtList);
static int x = file.Count();
string[,] list = new string[x ,5];
public void loadGuestList()
{
int count2 = 0;
foreach (string line in file)
{
string[] sliced = line.Split('|');
int count = 0;
list[count2, count] = sliced[0];
count++;
list[count2, count] = sliced[1];
count++;
list[count2,count] = sliced[2];
count++;
list[count2,count]= sliced[3];
count++;
list[count2, count] = sliced[4];
count++;
listBox1.Items.Add(list[count2,0]);
count2++;
}
}
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
foreach (string person in list)
{
if ( person[0].ToString()==listBox1.SelectedItem.ToString())
{
addTxt.Text = char.ToString(person[1]);
textPhone.Text = char.ToString(person[2]);
textPeople.Text = char.ToString(person[3]);
if (person[4] == 'n' )
{
}
else
{
chkRSVP.Checked = true;
}
break;
}
}
}
The problem lies in this line:
foreach (string person in list)
The list is defined as being string[,] which when you for each over will do every element, not just the column of data. You really should do something such as:
for(int index = 0; index <= list.GetUpperBound(0); index++)
{
string slice1 = list[index, 0];
string slice2 = list[index, 1];
....
}
or switch to using a Dictionary<string, string[]>().
Try to use a "Person" object and override equals(). Right now you're trying to put your multidimensional array (list[0]) into a string, it'll give you a unwanted result. You should use list[0,0] instead.
In agreement with Adam Gritt, I tested the following code and it seemed to work:
using System;
namespace so_foreach_bounds
{
class MainClass
{
public static void Main (string[] args)
{
//System.Text.StringBuilder newFile = new System.Text.StringBuilder();
string txtList= "guest_list.txt";
string[] file = System.IO.File.ReadAllLines(txtList);
int x = file.Length;
System.Collections.Generic.List<string[]> list = new System.Collections.Generic.List<string[]> ();
foreach (string line in file)
{
string[] sliced = line.Split('|');
list.Add(sliced);
}
foreach (string[] person in list)
{
Console.WriteLine (String.Join(", ", person));
if (person[0] =="Gary")
{
string txtAdd = person[1];
string txtPhone = person[2];
string txtpeople = person[3];
if (person[4] == "n" )
{
}
else
{
bool has_resvped = true;
}
break;
}
}
}
}
}
The issue is how you are iterating over the 2d array. It is usually a better idea to create a "Person" class, than try to manage it via arrays though. Oh yes, and it's usually a good idea to check that a list box item is selected before attempting to use one of its members.

c# splitting an array and displaying it in descending order in a textbox

I wish to display an array of text in a textbox, after splitting it with a comma, i pass a bunch of numbers into textbox1 and split it with the commas, how do i sort the number in descending order. here is the method i got so far
private void btnCalc_Click(object sender, EventArgs e)
{
//string A = txtInput.Text;
string[] arrText = txtInput.Text.Split(',');
int[] newOne = new int[]{};
foreach (string r in arrText)
{
}
txtOutput.AppendText( );
}
int[] newOne = arrText.Select(x => int.Parse(x)).OrderByDescending(x => x).ToArray();
You should be able to do it like this:
private void btnCalc_Click(object sender, EventArgs e)
{
//string A = txtInput.Text;
string[] arrText = txtInput.Text.Split(',');
txtOutput.Text = string.Join(",",arrText.Select( s => int.Parse(s)).OrderByDescending( i => i))
}
Note that this will blow up if some of the input text between the commas is not a number.
this should work:
var newOne = arrText.OrderByDescending(int.Parse).ToArray();
foreach (var s in newOne)
{
txtOutput.AppendText(s);
}

Categories