Wrox Programmer Forums
Go Back   Wrox Programmer Forums > C# and C > C# 4.0 aka C# 2010 > BOOK: Beginning Visual C# 2010
|
BOOK: Beginning Visual C# 2010
This is the forum to discuss the Wrox book Beginning Visual C# 2010 by Karli Watson, Christian Nagel, Jacob Hammer Pedersen, Jon D. Reid, Morgan Skinner, ; ISBN: 9780470502266
Welcome to the p2p.wrox.com Forums.

You are currently viewing the BOOK: Beginning Visual C# 2010 section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
 
Old July 30th, 2012, 07:30 PM
Authorized User
 
Join Date: Jul 2012
Posts: 13
Thanks: 4
Thanked 0 Times in 0 Posts
Default Is it possible to make an array of FileStream objects?

I'm trying to open a series of files for writing (though my example below is reading). The following code works for a single file:
Code:
public partial class Form1 : Form {

        FileStream QUERYFILEHOOK;
        StreamReader QUERYFILE;


        public Form1() {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e) {
            try {
                QUERYFILEHOOK = new FileStream(@"K:\data\fruit.txt", FileMode.Open);
                QUERYFILE = new StreamReader(QUERYFILEHOOK);

            } catch (IOException ex) {
                MessageBox.Show("Uhoh...\r\n" + ex.ToString());
            }

        }

        private void button3_Click(object sender, EventArgs e) {
            string row;

            // Now we go through the actual data
            row = QUERYFILE.ReadLine();
            row = row.Trim();
            while (row != null) {
                row = row.Trim();

                // Ignore blank lines
                if (row == "") continue;

                tb.Text += row + "\r\n";

                row = QUERYFILE.ReadLine();
            }
        }
    }
But if I make the FileStream object an array I get an exception thrown. The code is:

Code:
public partial class Form1 : Form {

        FileStream[] QUERYFILEHOOK;
        StreamReader[] QUERYFILE;

