Hello!

So I have a program where I need to open a file, pass the reader into a method, and then within the method read from the file. Then when control shifts out of the method, I need the file reader to be able to pick up where the method left off.

In c++ it would be something like this:

#include <fstream>
using namespace std;

int main()
{
     ifstream fin;
     fin.open("file.txt");
     readFile(fin);
     return 0;
}

void readFile(istream& in)
{
     int hold;
     in>>hold;
}

I'm having trouble figuring out what the parameter should be for the method in c#, like istream& out is in c++.

Thanks for any help!

Recommended Answers

All 13 Replies

Generally I don't get a lot of opportunity to work with filestream type controls because lately I've been doing more ASP.Net than straight up C# coding.

I did, however, find this forum post elsewhere that seems to cover much of the same issue you're asking about and seems to have come to some roundabout answers that might solve your problem.

Hope it helps :)

Hmmm, That's not quite what I was looking for. I know how to read from a file, but what I don't know is how to pass that reader into a method...I don't know what the type should be.

It's almost exactly the same. All the "reader" and "writer" objects have a base stream. You can pass that stream to another method, just like you would in C++.

static void Main(string[] args)
        {
            Stream myStream = File.Open("PathToMyFile", FileMode.Open);
            ReadTextFile(myStream);
            ReadBinaryFile(myStream);
            Console.ReadLine();
        }

        static void ReadTextFile(Stream myStream)
        {
            StreamReader streamReader = new StreamReader(myStream);
            Console.WriteLine(streamReader.ReadLine());
        }

        static void ReadBinaryFile(Stream myStream)
        {
            BinaryReader binaryReader = new BinaryReader(myStream);
            Console.WriteLine("My Int Was: " + binaryReader.ReadInt32());
        }

Obviously the code up there is pretty daft, as you wouldn't read a text file and then have binary in the same text file...But it does demonstrate that you can use the same base stream for both class types.

Thanks! That sort of works...the only problem now is that it will correctly read from the file the first time it goes through the method, then when it goes through a second time it reads in null instead of a value from the file. Here's what I've got:

Stream fin = File.Open("Bionics.txt", FileMode.Open);
            TextReader file = new StreamReader(fin);

            for (int ct = 0; ct < 4; ct++)
            {
                metal[ct].setBionic(fin);
            }

            fin.Close();

Where setBionic is this:

public void setBionic (Stream fin)
        {
            TextReader read = new StreamReader(fin);
            name = read.ReadLine();
            Aname = read.ReadLine();
            string hold = read.ReadLine();
        }

Why does it only read the first time through?

While I'm seeing the close of the "fin" stream I'm not seeing the close of the "read" stream.

My guess here is that it may be possible that your "read" stream is picking up where it left off instead of starting at the top of the stream again when called subsequent to the first pass.

I could be wrong though :)

That's what I thought, too. So I added the read.close(); at the end of setBionic, but then instead of not reading anything from the file the second time, it said the stram was unreadable when the program tried to execute the
TextReader read = new StreamReader (fin);

Hmm... Now I'm confused lol... and the difficulty is that you declare the reader within the 2nd function so it can't be managed from outside that function.

What I might recommend is that you take

TextReader read = new StreamReader(fin);

and declare it just below the fin stream instead of inside it's function. Then change the process for the 2nd read to read

public void setBionic ()
    {
        name = read.ReadLine();
        Aname = read.ReadLine();
        string hold = read.ReadLine();
    }

Also, what are you doing with "string hold"? because it's declared in the function but never used and the function is set to return "void" so "hold" seems to be redundant unless it's just a placeholder to cause a 3rd ReadLine.

In the end the new code segment to match your top segment would be:

Stream fin = File.Open("Bionics.txt", FileMode.Open);
TextReader file = new StreamReader(fin);
TextReader read = new StreamReader(fin);

for (int ct = 0; ct < 4; ct++)
{
    metal[ct].setBionic(fin);
}

read.Close();
fin.Close();

Of course, now I'm thoroughly confused however as to why you have a need for 2 readers for the same file... unless you have multiple calls to multiple files being handled with the 2nd process there.

The problem is that the 2nd reader is being called repetatively within a loop from the first function without ever closing afterward. Alternately if you need the 2nd reader's properties (fin) to be determined dynamically from outside the property you could still declare the reader for "read" outside of the function (globally) as a generic reader and assign the property (fin) within the function.

I hope I haven't completely made a mess of this for you :P

Anything you do that involves the base stream is reflected across anything that uses that stream.

So if you read a line of text in one method and in the next method read another line of text. The base stream has already moved up by a line and the second method would read from the second line.

When you create a new object of TextReader with the base stream, TextReader has all the properties of the current base stream.

(So if you call TextReader.Close() you're actually closing the base stream)

To be perfectly honest, I can't see anything wrong with your original code. Could you please attach the text file you are using and I'll run through it myself.

Maybe I just wasn't clarifying what I was trying to say (I've been awake way too many hours the past few days)...

Basically my interpretation of the problem was that the process in the first code segment was being called more than once and... when called the first time, worked as intended. When called subsequent times, it was intended to replicate the results of the first call but didn't.

My read into the cause of this is that the streamreader for the enclosed loop never closes and never resets to line 0 of the stream so in subsequent calls it basically does the following:

First call (line 0, 1, 2)
Second call (line 3, 4, 5)

and so forth.

I could be interpreting the situation completely incorrectly tho.

I doubt that's what he wants to be honest. But even so he would have to re-open the initial base stream every call, or, perform a seek to the beginning of the file.

I doubt that's what he wants to be honest. But even so he would have to re-open the initial base stream every call, or, perform a seek to the beginning of the file.

Actually, re-reading the original post...

It looks more like he wants to do the following:

Open file in reader -> Pass to function

In function: read line 1 to variable -> read line 2 to variable -> read line 3 just to set position in file -> pass back out of function

outside function: continue from file position and perform further tasks.

So ya, looks like I completely butchered it hehe... That's what I get for being over-tired and under-rested :yawn:

Actually I missed something glaringly obvious. Garbage Collection....

You're creating a new object that uses the base stream. That object is then dispose at the end of the method. Setting the position of the Stream to the end of the file. The stream still exists, but it's at the end of the file and therefore, won't read any more data.

You can however, use the base stream itself to read the data, it's just a bit more complicated ;)

Wow...I could have sworn I tried that When I was first trying to figure this out. Well, I managed to solve the problem not using the stream class directly, but instead the derived StreamReader, and having the type of the parameter StreamReader. I thought I tried that already, but I guess not...it works!!! Here's the code if anyone's interested :)

StreamReader fin = new StreamReader("Bionics.txt");
            count = int.Parse(fin.ReadLine());

            for (int ct = 0; ct < count; ct++)
            {
                metal[ct].setBionic(fin);
            }

            fin.Close();

where setBionic is:

public void setBionic (StreamReader read)
        {
            name = read.ReadLine();
            Aname = read.ReadLine();
            string hold = read.ReadLine();
            string[] line = hold.Split(' ');
        }

Thanks so much for everyone's help!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.