Adding items from a text file to an array - c#

In my C# program, I'm trying to read in data from a text file to an array. I've looked at many answers on here and can't figure out what's wrong with my code. Whenever I run it, I get an exception that says that I got an unhandled exception of type 'System.IndexOutOfRangeException', but I don't understand why the index would be out of range.
Here's what I have:
string[] namesArray = new string[] { };
using (var sr = new StreamReader(mydocpath + #"\nameIDLines.txt"))
{
for (int i = 1; i < numLines; i++)
{
nameIDLine = sr.ReadLine();
nameIDLine = nameIDLine.Split(new string[] { "ID" }, StringSplitOptions.None)[0];
namesArray[i] = nameIDLine;
}
}

When you do this:
string[] namesArray = new string[] { };
You're initializing an array with length 0. Therefore, when you do namesArray[i], it will always be out of range regardless of i.
Since you know the number of lines, and therefore the number of items, you can initialize the array with that number:
string[] namesArray = new string[numLines];

As #stybl pointed out, the problem is that you are initializing a zero-length array to store your lines... and that will always lead to an "index out of range" exception. On the top of that, I wonder how you are managing to get a consistent numLines value while using a StreamReader to parse the file... this is very risky since you must be sure that the file always contains enough lines.
I suggest you to use the following approach instead:
String[] lines = File.ReadAllLines(mydocpath + #"\nameIDLines.txt");
If you want to take a specific number of lines from the file, you can proceed as follows:
String[] lines = File.ReadAllLines(mydocpath + #"\nameIDLines.txt").Take(numLines).ToArray();

Related

how to convert a String list into a String array then converting it into an int array then counting the total sum of the numbers in the array?

So I am so fresh into the world of programming, starting new, I decided to start messing around in C# to create simple apps from ideas that come to mind, with this little app, I'm trying to have multiple TextBoxes named d1,d2,d3,d4,etc... the user inserts numbers into the textboxes then clicks button1, which begins the process in the code below creating a new list which contains all of the values of the textboxes and then the list is converted to an array and the array is then converted into an int array, etc....
BUT, when starting the application and I add values to the textboxes and then click button1, it shows 2 error like shows in the //gray code line below
Please help.
private void button1_Click(object sender, EventArgs e)
{
List<string> dodo = new List<string>();
dodo.Add(d1.Text); dodo.Add(d2.Text); dodo.Add(d3.Text); dodo.Add(d4.Text); dodo.Add(d5.Text);
dodo.Add(d6.Text); dodo.Add(d7.Text); dodo.Add(d8.Text); dodo.Add(d9.Text); dodo.Add(d10.Text);
dodo.Add(d11.Text); dodo.Add(d12.Text); dodo.Add(d13.Text); dodo.Add(d14.Text); dodo.Add(d15.Text);
dodo.Add(d16.Text); dodo.Add(d17.Text); dodo.Add(d18.Text); dodo.Add(d19.Text); dodo.Add(d20.Text);
foreach(string numb in dodo)
{
if (numb == "")
numb = "0"; //numb word has a red underline
}
string[] terms = dodo.ToArray();
int[] valv = {};
int x = 0;
for(int i=0;i<=19;i++)
{
valv[i] = int.Parse(terms[i]); //the ; in the end has a red underline and shows "FormatException was unhandled" error
i++;
x = x + valv[i];
}
string myString;
myString = x.ToString();
Result1.Text = myString;
}
you can't change the iteration variable which is numb in your case. Please change in the List container instead
List<string> dodo = new List<string>();
dodo.Add(d1.Text); dodo.Add(d2.Text); dodo.Add(d3.Text); dodo.Add(d4.Text); dodo.Add(d5.Text);
dodo.Add(d6.Text); dodo.Add(d7.Text); dodo.Add(d8.Text); dodo.Add(d9.Text); dodo.Add(d10.Text);
dodo.Add(d11.Text); dodo.Add(d12.Text); dodo.Add(d13.Text); dodo.Add(d14.Text); dodo.Add(d15.Text);
dodo.Add(d16.Text); dodo.Add(d17.Text); dodo.Add(d18.Text); dodo.Add(d19.Text); dodo.Add(d20.Text);
int k = 0;
foreach (string numb in dodo)
{
if (numb == "")
{
//numb = "0"; //numb word has a red underline
dodo[k] = "0";
}
k++;
}
Now your code on parsing into integer won't give any runtime error.
The first line "tells" you that you are not able to assign a new value to the variable which is used as a foreach iteration variable.
The second line, "tells" you that you have string value which is not able to be parsed correctly (e.g. user put string which is not a number). To avoid this you can use Int32.TryParse method instead, which will safely try to parse the given string.
The best and easiest way to achieve what you need is using LINQ methods, here is the example based on few things/assumptions:
Since you are converting empty strings into zeros, you could simply skip those entries from counting
To avoid FormatException, you should use TryParse method instead. Since TryParse method will safely parse the given string, you don't even have to filter empty strings at all (they will be skipped). However, I deliberately left filtering part, to get you a better overview of a solution.
You can use list initializer to make list initialization more readable
Solution:
List<string> dodo = new List<string>()
{
d1.Text, d2.Text //...others
};
int sum = dodo
.Where(item => !String.IsNullOrEmpty(item))
.Sum(item =>
{
if (Int32.TryParse(item, out int parsedItem))
{
return parsedItem;
}
return 0;
});
You can get more familiar with LINQ and used methods on following link

Replace character at specific index in List<string>, but indexer is read only [duplicate]

This question already has answers here:
Is there an easy way to change a char in a string in C#?
(8 answers)
Closed 5 years ago.
This is kind of a basic question, but I learned programming in C++ and am just transitioning to C#, so my ignorance of the C# methods are getting in my way.
A client has given me a few fixed length files and they want the 484th character of every odd numbered record, skipping the first one (3, 5, 7, etc...) changed from a space to a 0. In my mind, I should be able to do something like the below:
static void Main(string[] args)
{
List<string> allLines = System.IO.File.ReadAllLines(#"C:\...").ToList();
foreach(string line in allLines)
{
//odd numbered logic here
line[483] = '0';
}
...
//write to new file
}
However, the property or indexer cannot be assigned to because it is read only. All my reading says that I have not set a setter for the variable, and I have tried what was shown at this SO article, but I am doing something wrong every time. Should what is shown in that article work? Should I do something else?
You cannot modify C# strings directly, because they are immutable. You can convert strings to char[], modify it, then make a string again, and write it to file:
File.WriteAllLines(
#"c:\newfile.txt"
, File.ReadAllLines(#"C:\...").Select((s, index) => {
if (index % 2 = 0) {
return s; // Even strings do not change
}
var chars = s.ToCharArray();
chars[483] = '0';
return new string(chars);
})
);
Since strings are immutable, you can't modify a single character by treating it as a char[] and then modify a character at a specific index. However, you can "modify" it by assigning it to a new string.
We can use the Substring() method to return any part of the original string. Combining this with some concatenation, we can take the first part of the string (up to the character you want to replace), add the new character, and then add the rest of the original string.
Also, since we can't directly modify the items in a collection being iterated over in a foreach loop, we can switch your loop to a for loop instead. Now we can access each line by index, and can modify them on the fly:
for(int i = 0; i < allLines.Length; i++)
{
if (allLines[i].Length > 483)
{
allLines[i] = allLines[i].Substring(0, 483) + "0" + allLines[i].Substring(484);
}
}
It's possible that, depending on how many lines you're processing and how many in-line concatenations you end up doing, there is some chance that using a StringBuilder instead of concatenation will perform better. Here is an alternate way to do this using a StringBuilder. I'll leave the perf measuring to you...
var sb = new StringBuilder();
for (int i = 0; i < allLines.Length; i++)
{
if (allLines[i].Length > 483)
{
sb.Clear();
sb.Append(allLines[i].Substring(0, 483));
sb.Append("0");
sb.Append(allLines[i].Substring(484));
allLines[i] = sb.ToString();
}
}
The first item after the foreach (string line in this case) is a local variable that has no scope outside the loop - that’s why you can’t assign a value to it. Try using a regular for loop instead.
Purpose of for each is meant to iterate over a container. It's read only in nature. You should use regular for loop. It will work.
static void Main(string[] args)
{
List<string> allLines = System.IO.File.ReadAllLines(#"C:\...").ToList();
for (int i=0;i<=allLines.Length;++i)
{
if (allLines[i].Length > 483)
{
allLines[i] = allLines[i].Substring(0, 483) + "0";
}
}
...
//write to new file
}

How can I change array elements C#

How can I get array or array values from for-loop?
Example first outputs prints right solution, but second output prints just last line, last word of array.
How to get correct value for array from splitLine and save it in variable for using it later?
File text
Title:
Here is my first line.
Here is my second line.
Here is my third line.
Here is my fourth line.
Here is my fifth line.
Code
using System;
using System.IO;
namespace Array
{
class Class
{
private static void Main()
{
string[] lines = File.ReadAllLines(
#"file.txt");
string[] array = new string[] {};
for (int i = 0; i < lines.Length; i++)
{
string[] splitLine = lines[i].Split();
for (int j = 0; j < splitLine.Length; j++)
{
Console.WriteLine(splitLine[j]);
array = splitLine[j].Split();
}
}
Array.ForEach(array, Console.WriteLine);
}
}
}
If you are expecting the 'array' variable to accumulated values from each string split operations, then you don't have it quite right. As written your code only sets the 'array' variable to the last string split operations. You should consider using a collection type like List as the type for your array. Then call the Add method to add a single item or the AddRange method to add an enumeration (which can be an array).
The ReadAllLines() method is already splitting your text into lines. I'm not clear if you want to split it further? If not, simply:
var lines = File.ReadAllLines(#"file.txt");
lines.ToList().ForEach(Console.WriteLine);
Should output the lines to the console

Can't find string in input file

I have a text file, which I am trying to insert a line of code into. Using my linked-lists I believe I can avoid having to take all the data out, sort it, and then make it into a new text file.
What I did was come up with the code below. I set my bools, but still it is not working. I went through debugger and what it seems to be going on is that it is going through the entire list (which is about 10,000 lines) and it is not finding anything to be true, so it does not insert my code.
Why or what is wrong with this code?
List<string> lines = new List<string>(File.ReadAllLines("Students.txt"));
using (StreamReader inFile = new StreamReader("Students.txt", true))
{
string newLastName = "'Constant";
string newRecord = "(LIST (LIST 'Constant 'Malachi 'D ) '1234567890 'mdcant#mail.usi.edu 4.000000 )";
string line;
string lastName;
bool insertionPointFound = false;
for (int i = 0; i < lines.Count && !insertionPointFound; i++)
{
line = lines[i];
if (line.StartsWith("(LIST (LIST "))
{
values = line.Split(" ".ToCharArray());
lastName = values[2];
if (newLastName.CompareTo(lastName) < 0)
{
lines.Insert(i, newRecord);
insertionPointFound = true;
}
}
}
if (!insertionPointFound)
{
lines.Add(newRecord);
}
You're just reading the file into memory and not committing it anywhere.
I'm afraid that you're going to have to load and completely re-write the entire file. Files support appending, but they don't support insertions.
you can write to a file the same way that you read from it
string[] lines;
/// instanciate and build `lines`
File.WriteAllLines("path", lines);
WriteAllLines also takes an IEnumerable, so you can past a List of string into there if you want.
one more issue: it appears as though you're reading your file twice. one with ReadAllLines and another with your StreamReader.
There are at least four possible errors.
The opening of the streamreader is not required, you have already read
all the lines. (Well not really an error, but...)
The check for StartsWith can be fooled if you lines starts with blank
space and you will miss the insertionPoint. (Adding a Trim will remove any problem here)
In the CompareTo line you check for < 0 but you should check for == 0. CompareTo returns 0 if the strings are equivalent, however.....
To check if two string are equals you should avoid using CompareTo as
explained in MSDN link above but use string.Equals
List<string> lines = new List<string>(File.ReadAllLines("Students.txt"));
string newLastName = "'Constant";
string newRecord = "(LIST (LIST 'Constant 'Malachi 'D ) '1234567890 'mdcant#mail.usi.edu 4.000000 )";
string line;
string lastName;
bool insertionPointFound = false;
for (int i = 0; i < lines.Count && !insertionPointFound; i++)
{
line = lines[i].Trim();
if (line.StartsWith("(LIST (LIST "))
{
values = line.Split(" ".ToCharArray());
lastName = values[2];
if (newLastName.Equals(lastName))
{
lines.Insert(i, newRecord);
insertionPointFound = true;
}
}
}
if (!insertionPointFound)
lines.Add(newRecord);
I don't list as an error the missing write back to the file. Hope that you have just omitted that part of the code. Otherwise it is a very simple problem.
(However I think that the way in which CompareTo is used is probably the main reason of your problem)
EDIT Looking at your comment below it seems that the answer from Sam I Am is the right one for you. Of course you need to write back the modified array of lines. All the changes are made to an in memory array of lines and nothing is written back to a file if you don't have code that writes a file. However you don't need new file
File.WriteAllLines("Students.txt", lines);

parsing multi sections of a text file C#

First let me start by thanking you all for being part of this site, I have already gained so much helpful information from it. including some basic parsing of text files in to Arrays, but i now want to go a step further.
I have a text file that looks some thing like this
Start Section 1 - foods
apple
bannana
pear
pineapple
orange
end section 1
Start section 2 - animals
dog
cat
horse
cow
end section 2
what I want to do is using a single read of the file copy the data from section 1 in to an array called "foods" and section 2 in to and array called "animals"
now I can get it to work by using a new loop for each section, closing and reopening the file each time, looping till I find the section I want and creating the array.
But I was thinking there must be a way to read each section in to a separate array in one go saving time.
so my current code is
List<string> typel = new List<string>();
using (StreamReader reader = new StreamReader("types.txt")) // opens file using streamreader
{
string line; // reads line by line in to varible "line"
while ((line = reader.ReadLine()) != null) // loops untill it reaches an empty line
{
typel.Add(line); // adds the line to the list varible "typel"
}
}
Console.WriteLine(typel[1]); // test to see if list is beeing incremented
string[] type = typel.ToArray(); //converts the list to a true array
Console.WriteLine(type.Length); // returns the number of elements of the array created.
which is for a simple text file with no sections just list of values, using list seemed a good way to deal with unknown lengths of arrays.
I was also wondering how to deal with the first value.
for example if i do
while ((line = reader.ReadLine()) != Start Section 1 - foods)
{
}
while ((line = reader.ReadLine()) != end Section 1)
{
foods.Add(line);
}
...
....
I end up with the "start Section 1 - foods" as one of the array elements. I can remove it with code but is there an easy way to avoid this so only the list items get populated?
Cheers and once again thanks for all the help. Its great to be getting back in to programming after many many years.
Aaron
Reading the lines is not the issue, see System.IO.ReadAllLines(fileName) and its siblings.
What you need is a (very simple) interpreter:
// totally untested
Dictionary<string, List<string>> sections = new Dictionary<string, List<string>>();
List<string> section = null;
foreach(string line in GetLines())
{
if (IsSectionStart(line))
{
string name = GetSectionName(line);
section = new List<string>();
sections.Add(name, section);
}
else if (IsSectionEnd(line))
{
section = null; // invite exception when we're lost
}
else
{
section.Add(line);
}
}
...
List<string> foods = sections ["foods"];
Look for pointers for start and end. This is where you start putting things into arrays, lists, etc.
Here is a stab at making it very flexible:
class Program
{
private static Dictionary<string, List<string>> _arrayLists = new Dictionary<string, List<string>>();
static void Main(string[] args)
{
string filePath = "c:\\logs\\arrays.txt";
StreamReader reader = new StreamReader(filePath);
string line;
string category = "";
while (null != (line = reader.ReadLine()))
{
if (line.ToLower().Contains("start"))
{
string[] splitHeader = line.Split("-".ToCharArray());
category = splitHeader[1].Trim();
}
else
{
if (!_arrayLists.ContainsKey(category))
{
List<string> stringList = new List<string>();
_arrayLists.Add(category, stringList);
}
if((!line.ToLower().Contains("end")&&(line.Trim().Length > 0)))
{
_arrayLists[category].Add(line.Trim());
}
}
}
//testing
foreach(var keyValue in _arrayLists)
{
Console.WriteLine("Category: {0}",keyValue.Key);
foreach(var value in keyValue.Value)
{
Console.WriteLine("{0}".PadLeft(5, ' '), value);
}
}
Console.Read();
}
}
To add to the other answers, if you don't want to parse the text file yourself, you could always use a quick and dirty regular expression if you're comfortable with them:
var regex = new Regex(#"Start Section \d+ - (?<section>\w+)\r\n(?<list>[\w\s]+)End Section", RegexOptions.IgnoreCase);
var data = new Dictionary<string, List<string>>();
foreach (Match match in regex.Matches(File.ReadAllText("types.txt")))
{
string section = match.Groups["section"].Value;
string[] items = match.Groups["list"].Value.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
data.Add(section, new List<string>(items));
}
// data["animals"] now contains a list of "dog", "cat", "horse", and "cow"
In response to the comment:
but "list" sounds so simple and basic
(like i am going shopping), array has
much nicer ring to it ;) But I will
look in to them maybe a bit more, I
got the impression from my research
that arrays are more efficent code?
It's not about whether a list vs. array is "basic" or "has a nicer ring", it's about the purpose of the code. In your case, you're iterating a file line-by-line and adding items to a collection of an unknown size beforehand - which is one problem a list was designed to solve. Of course you could peek through the file and determine the exact size, but is doing that worth the extra "efficiency" you get from using an array, and is iterating the file twice going to take longer than using a list in the first place? You don't know unless you profile your code and conclude that specific portion is a bottleneck... which I'll say, will almost never be the case.
Uhmmm, like this?
//converting it to array called allLines, elements/index per line
string[] allLines = File.ReadAllLines("types.txt").ToArray();
//getting the index of allLines that contains "Start Section 1" and "end section 1"
int[] getIndexes = new int[] { Array.FindIndex(allLines, start => start.Contains("Start Section 1")), Array.FindIndex(allLines, start => start.Contains("end section 1")) };
//create list to get indexes of the list(apple,banana, pear, etc...)
List<int> indexOfList = new List<int>();
//get index of the list(apple,banana, pear,etc...)
for (int i = getIndexes[0]; i < getIndexes[1]; i++)
{
indexOfList.Add(i);
}
//remove the index of the element or line "Start Section 1"
indexOfList.RemoveAt(0);
//final list
string[] foodList = new string[]{ allLines[indexOfList[0]], allLines[indexOfList[1]], and so on...};
Then you can call them or edit then save.
//call them
Console.Writeline(foodList[0] + "\n" + foodList[1] + ...)
//edit the list
allLines[indexOfList[0]] = "chicken"; //from apple to chicken
allLines[indexOfList[1]] = "egg"; //from banana to egg
//save lines
File.WriteAllLines("types.txt", allLines);

Categories

Resources