SJWard
SJWard

Reputation: 3759

Creating a class with an open file stream

I've created a class which is supposed to read in DNA sequences: It contains an if stream private member:

Interface:

class Sequence_stream {
    const char* FileName;
    std::ifstream FileStream;
    std::string FileFormat;

public:
    Sequence_stream(const char* Filename, std::string Format);
    NucleotideSequence get();
};

Implementation:

Sequence_stream::Sequence_stream(const char* Filename, std::string Format)
{
    FileName = Filename;
    FileStream.open(FileName);
    FileFormat = Format;
    std::cout << "Filestream is open: " << FileStream.is_open() << std::endl;
}

NucleotideSequence Sequence_stream::get()
{
    if (FileStream.is_open())
    {
        char currentchar;
        int basepos = 0;
        std::string name;
        std::vector<Nucleotide> sequence;
        currentchar = FileStream.get();
        if (currentchar == '>' && false == FileStream.eof()) {  // Check that the start of the first line is the fasta head character.
            currentchar = FileStream.get(); // Proceed to get the full name of the sequence. Get characters until the newline character.
            while(currentchar != '\n' && false == FileStream.eof())
            {
                if (true == FileStream.eof()) {
                    std::cout << "The file ends before we have even finished reading in the name. Returning an empty NucleotideSequence" << std::endl;
                    return NucleotideSequence();
                }
                name.append(1, currentchar);
                currentchar = FileStream.get();
            } // done getting names, now let's get the sequence.
            currentchar = FileStream.get();
            while(currentchar != '>' && false == FileStream.eof())
            {
                if(currentchar != '\n'){
                    basepos++;
                    sequence.push_back(Nucleotide(currentchar, basepos));
                }
                currentchar = FileStream.get();
            }
            if(currentchar == '>')
            {
                FileStream.unget();
            }
            return NucleotideSequence(name, sequence);
        } else {
            std::cout << "The first line of the file was not a fasta format description line beginning with '>'. Are you sure the file is of FASTA format?" << std::endl;
            return NucleotideSequence();
        }

    } else {
        std::cout << "The filestream is not open..." << std::endl;
        return NucleotideSequence();
    }
}

However if I test it:

int main()
{
    std::cout << "Let's try and read in a sequence!" << std::endl;
    std::cout << "First we'll create a stream!" << std::endl;
    Sequence_stream MyDNAStream("~/Dropbox/1_20dd5.fasta", "fasta");
    std::cout << "Done!" << std::endl;
    std::cout << "Now let's try and get a sequence!" << endl;
    NucleotideSequence firstsequence = MyDNAStream.get();
    return 0;
} 

I see that the if stream is not open:

Let's try and read in a sequence!
First we'll create a stream!
Filestream is open: 0
Done!
The filestream is not open...
logout

[Process completed]

Although I thought the constructor function opens the if stream. What do I need to do to correct this so as the object is created and contains an open stream? (I know I'm yet to include a destructor which will close the stream upon destruction of the object).

Thanks, Ben.

Upvotes: 0

Views: 1034

Answers (1)

R&#233;mi
R&#233;mi

Reputation: 116

Your example shows that is_open returned false. I think you should check in your constructor that the file is indeed open, and throw if not.

In your case, I suspect this is due to passing "~/Dropbox/1_20dd5.fasta" as an input parameter. Did you test with a full pathname, with no ~? I have no knowledge of a C++ library that handles real path expansion (like python's os.path).

Upvotes: 3

Related Questions