4

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..

5
  • Can you post a few sample lines of settings.txt? Commented Jun 17, 2009 at 12:59
  • Which line do you get the exception? Commented Jun 17, 2009 at 12:59
  • It would help if you made it clear what the php does... Commented Jun 17, 2009 at 13:00
  • @Andrew: Its just csv: value,value,value,value,value,value @Daniel: settings[i++, 0] = line[0]; Commented Jun 17, 2009 at 13:03
  • It turns csv into an array: { 0 : {value,value,value,value,value,value}, 1 : {value,value,value,value,value,value}, 2 : {value,value,value,value,value,value}, 3 : {value,value,value,value,value,value} } Commented Jun 17, 2009 at 13:06

6 Answers 6

7

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.

Sign up to request clarification or add additional context in comments.

2 Comments

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

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++;

1 Comment

then you should use a List<string> or ArrayList to store your lines.
3

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]);
    }

Comments

3

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.)

2 Comments

It was initialized outside of that code block because i need to access it from lots of different functions :)
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.
0

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.

Comments

0

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
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.