Hey guys Im trying to be able to save an array from a text file but I'm at my wits end trying to figure out how to save it. I can print all the elements of the matrix as can be seen from the text file.
Sample input:
1 2 3 4 5
2 3 4 5 6
3 4 5 6 7
1 2 3 4 5
I keep getting an index out of range exception. Not sure what's happening.
Hopefully you guys understand what im trying to do.
Here's what I have so far:
class Program
{
static void Main(string[] args)
{
string input =
#"C:\Users\Nate\Documents\Visual Studio 2015\Projects\Chapter 15\Chapter 15 Question 5\Chapter 15 Question 5\TextFile1.txt";
StreamReader reader = new StreamReader(input);
List<string> list = new List<string>();
char[] unwanted = new char[] { ' ' };
using (reader)
{
int row = 0;
int column = 0;
string line = reader.ReadLine();
while (line != null)
{
string[] numbersString = line.Split(unwanted);
int[,] numbersInt = new int [ row, numbersString.Length];
foreach (string a in numbersString)
{
Console.Write("{0} ",a);// this is to check that the array was read in the right order
numbersInt[row, column] = int.Parse(a);
column++;
}
line = reader.ReadLine();
Console.WriteLine();
row++;
}
}
}
}
I suggest using jugged arrays (array of array int[][]) instead of 2D ones; in that case the solution will be quite simple, something like this (Linq):
int[][] matrix = File
.ReadLines(#"C:\myFile.txt")
.Split(new Char[] {' ', '\t'}, StringSplitOptions.RemoveEmptyEntries)
.Select(items => items
.Select(item => int.Parse(item))
.ToArray())
.ToArray();
Test (let's print out the matrix):
String report = String.Join(Environment.NewLine, matrix
.Select(line => String.Join(" ", line)));
Console.Write(report);
This change in your while should do the trick:
while (line = file.ReadLine()) != null)
{
...
}
Source: MSDN
You appear to be creating your instance of numbersInt inside your while loop. This means that with each pass of the loop you will re-create the array and when the loop exits the array will be lost. Move the declaration for numberInt to outside of the while loop.
Your immediate issue is that your code does not reset column back to zero after reading each line. Move int column = 0 into the while loop to fix this issue.
The second issue is numbersInt allocation. You create it for each line, which is not right, because it's a 2-D array. You need to create it before the loop, but of course you can't, because you don't know how many lines you are going to have. One approach is to use a dynamic data structure, and add one row at a time to it.
You can greatly simplify your code by using File.ReadAllLines method in combination with LINQ, because this would let you get rid of a lot of simple code. Now you can check how many lines you have before creating your 2-D array, and you could fill it in much easier as well:
var allRows = File
.ReadLines(#"C:\Users\Nate\Documents\Visual Studio 2015\Projects\Chapter 15\Chapter 15 Question 5\Chapter 15 Question 5\TextFile1.txt")
.Select(line => line.Split(unwanted).Select(int.Parse).ToList())
.ToList();
If you are OK with an array of arrays, you don't need to do anything: allRows is a 2-D structure of rows and columns containing your matrix.
If you must convert it to a 2-D array, you can do it with a pair of nested for loops:
if (allRows.Count == 0) {
// ... The file has no data - handle this error
}
var matrix = new int[allRows.Count, allRows[0].Count];
for (int row = 0 ; row != allRows.Count ; row++) {
for (int col = 0 ; col != allRows[0].Count ;col++) {
matrix[row, col] = allRows[row][col];
}
}
Related
I've made a program that extracts some info from a file , do some operations with it and store it back on a list.
Following this link:
Are 2 dimensional Lists possible in c#?
I've been able to create a class with a list who would suit my needs. But after some debugging i've found that i was overwriting the list on each loop iteration.
Then i decided to make an array of lists - followed this link:
How to create an array of List<int> in C#?
Created an array of lists, initialized it and added elements. But when it needs to move to the next list position , it throws the out of boundaries exception.
I've tried a few things (readed about race condition) but none of 'em worked.
The problem will happen only when i open more than one file with my code ; otherwise it works perfectly.
Exception is thrown at xmldata , in the last iteration of the current file.
Ex: Selected two files, each one will add five elements. In the last element of the first file the exception will be thrown and there's data in the last element's position to be added.
Additional information: Index was outside the bounds of the array. (Exception thrown).
Any help will be appreciated. Thanks a lot.
Code:
List<xmldata>[] finalcontent = new List<xmldata>[9999];
finalcontent[listpos] = new List<xmldata>();//Initializing a list for each filename
foreach (Match m in matches)
{
Double[] numbers;
string aux;
aux = m.Groups[1].ToString();
aux = Regex.Replace(aux, #"\s+", "|");
string[] numbers_str = aux.Split(new[] { "|" }, StringSplitOptions.RemoveEmptyEntries);
numbers = new Double[numbers_str.Length];
for (int j = 0; j < numbers.Length; j++)
{
numbers[j] = Double.Parse(numbers_str[j], CultureInfo.InvariantCulture);
//Converts each number on the string to a Double number, store it in a position
//in the Double array
numbers[j] = numbers[j] / 100; //Needed calculus
numbers[j] = Math.Round(numbers[j], 3); //Storing numbers rounded
}
string values = String.Join(" ", numbers.Select(f => f.ToString()));
if (i <= colors_str.Length)
{
finalcontent[listpos].Add(new xmldata//The exception is thrown right here
{
colorname = colors_str[i],
colorvalues = values,
});//Closing list add declaration
}//Closing if
i++;
}//Closing foreach loop
Link to the file: https://drive.google.com/file/d/0BwU9_GrFRYrTT0ZTS2dRMUhIWms/view?usp=sharing
Arrays are fixed size, but Lists automatically resize as new items are added.
So instead, and since you're using Lists anyway, why not use a list of lists?
List<List<int>> ListOfListsOfInt = new List<List<int>>();
Then, if you really absolutely must have an array, then you can get one like this:
ListOfListsOfString.ToArray();
// Convert non-ascii characters to .
for (int jx = 0; jx < cnt; ++jx)
if (line[jx] < 0x20 || line[jx] > 0x7f) line[jx] = (byte)'.';
This is a big example, but check this one. You increase 'jx' before entering the statement, possibly exceeding the boundary of cnt?
Try changing the following:
if (i <= colors_str.Length)
to
if (i < colors_str.Length).
In fact I'm convinced that this is the problem.
This is because refereces begin at 0 and the last reference is length - 1, not length.
When using a list - it is better to use native functions for it.
List<xmldata>[] finalcontent = new List<xmldata>();
......
finalcontent[listpos] = new List<xmldata>(); insted of var _tmpVariable = new List<xmldata>();//Initializing a list for each filename
......
_tmpVariable.Add(new xmldata
{
colorname = colors_str[i],
colorvalues = values,
});//Closing list add declaration
fs.Close();//closing current file
listpos++;//Increment list position counter
finalcontent.Add(_tmpVariable); // add list into list
As there is no exception details it is hard to get where the exception is thrown.
It could be a list issue, a string issue or other (even file reading issue as well),
So please update this with current exception details.
My problem today is about creating an array from an existing one.
My "parent" array contains elements with two characters.
My new array's elements should contain 20 elements from the "parent" array.
Example:
string[] parentArray = {aa, bb, cc, df, ds, aa, zz, xx, cc, ww, fg, qq, ww, ee,
key: (0) (1) (2) (3) (4) (6) (7) (8) (9) (10)........ rr, dd, ss, qq, dd, ss, sa, wq, ee, rr}
string[] childArray = {aabbccdfdsaazzxxccwwfgqqwweerrddssqqddss,.....}
(1)
With some of the extension functions for enumerables you can go a long way here.
int cursor = 0;
List<string> result = new List<string>();
while (cursor < parentArray.Length)
{
result.Add(String.Join("", parentArray.Skip(cursor).Take(20)));
cursor += 20;
}
string[] childArray = result.ToArray();
This function walks over your array, fetches 20 elements (or less in case there aren't 20 elements left) and merges them into a string and add that string to a list. I made use of the String.Join method to concat the string. That works nicely here.
The Skip function and the Take function are extension functions for IEnumerable and do just what they say.
EDIT: I did assume that your source array is longer and may contain multiple blocks of 20 elements that need to be moved to the childArray
EDIT2: In case you have a load of values in your parentArray you may want to go a different way, to get some more performance out of it. In that case I suggest using the StringBuilder.
var builder = new Text.StringBuilder();
List<string> result = new List<string>();
for (int cursor = 0; cursor < parentArray.Length; cursor++)
{
if (builder.Length > 0 && (cursor % 20) == 0)
{
result.Add(builder.ToString());
builder.Length = 0;
}
builder.Append(parentArray[cursor]);
}
/* At this point you can choose to add the remaining elements to the list or not. */
if (builder.Length > 0)
{
result.Add(builder.ToString());
}
string[] childArray = result.ToArray();
Sounds as if a simple LINQ-statement will do what you need:
var myArr = parent.Take(20).ToArray();
This will select the 20 first elements of your parent-array.
EDIT: To do this with all of your elements within parent loop its entries:
List<string> result= new List<string>();
while(parent.Any()) {
result.Add(String.Join("", parent.Take(20).ToArray());
parent = parent.Skip(20).ToArray();
}
Finally convert your list back to an array using result.ToArray.
You can make a for loop on the parent array and add the element inside the array to a string like the following
String str="";
for (int i=0;i<count(parent);i++){
str+=parent[i].tostring();
}
Then make a new string array and at the first index put the str variable...
Hope this help you if this what u r asking for.
I have the code below which has created 2 arrays of integers from an input text file, I am trying to use the values from the 2 arrays to read a database using a stored procedure but I am getting this error:
Index was outside the bounds of the array.
Error is occuring when I run and debug program when it tries to assign
tests[x] = testId; in the code.
//read the error file
using (var reader = new StreamReader(#"D:\Temp\AccessError.txt"))
try
{
int testId = 0;
int eventId = 0;
string line;
while ((line = reader.ReadLine()) != null)
{
//split the line
string[] parts = line.Split(new[] { "Event" }, StringSplitOptions.None);
//get valid integers
int[] tests = GetInts(parts[0].Split(' ', '\'')).ToArray();
int[] events = GetInts(parts[1].Split(' ', '\'')).ToArray();
foreach (int x in tests)
{
tests[x] = testId;
}
foreach (int y in events)
{
events[y] = eventId;
}
//stored proc to call database
SybaseAccess.GetPlans(aseConn, testId, eventId);
}
}
The error message is probably just what's going wrong: You're trying to access the array at an index that doesn't exist.
Let's say that you've parsed the numbers 1,2,3,4,5 from the line. These numbers are stored in the tests array, it has five elements. In this case the first four array accesses will work, but the fifth will fail, because the array has the indices 0,1,2,3,4
You should check if the numbers in tests don't exceed the length of the array.
Moreover I don't understand what exactly you are doing. You are parsing an array of numbers from a line ? And then you overwrite each of these numbers by replacing it with the testId ? That's rather complicated. If you want to have an array that contains n-times the testId as an integer, why not create that directly ?
Example
If I had a text file with these lines:
The cat meowed.
The dog barked.
The cat ran up a tree.
I would want to end up with a matrix of rows and columns like this:
0 1 2 3 4 5 6 7 8 9
0| t-h-e- -c-a-t- -m-e-o-w-e-d-.- - - - - - - -
1| t-h-e- -d-o-g- -b-a-r-k-e-d-.- - - - - - - -
2| t-h-e- -c-a-t- -r-a-n- -u-p- -a- -t-r-e-e-.-
Then I would like to query this matrix to quickly determine information about the text file itself. For example, I would quickly be able to tell if everything in column "0" is a "t" (it is).
I realize that this might seem like a strange thing to do. I am trying to ultimately (among other things) determine if various text files are fixed-width delimited without any prior knowledge about the file. I also want to use this matrix to detect patterns.
The actual files that will go through this are quite large.
Thanks!
For example, I would quickly be able to tell if everything in column "0" is a "t" (it is).
int column = 0;
char charToCheck = 't';
bool b = File.ReadLines(filename)
.All(s => (s.Length > column ? s[column] : '\0') == charToCheck);
What you can do is read the first line of your text file and use it as a mask. Compare every next line to the mask and remove every character from the mask that is not the same as the character at the same position. After processing al lines you'll have a list of delimiters.
Btw, code is not very clean but it is a good starter I think.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace DynamicallyDetectFixedWithDelimiter
{
class Program
{
static void Main(string[] args)
{
var sr = new StreamReader(#"C:\Temp\test.txt");
// Get initial list of delimiters
char[] firstLine = sr.ReadLine().ToCharArray();
Dictionary<int, char> delimiters = new Dictionary<int, char>();
for (int i = 0; i < firstLine.Count(); i++)
{
delimiters.Add(i, firstLine[i]);
}
// Read subsequent lines, remove delimeters from
// the dictionary that are not present in subsequent lines
string line;
while ((line = sr.ReadLine()) != null && delimiters.Count() != 0)
{
var subsequentLine = line.ToCharArray();
var invalidDelimiters = new List<int>();
// Compare all chars in first and subsequent line
foreach (var delimiter in delimiters)
{
if (delimiter.Key >= subsequentLine.Count())
{
invalidDelimiters.Add(delimiter.Key);
continue;
}
// Remove delimiter when it differs from the
// character at the same position in a subsequent line
if (subsequentLine[delimiter.Key] != delimiter.Value)
{
invalidDelimiters.Add(delimiter.Key);
}
}
foreach (var invalidDelimiter in invalidDelimiters)
{
delimiters.Remove(invalidDelimiter);
}
}
foreach (var delimiter in delimiters)
{
Console.WriteLine(String.Format("Delimiter at {0} = {1}", delimiter.Key, delimiter.Value));
}
sr.Close();
}
}
}
"I am trying to ultimately (among other things) determine if various text files are fixed-width (...)"
If that's so, you could try this:
public bool isFixedWidth (string fileName)
{
string[] lines = File.ReadAllLines(fileName);
int length = lines[0].Length;
foreach (string s in lines)
{
if (s.length != Length)
{
return false;
}
}
return true;
}
Once you get that lines variable, you can access any character as though they were in a matrix. Like char c = lines[3][1];. However, there is no hard guarantee that all lines are the same length. You could pad them to be the same length as the longest one, if you so wanted.
Also,
"how would I query to get a list of all columns that contain a space character for ALL rows (for example)"
You could try this:
public bool CheckIfAllCharactersInAColumnAreTheSame (string[] lines, int colIndex)
{
char c = lines[0][colIndex];
try
{
foreach (string s in lines)
{
if (s[colIndex] != c)
{
return false;
}
}
return true;
}
catch (IndexOutOfRangeException ex)
{
return false;
}
}
Since it's not clear where you're have difficulty exactly, here are a few pointers.
Reading the file as strings, one per line:
string[] lines = File.ReadAllLines("filename.txt");
Obtaning a jagged array (a matrix) of characters from the lines (this step seems unnecessary since strings can be indexed just like character arrays):
char[][] charMatrix = lines.Select(l => l.ToCharArray()).ToArray();
Example query: whether every character in column 0 is a 't':
bool allTs = charMatrix.All(row => row[0] == 't');
I have a file of integers. the first number - the number of subsequent numbers.
as the easiest way to take this file into an array? C#
Example 1: 8 1 2 3 4 5 6 7 8
Example 2: 4 1 2 3 0
Example 3: 3 0 0 1
int[] numbers = File
.ReadAllText("test.txt")
.Split(' ')
.Select(int.Parse)
.Skip(1)
.ToArray();
or if you have a number per line:
int[] numbers = File
.ReadAllLines("test.txt")
.Select(int.Parse)
.Skip(1)
.ToArray();
int[] numbers = File
.ReadAllLines("test.txt")
.First()
.Split(" ")
.Skip(1)
.Select(int.Parse)
.ToArray();
if your file consist of all numbers in column style (under eachother), than you can read it like this
static void Main()
{
//
// Read in a file line-by-line, and store it all in a List.
//
List<int> list = new List<int>();
using (StreamReader reader = new StreamReader("file.txt"))
{
string line;
while ((line = reader.ReadLine()) != null)
{
list.Add(Convert.ToInt16(line)); // Add to list.
Console.WriteLine(line); // Write to console.
}
}
int[] numbers = list.toArray();
}
ok, post was updated after i posted this, but might be of some help though :)