        public Form1() {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e) {
            try {
                QUERYFILEHOOK[1] = new FileStream(@K:\data\fruit.txt", FileMode.Open);
                QUERYFILE[1] = new StreamReader(QUERYFILEHOOK[1]);

                QUERYFILEHOOK[2] = new FileStream(@"K:\data\animals.txt", FileMode.Open);
                QUERYFILE[2] = new StreamReader(QUERYFILEHOOK[1]);


            } catch (IOException ex) {
                MessageBox.Show("Uhoh\r\n" + ex.ToString());
            }

        }

        private void button2_Click(object sender, EventArgs e) {
          
            string row;

            // Now we go through the actual data
            row = QUERYFILE[1].ReadLine();
            row = row.Trim();
            while (row != null) {
                row = row.Trim();

                // Ignore blank lines
                if (row == "") continue;

                tb.Text += row + "\r\n";

                row = QUERYFILE[1].ReadLine();

            }
        }
    }
And the exception is:

Quote:
Object reference not set to an instance of an object.
Is there some reason that I can't create an array of FileStream objects?

Thanks!
 
Old July 31st, 2012, 01:45 PM
Authorized User
 
Join Date: Jul 2012
Posts: 13
Thanks: 4
Thanked 0 Times in 0 Posts
Default Solution

Well I got it to work, but it turns out to be a terrible headache. Instead of arrays I used a List of Dictionary elements.

Allow me to share the solution with you. But first, to reiterate the problem.


The Problem

In the example code in my original post above, I first created an uninitialized array to hold FileStream objects:

Code:
FileStream[] QUERYFILEHOOK
The problem is, how can I initialize the array now? In my example I showed,

Code:
QUERYFILEHOOK[1] = new FileStream(@K:\data\fruit.txt", FileMode.Open);
But that's not how you initialize an array, is it? It should look something like,

Code:
QUERYFILEHOOK = new FileStream(@K:\data\fruit.txt", FileMode.Open)[3];
So now I've made an array of FileStream objects but each one is pointing to the same file. That's not what I want. Normally you would start with a blank array of proper size, and populate it later. Hence you may be tempted to write a line such as,

Code:
FileStream[] QUERYFILEHOOK = new FileStream()[3];
But this will generate an error:

Quote:
'System.IO.FileStream' does not contain a constructor that takes 0 arguments
A Solution

Well I got this code to work using List and Dictionary elements. First the code:

Code:
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.IO;


namespace learning_try_catch_filehandles {

    public partial class Form1 : Form {

        int max = 2;        // Number of files we're going to be looking at;

        Dictionary<FileStream, StreamReader> FILE = new Dictionary<FileStream, StreamReader>();
        List<Dictionary<FileStream, StreamReader>> FILELIST = new List<Dictionary<FileStream, StreamReader>>(2);

        FileStream tmp_stream;
        StreamReader tmp_reader;
        Dictionary<FileStream, StreamReader> tmp_dict;

        public Form1() {
            InitializeComponent();

            // Initialize proper number of FILELIST elements  (see comment 1 below)
            for (int i = 0; i < max; ++i) {
                FILELIST.Add(tmp_dict);
            }

        }

        private void button1_Click(object sender, EventArgs e) {

            try {

                tmp_stream = new FileStream(@"K:\data\set1.txt", FileMode.Open);
                tmp_reader = new StreamReader(tmp_stream);
                tmp_dict = new Dictionary<FileStream, StreamReader>();
                tmp_dict.Add(tmp_stream, tmp_reader);

                FILELIST[0] = tmp_dict;

                tmp_stream = new FileStream(@"K:\data\set2.txt", FileMode.Open);
                tmp_reader = new StreamReader(tmp_stream);
                tmp_dict.Add(tmp_stream, tmp_reader);

                FILELIST[1] = tmp_dict;

            } catch (IOException ex) {
                MessageBox.Show("Uhoh...\r\n" + ex.ToString());
            }

        }

        private void button2_Click(object sender, EventArgs e) {

            string row;

            // Now we go through the actual data
            for (int i = 0; i < 2; i++) {
                tmp_dict = FILELIST[i];

                foreach (KeyValuePair<FileStream, StreamReader> kvp in FILELIST[i]) {       // See comment 2
                    row = kvp.Value.ReadLine();

                    while (row != null) {

                        row = row.Trim();
                        if (row == "") continue;                // Ignore blank lines

                        textbox.Text += row + "\r\n";
                        row = kvp.Value.ReadLine();
                    }

                    textbox.Text += "\r\n";

                } // END foreach
            } // END for
        } // END button2_Click
    }// END class Form1
}
If you notice in the code above there are to comment references (comment 1 and 2). Let me address them now:

Comment 1: I'm looping through and adding 'max' number of empty dictionary elements to FILELIST. The reason I'm doing this is because in my particular application I need to know for sure exactly which file is connected to which index within the List. Therefore I can't just add each Dictionary element ( using FILELIST.Add() ) with my actual data.

So I first create an empty set so that I may add the actual Dictionary elements using the index notation, FILELIST[0] = tmp_dict;.

Also, as an aside, although in my example code I'm adding the two Dictionary elements using explicit file names, it's hopefully obvious that I can do that in a loop instead (which I'll be doing in my actual project).

Comment 2: I'm using the foreach loop in concert with the KeyValuePair function to get the Key and Value (which is the FileStream and StreamReader objects respectively) for this particular Dictionary element.

Even though there is only a single Dictionary element in each List I personally don't know of a better way to access the Dictionary's Value without an explicit reference to the Key (which I'm trying to avoid to keep this generic), even though there is only a single Dictionary element in each List element.

Final Thoughts

First off, I'm not sure that I even need to keep the FileStream references once I have the StreamReader objects created. In such a case I could do this all with just a List with no Dictionary.

Secondly, you may be thinking that this is an excessive amount of code just to open a few files; to that I would reply,
  1. I am new to C#. There's no reason to think this is the most efficient way to code a solution.
  2. Remember that C# is written by Microsoft. I don't think anyone, in the history of the company, has accused them of being efficient at anything. ;)

As it turns out, after getting this to work. I feel like it's too complicated to keep. Since the code I'm writing will be maintained by someone else I don't feel comfortable handing this sort of convolution onto some poor soul. Hence I've decided that I will go ahead and just manually create each file handle with easy to understand variable names.

Not ideal, I know, but this mess is, well, too messy. :P

Last edited by KaneT; July 31st, 2012 at 01:51 PM..
 
Old July 31st, 2012, 02:15 PM
Authorized User
 
Join Date: Jul 2012
Posts: 13
Thanks: 4
Thanked 0 Times in 0 Posts
Default Using just a List

Assuming you read my obnoxiously long "Solution" post above, there is indeed no reason to keep track of the FileStream objects once you've instantiated the StreamReader objects.

The code becomes much more simple then. However notice the "dummy.txt" file need to create a dummy FileStream instance. Not a very clean solution, but I have no better one. :/

Code:
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.IO;


namespace learning_try_catch_filehandles {

    public partial class Form1 : Form {

        int max = 2;        // Number of files we're going to be looking at;

        List<StreamReader> FILES = new List<StreamReader>();

        FileStream tmp_stream;
        StreamReader tmp_reader;
        Dictionary<FileStream, StreamReader> tmp_dict;

        public Form1() {
            InitializeComponent();

            string filename;
            FileStream tmp_stream;
            StreamReader tmp_reader;

            // Initialize proper number of FILES elements  (see comment 1 below)
            tmp_stream = new FileStream(@"K:\data\dummy.txt", FileMode.Create);
            tmp_reader = new StreamReader(tmp_stream);
            for (int i = 0; i < max; ++i) {
                FILES.Add(tmp_reader);
            }

            // Now the ACTUAL files are put in place
            try {
                for (int i = 0; i < max; ++i) {
                    filename = @"K:\visual_studio\learning_try_catch_filehandles\learning_try_catch_filehandles\set" + i + ".txt";
                    tmp_stream = new FileStream(filename, FileMode.Open);
                    tmp_reader = new StreamReader(tmp_stream);
                    FILES[i] = tmp_reader;
                }
            } catch (IOException ex) {
                MessageBox.Show("Uhoh...\r\n" + ex.ToString());
            }

        }

        private void button2_Click(object sender, EventArgs e) {

            string row;
            for (int i = 0; i < max; ++i ) {

                    row = FILES[i].ReadLine();

                    while (row != null) {

                        row = row.Trim();
                        if (row == "") continue;                // Ignore blank lines

                        textbox.Text += row + "\r\n";
                        row = FILES[i].ReadLine();
                    }
                    textbox.Text += "\r\n";
            } 
        } 
        

    }// END class Form1
}
 
Old July 31st, 2012, 02:44 PM
Wrox Author
 
Join Date: Sep 2010
Posts: 175
Thanks: 3
Thanked 53 Times in 53 Posts
Default

Quote:
Originally Posted by KaneT View Post
Normally you would start with a blank array of proper size, and populate it later. Hence you may be tempted to write a line such as,
Code:
FileStream[] QUERYFILEHOOK = new FileStream()[3];
But this will generate an error
Of course this creates an error. You need to declare the array like this - here you create an array of 3 elements:
Code:
FileStream[] queryFileHook = new FileStream[3];
And then you can initialize the elements of the array:
Code:
queryFileHook[0] = fs1;
queryFileHook[1] = fs2;
queryFileHook[2] = fs3;
__________________
Christian
CN innovation
Visit my blog at: csharp.christiannagel.com
Follow me on twitter: @christiannagel
The Following User Says Thank You to ChristianNagel For This Useful Post:
KaneT (August 1st, 2012)
 
Old August 1st, 2012, 12:03 PM
Authorized User
 
Join Date: Jul 2012
Posts: 13
Thanks: 4
Thanked 0 Times in 0 Posts
Default

Quote:
Originally Posted by ChristianNagel View Post
Of course this creates an error. You need to declare the array like this - here you create an array of 3 elements:
Code:
FileStream[] queryFileHook = new FileStream[3];
And then you can initialize the elements of the array:
Code:
queryFileHook[0] = fs1;
queryFileHook[1] = fs2;
queryFileHook[2] = fs3;
Arrggh! No parenthesis! So tricky. :P

Thanks (again!) for catching my mistake (again!). :)





Similar Threads
Thread Thread Starter Forum Replies Last Post
HOW TO MAKE OBJECTS FLOW ojbrowser Visual Studio 2005 0 August 13th, 2008 06:50 AM
array of arrays-objects joker Java Basics 1 February 11th, 2007 09:12 PM
Assoc. Array of Objects hmmm PHP How-To 1 June 19th, 2006 11:38 AM
passing jagged array of objects nutrino Beginning VB 6 0 January 27th, 2006 11:58 AM
Dynamically Creating Objects of Array of Classes dinkarsinha General .NET 0 January 28th, 2005 06:22 AM





Powered by vBulletin®
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
Copyright (c) 2020 John Wiley & Sons, Inc.