tags:

views:

658

answers:

6

Hi Guys,

I've been trying to do this for about 6 hours now and i'm stumped..

I want the equivalent of this in C#:


    $settings = array();
    foreach(file('settings.txt') as $l) $settings[]=explode(',',$l);
    print $settings[0][2];

This is what i've got so far that doesn't work:


    string fileName = System.IO.Path.GetDirectoryName(Application.ExecutablePath) + "\\" + "settings.txt";
    string[,] settings;

    FileStream file = null;
    StreamReader sr = null;

    try
    {
        file = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.Read);
        sr = new StreamReader(file, Encoding.ASCII);
        string[] line;
        int i = 0;
        do
        {
            line = sr.ReadLine().Split(',');
            settings[i++, 0] = line[0];
        } while (line != null);
        file.Close();

        MessageBox.Show(settings[1, 0]);
    } catch (Exception err) { MessageBox.Show(err.Message); }

I get "Object reference not set to an instance of an object", any ideas would be greatly appreciated..

+3  A: 

You should initiate your array first, like that :

string[,] settings = new string[3,3];

EDIT : Also by this line, you skip to set first item of the array :

settings[i++, 0] = line[0];

You should assign your value like that :

settings[i, 0] = line[0];
i++;
Canavar
Hi Canavar, the length will vary after the program has been compiled..
Dean Bayley
then you should use a List<string> or ArrayList to store your lines.
Canavar
Just like Konrad's answer.
Canavar
+7  A: 

Use a jagged array instead of a multidimensional one – or better yet, a List<string[]>:

var settings = new List<string[]>();

foreach (string line in File.ReadLines("settings.txt", System.Text.Encoding.ASCII))
    settings.Add(line.Split(','));

Marc's use of LINQ instead of the loop is a good alternative.

Konrad Rudolph
I like this better than having to explicitly state your bounds.
TheTXI
You can even go nuts and use a Collection<Collection<string>> :-)
Matthew Whited
+3  A: 

If you are going to look at lots of different cells:

    string[][] lines = File.ReadAllLines(path).Select(
        line => line.Split(',').ToArray()).ToArray();
    Console.WriteLine(lines[0][2]);

If you only want [0][2], you can limit it a bit...

    using (StreamReader sr = File.OpenText(path))
    { // only read the first line (zero)
        Console.WriteLine(sr.ReadLine().Split(',')[2]);
    }
Marc Gravell
+3  A: 

Well, that shouldn't even compile - you never initialize the value of settings. Arrays in .NET are of a fixed size - it looks to me like you should be using a List<string[]> instead:

List<string> settings = new List<string>();

using (TextReader reader = File.OpenText(fileName, Encoding.ASCII))
{
    string line;
    while ((line = reader.ReadLine()) != null)
    {
        settings.Add(line.Split(','));
    }
}

MessageBox.Show(settings[1][0]); // Shows the first part of the second line

(Note that this also makes sure that the file gets closed even if exceptions occur - you should definitely learn about the using statement. Marc's solution avoids this by loading all the lines in a single call, which obviously has a memory overhead but is otherwise good.)

Jon Skeet
It was initialized outside of that code block because i need to access it from lots of different functions :)
Dean Bayley
Given that the way you initialize it is one of the important pieces of information, it would help if you'd present self-contained chunks of code.
Jon Skeet
A: 

Hi Guys,

Thanks for the super fast answers!!

I settled on:


    List settings = new List();
    foreach (string line in File.ReadAllLines("settings.txt", System.Text.Encoding.ASCII)) settings.Add(line.Split(','));

Thanks!

Dean.

Dean Bayley
A: 

There was a code-golf question about a similar problem last week. And by request I wrote a version that used LINQ. You can check it out on my site.

You probably want to adapt it a bit for your needs...

static void Main(string[] args)
{
        string[][] lines = null;
        using (var lp = "settings.txt".Load())
            lines = lp.Select(l => l.Split(',')).ToArray();
}

http://hackersbasement.com/?p=96 (and just in case my site ever changes)

public static class LineProcessorLinq
{
    public static LineProcessor Load(this string fileName)
    {
        return new LineProcessor(fileName);
    }

    public static void Write(this IEnumerable<string> lines, string header, string footer, string fileName)
    {
        using (var fs = File.AppendText(fileName))
            lines.Write(header, footer, fs);
    }

    public static void Write(this IEnumerable<string> lines, string header, string footer, StreamWriter writer)
    {
        if (writer == null)
            throw new ArgumentNullException("writer");

        if (!string.IsNullOrEmpty(header))
            writer.Write(header);

        foreach (var line in lines)
            writer.Write(line);

        if (!string.IsNullOrEmpty(footer))
            writer.Write(footer);
    }
}
public class LineProcessor : Component, IEnumerable<string>
{
    private StreamReader _reader = null;

    public LineProcessor(string fileName) : this(File.OpenText(fileName)) { }

    public LineProcessor(StreamReader reader)
    {
        if (reader == null)
            throw new ArgumentNullException("reader");
        _reader = reader;
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing && _reader != null)
            _reader.Close();
    }

    #region IEnumerable<string> Members

    public IEnumerator<string> GetEnumerator()
    {
        var currentPos = _reader.BaseStream.Position;
        while (!_reader.EndOfStream)
            yield return _reader.ReadLine();
        if (_reader.BaseStream.CanSeek)
            _reader.BaseStream.Seek(currentPos, SeekOrigin.Begin);
    }

    #endregion

    #region IEnumerable Members

    IEnumerator IEnumerable.GetEnumerator() { throw new NotImplementedException(); }

    #endregion
}
Matthew Whited