read a value by its index from a file in C# - c#

I'm new to programming, so please forgive my naive question .
I have double[ ] array, I manage to write it to text file using the code below:
using (System.IO.StreamWriter outfile = new System.IO.StreamWriter(#"C:\Seasonality.txt") )
{
for (int raw = 1; raw <54; raw++)
{
outfile.Write("{0} ",array[raw]);
}
}
The output text file (1 raw) consist of 54 records separated by space as demonstrated below:
1.323 2.3443 2.367 5.3453 0.3432 1.754 ........etc
What I'm trying to achieve is a function where I read a value by passing its index, i.e. index =1 for the first value in the file, or index =5 for the fifth value in the file etc..
Double GetValue (int index)
{
.....
}
P.S: please suggest if you think that changing output file structure to one value per line will ease the task.
Thanks in advance

For completeness, since you mention the option of splitting into lines per value - if you did that it would be:
var item = File.ReadLines(path).Skip(index-1).First();
(plus parsing the final value)

You're going to need to do a few things.
First: Load the file into a string. You can use File.ReadAllText() or something similar (use the IO streams if you want).
Next you need to parse your data. You have your items separated by spaces so you're going to want to use stringName.split(' '); where stringName is the variable you use for the file you just loaded and the ' ' represents the character for space (not sure how new you are but " " is a string and ' ' is a character).
Finally you want to grab the correct index, which should actually be the same as you saved the array since you're just reloading it.
Hope this helps!
Edit: Forgot that you'll need to do the double.parse thing at the end to return your value, as others have shown.

you can do as below,
double GetValue(int index)
{
return double.Parse(File.ReadLines(path).First().Split()[index-1]);
}
Note:
better you can do more validations for the results of read line, split having enough items to take by given index and use double.TryParse to convert.

double GetValue(int index)
{
return double.Parse(System.IO.File.ReadAllLines(your file)[0].Split(' ')[index]);
}

Related

Getting "System.String[]" instead of actual value after splitting.

So I have a very simple bit of code
public static string[] config = File.ReadAllLines(Environment.CurrentDirectory.ToString() + "\\documents\\config.json");
public static void Start()
{
Console.WriteLine(config[4]);
Console.ReadKey();
}
This properly displays the 5th item in the array, which is "0x00=jU0UrZBkqPXfp8MsMoILSRylevQGaUmJRnpFbfUvcGs=7lvpCgtyWl0 : crypt_wallet". I only want the first part of the string, so "0x00=jU0UrZBkqPXfp8MsMoILSRylevQGaUmJRnpFbfUvcGs=7lvpCgtyWl0".
When I use Console.WriteLine(config[4].split(null); or anything else in the split arguments, I just get back System.String[].
How would I fix that so it properly displays the answer?
Should rather be like below since you will have to choose the element to print since Split() returns a string[]
Console.WriteLine(config[4].Split(':')[0]);
Not sure what you mean by the "the first part of the string". But you can achieve this by using .Substring().
If you know that the beginning will always be a fixed length, you can do:
config[4].Substring(0, 4);
If you know the value will be followed by a certain character (like the "=" for an example:
config[4].Substring(0, config[4].IndexOf("="));

Read CSV File and Store Column in list double

carry the code below where I embarked.
class readFile{
List<double> out1 = new List<double>();
List<double> out2 = new List<double>();
List<double> out3 = new List<double>();
public readFile()
{
}
public void aproCSV()
{
var reader = new StreamReader(File.OpenRead(#"C:\altraprova.csv"));
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
var values = line.Split(';');
out1.Add(values[0]);
out2.Add(values[1]);
out3.Add(values[2]);
}
}
}
Allow me to explain my intent ....
I open my csv file
the goal is to read the second column and insert it into a list of type double and then get the value MAX.
If you use lists of type string not get erors .... but since the values contain only numbers you are signed semicolon, then I need to use the type double.. using the double type get the following error:
error 5 The best match of the overloaded method for
'System.Collections.Generic.List <double> .Add (double)' has some
invalid arguments
Split() returns a string[] and your lists are of type List<double> which means you need to parse the strings into doubles like the following:
double value1 = double.Parse(values[0]); etc
then add them to your list: out1.Add(value1);
Do be aware that you have no error handling so if the value is not a double, the code will still throw an exception.
CSV are surprisingly not so straightforward to parse, there are a lot of special cases which you have to take into consideration. For example, if your data would contain the "separation character" you'd need to put the data between quotes ("). If he contains quotes, then you have to escape them with a backslash (\) (or doubling them, I'm not sure).
So, except if you know the data you're going to be importing and are sure that those case won't happen, a simple "split" won't be sufficient.
I really recommend using an existing parser to help you on this task. I've used CsvHelper with success. It's a nice library and quite easy to use.
You need to do some parsing, because a generic list only accepts elements of the given type (double in your case):
var line = reader.ReadLine();
var values = line.Split(';');
out1.Add(double.Parse(values[0]));
out2.Add(double.Parse(values[1]));
out3.Add(double.Parse(values[2]));
This is the quick and dirty trick, you should use double.TryParse
for safety because maybe not everything you get is a double.
From you code I suppose the you need to get the max from list out2 (your second column). For this, use List.Max Method

load image in a for loop

for (int s = 1; s <= NumComponents;s++ )
{
fname = #"C:\Users\Johaira\Documents\Visual Studio 2010\Projects\SpecialProblem1\SpecialProblem1\bin\Debug\" ;
fname2 = fname + string.Format("{0:00}.png", s);
Bitmap inputImage = new Bitmap(fname2);
//do some image processing here...for example thinning
}
I am doing image processing in c#. I have this for loop that processes each image from a directory.. the file names of my images are numbers.. but I cannot load them.. what do I do..
It works when it is not in a loop..when I call
Bitmap inputImage = new Bitmap(#"C:\Users\Johaira\Documents\Visual Studio 2010\Projects\SpecialProblem1\SpecialProblem1\bin\Debug\1.png");
It is working fine..in one image only..but I want it to be dynamic so what do I do? Pls help me..thank you.
Your code uses
string.Format("{0:00}.png", s)
to produce the filename. For an input value of 1 this results in the string "01". That's because your format string explicitly includes a leading zero.
So the problem boils down to your conversion from integer to string. You want a conversion that does not have leading zeros. For example:
s.ToString()
Or if you want the convenience of converting the number, and adding on the extension in one go, then
string.Format("{0}.png", s)
The format item has the following syntax:
{ index[,alignment][ :formatString] }
So, since {0} contains just the index, and omits the formatString, the default formatting is performed by calling ToString() on the object. So, the above call to string.Format() is just a convenient way to write:
s.ToString() + '.png'
As a piece of general advice, I suggest you take some time to learn how to get the most out of your debugger. Had you inspected the value of your file name variable you would immediately have seen the erroneous leading zero. You will benefit greatly from learning how to use the debugger to investigate problems with your code.
Assuming your filenames are for example 1.png, 2.png etc:
for (int s = 1; s <= NumComponents;s++ ) {
const string fname = #"C:\Users\Johaira\Documents\Visual Studio 2010\Projects\SpecialProblem1\SpecialProblem1\bin\Debug\" ;
var fname2 = Path.Combine(fname,String.Format("{0}.png",s));
using (Bitmap inputImage = new Bitmap(fname2)) {
// Process image
}
}
The reason your code didn't work originally was you were using {0:00} which would have padded with 0 you loop value.

send a String array as parameter to a function

I have a function in a class called Function, like below:
public int SearchedRecords(String [] recs)
{
int counter = 0;
String pat = "-----";
String[] records = recs;
foreach (String line in records)
{
if (line.Contains(pat) == true)
{
counter++;
}
}
return counter;
}
And I am calling this method from my main class this way:
String [] file = File.ReadAllLines("C:/Users.../results.txt");
int counter = Function.SearchedRecords( []file);
But I get an error saying:
;expected
What is wrong?
Another question: The function above is counting from a file all the lines with the pattern ----- in them (even if with more dashes, or if the line has some chars before or after the dashes). Am I right?
It's something like the patterns in Java so maybe there is an other way.
Can you enlighten me?
Remove the [] from your parameter.
e.g.
int counter = Function.SearchedRecords(file);
And yes, your assumption about the behavior of the Contains method is correct - you'll match any line containing five consecutive dashes, regardless of what characters are before or after them.
If you want to parse for exactly five dashes, with nothing before or after them I suggest looking into the RegEx class (regular expressions).
Change
int counter = Function.SearchedRecords( []file);
to
int counter = Function.SearchedRecords(file);
and yes, this will work, for that string.
However Contains is case sensitive, if you were matching on a name, or another string with alphabetic characters, the case would have to be identical to match e.g. line.Contains("Binary Worrier") will not match a string "Hello binary worrier".
Also, reading the entire file into memory is fine if you know that the file will always be small, this method gets less efficient the larger the file.
Better to always use something like System.IO.StreamReader or System.IO.File.ReadLines (available in .Net 4 and later), these allow you to consume the file one line at a time. e.g.
using (var reader = new System.IO.StreamReader("MyFile.txt"))
{
while(!reader.EndOfStream)
{
string line = reader.ReadLine();
if (line.Contains(pattern))
counter++;
}
}
Change it to
int counter = Function.SearchedRecords(file);
Remove '[]' from a method call. Yes, your function seems to count what you want.
First of all you need to create an instance of function class and then run the function. Hope following code helps
Function fb = new Function();
int counter = fb.SearchedRecords(file);
Right now, you are using SearchRecords as an static function of a static class which doesn't require instantiation.
You can do this in a shorter way using LINQ:
int counter = file.Count(line => line.Contains("-----"));

How to get the value of a System.String object instead of returning "System.String[]"

I am working on a file parser, and this bit of code is not giving me what I want. Before I go any farther, I should mention that I did not write this program, I am only editing the source to fix this specific problem. Also, I can compile the code, so that is not a problem (you know how downloaded programs always have compile errors). Here's the code.
case EsfValueType.Binary4E: //System.String[]
{
int size = (int)(this.reader.ReadUInt32() - ((uint)this.reader.BaseStream.Position));
var strings = new string[size / 4];
for (int i = 0; i < size / 4; i++)
strings[i] = this.stringValuesUTF16[this.reader.ReadUInt32()];
esfValue.Value = strings.ToString();
break;
}
Now, I added the .ToString(); part to the above line, but it made no difference. The problem is that esfValue.Value ends up with System.String[] as it's value, and I want the value of the System.String object. If you can make sense out of this and tell me what is wrong, it would be appreciated.
The program name is ESF Editor 1.4.8.0.
case EsfValueType.Binary4E: //System.String[]
{
int size = (int)(this.reader.ReadUInt32() - ((uint)this.reader.BaseStream.Position));
var strings = new StringBuilder();
for (int i = 0; i < size / 4; i++)
{
strings.Append(this.stringValuesUTF16[this.reader.ReadUInt32()]); //or AppendLine, depending on what you need
}
esfValue.Value = strings.ToString();
break;
}
The strings variable is an array of strings - the Array class does not override the default ToString() implementation which returns the type of the object.
You need to concatenate all the strings in the array - either looping and concatenating or using LINQ and assign the resulting string to esfValue.Value. Of course, this assumes you want the values all in one string, one after the other.
Your issue is that strings isn't a single string, its an array of strings. As a result your call to ToString is calling Object.ToString(), which returns the type of the object.
Maybe you want something like
esfValue.Value = strings.Aggregate((acc, next) => acc + next)
which will simply concatenate all the strings together.
When you do a .ToString() on a class that doesn't override the .ToString() base method to return a custom string (which string[] doesn't), you're always going to get the type's namespace/class as the result.
Arrays, in and of themselves, don't have values. What value are you trying to get? Are you trying to join the array into a single, character-delimited string? If so, this would work:
esfValue.Value = string.Join(",", strings);
Just replace the , with whatever character you want to delimit the array with.
I think you just need to join the string values contained in the string array. In order to do so, you need to call String.Join and pass the string separator and the string array. It returns a single System.String.

Categories

Resources