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.
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).
Related
I'm trying to dump the contents of a file to cout.
#include <iostream>
#include <fstream>
int main(int argc, char** argv)
{
if (argc > 1) {
std::ifstream fin(argv[1]);
if (fin) {
std::cout << "---file contents---\n";
std::cout << fin.rdbuf();
std::cout << "---end contents---\n";
} else {
std::cout << "The file does not exist\n";
}
}
else {
std::cout << "Usage: " << argv[0] << " FILE\n";
}
if (std::cout.good()) {
return 0;
}
else if (std::cout.fail()) {
return 1;
}
else {
return 2;
}
}
This code does not work as intended when the input file is empty. It prints the initial "---file contents---", but never prints the trailing "---end contents---". After debugging, I found the application is not crashing, but instead is putting std::cout in an error state (the return code is 1).
How can I print the contents of an empty file without putting cout in an error state?
This operator<< reference (overload number 10 in the list) explains it all:
If no characters were inserted, executes setstate(failbit).
Since the input file is empty, there's no characters to insert into the output stream. And the failbit is set.
You need to add a specific check for failbit after
std::cout << fin.rdbuf();
to see if the input file was empty or not.
For my formation, an exercise ask us to create a program similar to the linux 'cat' command.
So to read the file, i use an ifstream, and everything work fine for regular file.
But not when i try to open /dev/ files like /dev/stdin: the 'enter' is not detected and so, getline really exit only when the fd is being closed (with a CTRL-D).
The problem seems to be around how ifstream or getline handle reading, because with the regular 'read' function from libc, this problem is not to be seen.
Here is my code:
#include <iostream>
#include <string>
#include <fstream>
#include <errno.h>
#ifndef PROGRAM_NAME
# define PROGRAM_NAME "cato9tails"
#endif
int g_exitCode = 0;
void
displayErrno(std::string &file)
{
if (errno)
{
g_exitCode = 1;
std::cerr << PROGRAM_NAME << ": " << file << ": " << strerror(errno) << std::endl;
}
}
void
handleStream(std::string file, std::istream &stream)
{
std::string read;
stream.peek(); /* try to read: will set fail bit if it is a folder. */
if (!stream.good())
displayErrno(file);
while (stream.good())
{
std::getline(stream, read);
std::cout << read;
if (stream.eof())
break;
std::cout << std::endl;
}
}
int
main(int argc, char **argv)
{
if (argc == 1)
handleStream("", std::cin);
else
{
for (int index = 1; index < argc; index++)
{
errno = 0;
std::string file = std::string(argv[index]);
std::ifstream stream(file, std::ifstream::in);
if (stream.is_open())
{
handleStream(file, stream);
stream.close();
}
else
displayErrno(file);
}
}
return (g_exitCode);
}
We can only use method from libcpp.
I have search this problem for a long time, and i only find this post where they seems to have a very similar problem to me:
https://github.com/bigartm/bigartm/pull/258#issuecomment-128131871
But found no really usable solution from them.
I tried to do a very ugly solution but... well...:
bool
isUnixStdFile(std::string file)
{
return (file == "/dev/stdin" || file == "/dev/stdout" || file == "/dev/stderr"
|| file == "/dev/fd/0" || file == "/dev/fd/1" || file == "/dev/fd/2");
}
...
if (isUnixStdFile(file))
handleStream(file, std::cin);
else
{
std::ifstream stream(file, std::ifstream::in);
...
As you can see, a lot of files are missing, this can only be called a temporary solution.
Any help would be appreciated!
The following code worked for me to deal with /dev/fd files or when using shell substitute syntax:
std::ifstream stream(file_name);
std::cout << "Opening file '" << file_name << "'" << std::endl;
if (stream.fail() || !stream.good())
{
std::cout << "Error: Failed to open file '" << file_name << "'" << std::endl;
return false;
}
while (!stream.eof() && stream.good() && stream.peek() != EOF)
{
std::getline(stream, buffer);
std::cout << buffer << std::endl;
}
stream.close();
Basically std::getline() fails when content from the special file is not ready yet.
ifstream read;
read.open(name);
char g[3];
read.getline(g,3);
char v = read.get();
cout << v;
read.close();
the issue i'm having is that after the getline function, the get is set to garbage and the file doesn't read properly anymore. However im sure that the file im reading contains more characters than getline takes, so what is issue?
Did you check that the read worked?
When you use a read always check the read worked before using the value:
if (read.getline(g,3)) {
// Read worked correctly
std::cout << "Got: >" << std::string(g, read.gcount()) << "<\n";
}
else {
std::cerr << "Read Failed\n";
throw "Failed";
}
if ((v = read.get()) != EOF) {
std::cout << "Got: >" << v << "<\n";
}
else {
std::cerr << "Read Failed\n";
throw "Failed";
}
Read file by std::fstream:
std::string str;
std::fstream file = "test.txt";//write in text.txt: GhY67. Test.
while(getline(file, str))//while get line of test.txt file,
// saves
// line in str string.
{
std::cout << str << '\n';
//Outputs str string(all lines in test.txt document)
}
If your wish always input characters, write this code:
std::string str;
while(getline(std::cin, str))//while getline in console, user
//inputs characters and characters in onr line saves in str
//string.*
{
if(str == "What?")
{
std::cout << "Hello, world!";
//*If user inputs string "What?", console outputs
string "Hello, world!*/
}
}
I have written a small C++ program to set a property in a text file. The implementation is as following:
#include <cstdio>
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
const string PROPFILE = "./propfile";
const string TEMPFILE = PROPFILE + ".tmp";
int setProp(const string &key, const string &val) {
try {
ifstream original(PROPFILE, ios::in);
ofstream tempfile(TEMPFILE, ios::out | ios::trunc);
for (string line; getline(original, line); ) {
if (line.compare(0, key.size(), key) == 0 && line[key.size()] == '=') {
tempfile << key << '=' << val << endl;
} else {
tempfile << line << endl;
}
}
cout << "original.rdstate()" << original.rdstate() << endl;
original.close();
tempfile.close();
} catch (ifstream::failure e) {
cerr << e.what() << endl;
}
if (rename(TEMPFILE.c_str(), PROPFILE.c_str()) != 0) {
cout << "Could not move " + TEMPFILE << "to " << PROPFILE << endl;
return 1;
}
return 0;
}
int main(int argc, const char *argv[]) {
try {
return setProp(argv[1], argv[2]);
} catch (logic_error) {
cout << "Invalid args" << endl;
return 1;
}
}
However, when I try to compile and execute it from commandline via ./a.out TESTPROP TESTVALUE, the value IS set as expected in propfile but rdstate() returns 6 (which means failbit and eofbit are set), I can't understand why are they getting set, can somebody explain ?
Contents of propfile before running ./a.out TESTPROP TESTVALUE are:
TESTPROP=NOTHING
After running the progam:
TESTPROP=TESTVALUE
I'm just a student, please don't mind if it's a dumb question :)
This is expected behaviour, the failbit is set whenever there is a failure to read the expected value. Even if that failure is because of end of file.
For instance see here
If no characters were extracted for whatever reason (not even the
discarded delimiter), getline sets failbit and returns.
I want to read data from a txt file, but i am not able to get it. I am new to c++.
Here is my code, but it does not work. I used getline(),
ifstream inFile;
string sPassWord;
inFile.open("QdatPassWordconfig.config");
inFile.seekg(0,ios::end);
int length=inFile.tellg();
if (inFile.is_open())
{
while (!inFile.eof())
{
getline(inFile,sPassWord);
cout<<sPassWord<<endl;
}
cout<<"get data from txt file"<<endl;
// here ,I cannot read data from file
cout<<sPassWord<<endl;
}
if(!inFile.is_open() || length==0)
{
cout<<"file is create or write"<<endl;
sPassWord="BdsWUjT26";
ofstream outFile;
outFile.open("QdatPassWordconfig.config");
outFile<<sPassWord<<endl;
outFile.close();
}
inFile.close();
cout<<sPassWord<<endl;
It isn't clear if you are trying to read the first line of the file, the last line of the file, or all the lines of the file. Here program snippets for each possibility:
To read the first line of the file:
// UNTESTED
{
ifstream inFile("QdatPassWordconfig.config");
string sPassWord;
if(std::getline(inFile, sPassWord)) {
std::cout << "Password is: " << sPassWord << "\n";
} else {
std::cout << "No password available.\n"
}
}
To read all of the lines of the file:
// TESTED
#include <iostream>
#include <fstream>
#include <string>
int main ()
{
std::ifstream inFile("QdatPassWordconfig.config");
std::string sPassWord;
while(std::getline(inFile, sPassWord)) {
std::cout << "Password is: " << sPassWord << "\n";
}
}
To read the last line of the file:
// UNTESTED
{
ifstream inFile("QdatPassWordconfig.config");
string sPassWord;
int lineCount = 0;
while(std::getline(inFile, sPassWord)) {
lineCount++;
}
if(lineCount) {
std::cout << "Password is: " << sPassWord << "\n";
} else {
std::cout << "No password available.\n";
}
}
inFile.seekg(0,ios::end);
int length=inFile.tellg();
1.You forgot seek back to the beginning. Like this:
inFile.seekg(0,ios::end);
int length=inFile.tellg();
inFile.seekg(0,ios::beg);
2.You need to practice on your if and else statement.
3.Don't use std::ifstream::eof. Use std::getline.
Do something like this:
// Declare local variables
std::ifstream inFile;
std::string sPassword = "";
::UINT length = 0;
// Attempt to open file
inFile.open( "QdatPassWordconfig.config" );
// Use your if and else statement like this:
// Is inFile open?
if( inFile.is_open( ) )
{
// Read file line by line using std::getline
while( std::getline( inFile, sPassword ) ) {
// Print sPassword
std::cout << sPassword << std::endl;
}
// Done with inFile, close it
inFile.close( );
}
else
{
// Do whatever if inFile can't be open
}
There are so many errors with your code, so I decided to show you how I would have done it (please do read the comments):
void Example( void )
{
// DECLARATION
bool bInputMode = true;
std::fstream ioFile;
::UINT nFileSize = 0;
std::string strPassword = "";
// INITIALIZATION
// *Open or create ioFile
// ioFile can now do both input and output operations
ioFile.open( "Passwords.pw",
std::fstream::in |std::fstream::out | std::fstream::app );
// *Calculate/set the value of bInputMode
// first, calculate the size of the file
// if the size of the file is = 0,
// bInputMode = false - which means to be in output mode
ioFile.seekg( 0, std::ios::end );
if( ( nFileSize = ioFile.tellg( ) ) = 0 )
bInputMode = false;
ioFile.seekg( 0, std::ios::beg );
// DO WHATEVER
// *Since bInputMode == true,
// we shall read each line from ioFile by using std::getline
if( bInputMode )
{
// *Get each line within ioFile and "copy" it to strPassword
// and then print strPassword
// *With std::getline, we could get the spaces
while( std::getline( ioFile, strPassword ) )
std::cout << strPassword << std::endl;
}
// *Since bInputMode == false,
// we shall create a new from ioFile and then write to it
else
{
std::cout << "Creating/writing a new file..." << std::endl;
strPassword = "Password123";
ioFile << strPassword << std::endl;
}
// CLEAN-UP
// We are done with ioFile, close it.
ioFile.close( );
};
Please point out any errors! Some feedback and suggestions would be great as well.