QFile is not reading nor opening my file - c++

I have a file called "sequence_30.dat" that contains a sequence of 1 and -1 in a vertical representation (i.e.: each 1 or -1 is in a separate line) .. I am trying to read the file for another operation using the following code:
int length = 31
QFile file("sequence_"+ (static_cast<QString>(length)) +".dat");
if(file.exists()){
file.open(QIODevice::ReadOnly);
if(file.isOpen()){
....
....
}
file.close();
}
but when debugging, the compiler skips the "if(file.exists())" statement and when it is removed the compiler again skips the "if(file.isOpen())" statement
I am very sure that path is correct, but if is not how to make sure that I am in the right path (i.e.: is there is a way to check where am I reading from) .. and if the path is correct why my file is not opening ?

static_cast<QString>(length)
Should be:
QString::number( length )
You can check it by just printing it out to the console:
cout << qPrintable( QString( "sequence_" ) +
QString::number( length ) + ".dat" ) << endl;

static_cast doesn't work that way, so instead of a static_cast, you should use QString::number to convert an int into a QString.

Related

Is there a way to request a certain location of a text file to be read in C++?

I'm using a text file which is in two lines. Each line has several thousand numbers on it (signed doubles). So it would look like this:
X.11 X.12 X.13 ...
X.21 X.22 X.23 ...
For each loop of my program I want to read one number from each line. So for the first iteration of the loop it would be X.11 & X.21 and for the second iteration X.12 & X.22 and so on. I don't need to store the values.
the expected output:
X.11 X.21
X.12 X.22
X.13 X.23
How can this be done in C++?
I usually read files using fstream, and reading the file line-by-line with std::getline(file, line). How would I read one number from each line?
I don't need to store the values.
Sure, but if you did, say in two arrays of doubles, then your loop would be trivial, and much faster than regular disk reads. And two arrays of several thousand doubles is probably less memory usage than you think it is. 1 Mb of RAM can contain 131072 eight byte doubles.
I assume you need: I want to read one number from each line.
otherwise comment me; I will delete the answer.
Read the file with 2 streams in parallel:
std::ifstream input_file_stream_1( "file" );
std::ifstream input_file_stream_2( "file" );
std::string line_1;
std::string line_2;
std::string ignore;
std::getline( input_file_stream_2, ignore ); // ignore the whole first line
for( ; input_file_stream_1 >> line_1 && input_file_stream_2 >> line_2; ){
std::cout << line_1 << " and " << line_2 << '\n';
}
input_file_stream_1.close();
input_file_stream_2.close();
the input:
X.11 X.12 X.13 ...
X.21 X.22 X.23 ...
the output:
X.11 and X.21
X.12 and X.22
X.13 and X.23
... and ...
how it works?
Since your file only has 2 lines, so I used two input_stream over the same file. One of them for the first line and the other for the second line. But before going to for-loop. the input_file_stream_2 reads the first line and no need to use that since the input_file_stream_1 wants to read this. So after ignore that line ( first line ). The input_file_stream_1 has line 1 and input_file_stream_2 has line 2. Now you have two lines with to streams. And in the for loop, ( or while ) you can extract each text by >> operator
or with std::regex library:
std::ifstream input_file_stream( "file" );
std::string line_1;
std::string line_2;
std::getline( input_file_stream, line_1 );
std::getline( input_file_stream, line_2 );
std::regex regex( R"(\s+)" );
std::regex_token_iterator< std::string::iterator > begin_1( line_1.begin(), line_1.end(), regex, -1 ), end_1;
std::regex_token_iterator< std::string::iterator > begin_2( line_2.begin(), line_2.end(), regex, -1 ), end_2;
while( begin_1 != end_1 && begin_2 != end_2 ){
std::cout << *begin_1++ << " and " << *begin_2++ << '\n';
}
input_file_stream.close();
the output:(as the same above)
X.11 and X.21
X.12 and X.22
X.13 and X.23
... and ...
NOTE:
There is more than one way to this
If you have already read the line using std::getline(file, line), you can take the string you got, and tokenize it char* p = strtok (yourline, " "); and then *p would result X.11 in the first line, and for the next one you just call strtok again
For an fstream you can use tellg and seekg to store and restore the position in the stream. However, I haven't verified that they work well together with formatted input.
Assuming you don't want to store the result in memory and it is only two lines another solution would be to open the file twice - and treat it as if you were reading the lines from two different files.

QT, Write in new line in a file

I have written a code to read from line_Edit in GUI, and write in a file. The code reads the text from line edit and writes the same in the file, but they are printed continuously without any spaces, I want to print the texts written in the line edit in different lines. The file has written text, just want to replace first word of each line by the user entered words.
Code to write in the file:
void MainWindow::on_write_btn_clicked(){
QString str, str2, lin;
str = ui->lineEdit->text();
str2 = ui->lineEdit2->text();
QFile file1("sample.txt");
if(file1.open(QIODevice::ReadWrite | QIODevice::Text)){
QTextStream out(&file1);
out << str;
lin = out.readLine();
out << str2;
file1.seek(30);
file1.close();
}
else
return;
}
File in which we want to write:
If you want the next string to be in a new line in the file you should add the new line character(s) to the stream \n.
Referring to your code you should put:
out << str << '\n' << str2;
which would make the contents of str and str2 appear in consecutive lines.
Instead of the above you could also use the endl manipulator from QTextStream:
out << str << endl << str2;
For this to work properly you need to be opening the file with QIODevice::Text and assure that the endl you are specifying actually comes from QTextStream (not std)
Also note that since you probably only want to write your file there is no need in opening it with ReadWrite option, WriteOnly should be enough.
EDIT according to further details:
To substitute first word from each line of the file you could do the following. Open two files, one which will be read and the second to write the modified data. After iterating though all the lines close the files, remove the original one and rename the output file to replace the original one. Sample implementation:
QFile fileIn("textIn.txt"), fileOut("textOut.txt");
fileIn.open(QFile::ReadOnly); // check result
fileOut.open(QFile::WriteOnly); // check result
QTextStream streamIn(&fileIn), streamOut(&fileOut);
const QChar delimeter = ' ';
while (!streamIn.atEnd())
{
QStringList list = streamIn.readLine().split(delimeter);
if (list.size() > 0) // in case of empty line
list[0] = "substitutedText"; // here put the text you want to set
streamOut << list.join(delimeter) << "\r\n"; // or endl
}
fileIn.close();
fileOut.close();
fileIn.remove(); // check result
fileOut.rename(QFileInfo(fileIn).absoluteFilePath()); // check result
Of course you could try doing the replacement on the original file opened with ReadWrite modifier and setting proper position inside the stream using seek. Although it could get tricky due to different lengths of the read and written data.

C++ reading a file in binary mode. Problems with END OF FILE

I am learning C++and I have to read a file in binary mode. Here's how I do it (following the C++ reference):
unsigned values[255];
unsigned total;
ifstream in ("test.txt", ifstream::binary);
while(in.good()){
unsigned val = in.get();
if(in.good()){
values[val]++;
total++;
cout << val <<endl;
}
}
in.close();
So, I am reading the file byte per byte till in.good() is true. I put some cout at the end of the while in order to understand what's happening, and here is the output:
marco#iceland:~/workspace/huffman$ ./main
97
97
97
97
10
98
98
10
99
99
99
99
10
100
100
10
101
101
10
221497852
marco#iceland:~/workspace/huffman$
Now, the input file "test.txt" is just:
aaaa
bb
cccc
dd
ee
So everything works perfectly till the end, where there's that 221497852. I guess it's something about the end of file, but I can't figure the problem out.
I am using gedit & g++ on a debian machine(64bit).
Any help help will be appreciated.
Many thanks,
Marco
fstream::get returns an int-value. This is one of the problems.
Secondly, you are reading in binary, so you shouldn't use formatted streams. You should use fstream::read:
// read a file into memory
#include <iostream> // std::cout
#include <fstream> // std::ifstream
int main () {
std::ifstream is ("test.txt", std::ifstream::binary);
if (is) {
// get length of file:
is.seekg (0, is.end);
int length = is.tellg();
is.seekg (0, is.beg);
char * buffer = new char [length];
std::cout << "Reading " << length << " characters... ";
// read data as a block:
is.read (buffer,length);
if (is)
std::cout << "all characters read successfully.";
else
std::cout << "error: only " << is.gcount() << " could be read";
is.close();
// ...buffer contains the entire file...
delete[] buffer;
}
return 0;
}
This isn't the way istream::get() was designed to be used.
The classical idiom for using this function would be:
for ( int val = in.get(); val != EOF; val = in.get() ) {
// ...
}
or even more idiomatic:
char ch;
while ( in.get( ch ) ) {
// ...
}
The first loop is really inherited from C, where in.get() is
the equivalent of fgetc().
Still, as far as I can tell, the code you give should work.
It's not idiomatic, and it's not
The C++ standard is unclear what it should return if the
character value read is negative. fgetc() requires a value in
the range [0...UCHAR_MAX], and I think it safe to assume that
this is the intent here. It is, at least, what every
implementation I've used does. But this doesn't affect your
input. Depending on how the implementation interprets the
standard, the return value of in.get() must be in the range
[0...UCHAR_MAX] or [CHAR_MIN...CHAR_MAX], or it must be EOF
(typically -1). (The reason I'm fairly sure that the intent is
to require [0...UCHAR_MAX] is because otherwise, you may not
be able to distinguish end of file from a valid character.)
And if the return value is EOF (almost always
-1), failbit should be set, so in.good() would return
false. There is no case where in.get() would be allowed
to return 221497852. The only explication I can possibly think
of for your results is that your file has some character with
bit 7 set at the end of the file, that the implementation is
returning a negative number for this (but not end of file,
because it is a character), which results in an out of bounds
index in values[val], and that this out of bounds index
somehow ends up modifying val. Or that your implementation is
broken, and is not setting failbit when it returns end of
file.
To be certain, I'd be interested in knowing what you get from
the following:
std::ifstream in( "text.txt", std::ios_base::binary );
int ch = in.get();
while ( ch != std::istream::traits_type::eof() ) {
std::cout << ch << std::endl;
ch = in.get();
}
This avoids any issues of a possibly invalid index, and any type
conversions (although the conversion int to unsigned is well
defined). Also, out of curiosity (since I can only access VC++
here), you might try replacing in as follows:
std::istringstream in( "\n\xE5" );
I would expect to get:
10
233
(Assuming 8 bit bytes and an ASCII based code set. Both of
which are almost, but not quite universal today.)
I've eventually figured this out.
Apparently it seems the problem wasn't due to any code. The problem was gedit. It always appends a newline character at the end of file. This also happen with other editors, such as vim. For some editor this can be configured to not append anything, but in gedit this is apparently not possible. https://askubuntu.com/questions/13317/how-to-stop-gedit-gvim-vim-nano-from-adding-end-of-file-newline-char
Cheers to everyone who asked me,
Marco

remove not working properly ? ( of std namespace)

Through this snippet i try to remove a certain file from a directory. Here is the code for that.
/* char* cpathToDeleteGND;
char* cpathToDeleteFST;
char* cpathToDeleteSND;
*/
cout << "Enter the name to be removed : ";
cin.ignore();
getline( cin , fullName );
string pathToDeleteGND = "d:/HostelManager/studentDetails/groundFloor/" + fullName + ".txt";
string pathToDeleteFST = "d:/HostelManager/studentDetails/firstFloor/" + fullName + ".txt";
string pathToDeleteSND = "d:/HostelManager/studentDetails/secondFloor/" + fullName + ".txt";
ifstream checkToDeleteGND( pathToDeleteGND );
ifstream checkToDeleteFST( pathToDeleteFST );
ifstream checkToDeleteSND( pathToDeleteSND );
cpathToDeleteGND = new char[ pathToDeleteGND.size() + 1 ];
cpathToDeleteFST = new char[ pathToDeleteFST.size() + 1 ];
cpathToDeleteSND = new char[ pathToDeleteSND.size() + 1 ];
strcpy( cpathToDeleteGND , pathToDeleteGND.c_str() );
strcpy( cpathToDeleteFST , pathToDeleteFST.c_str() );
strcpy( cpathToDeleteSND , pathToDeleteSND.c_str() );
if( checkToDeleteGND ) {
if( remove( cpathToDeleteGND) == 0 ) {
cout << "\nStudent details cleared successfully !";
}
} else if( checkToDeleteFST) {
if( remove( cpathToDeleteFST) == 0 ) {
cout << "\nStudent details cleared successfully ! ";
}
} else if( checkToDeleteSND ) {
if( remove( cpathToDeleteSND) == 0 ) {
cout << "\nStudent details cleared successfully !";
}
} else {
cout << "\nIt seems that either the student has already been removed or does not exist.";
}
I give the name that should be removed from the directory.Though the if else blocks work but the remove function does not work. I can't understand the reason ..
For example , the output goes like :
Enter the name to be removed : diana
Press any key to continue . . .
The file diana.txt existed that's why it didn't execute the last else block . But the remove function does not work. Why is that ?
The file diana.txt existed that's why it didn't execute the last else block . But the remove function does not work. Why is that?
You don't know because you only print a message if remove succeeds. Try:
if (remove(pathToDeleteFST.c_str()) == 0) {
// success, print something
} else {
// failure, much more interesting
cout << "Can't remove " << pathToDeleteFST << ": "
<< strerror(errno) << endl;
}
errno is in errno.h, strerror in string.h.
(Instead of opening the file to check whether it exists, you could also charge ahead and try to remove it. As #n.m. notes, that may even be necessary on Windows.)
You open the file before deleting it. Windows won't delete files which are open by someone. Do not check for existence of a file by opening it, use stat or just call remove without checking.
This is a very old question but may still be relevant for people who come across this looking for a solution.
The reason this particular example can't delete the file properly is because the files to be deleted are currently being used by the code inside of the iftream variables for each.
Before you can remove and files, you must first .close() them.
If you are having trouble with deleting files that you've previously loaded via fstream, ensure that you have properly closed them before trying to use the remove function.
Hope this helps.
There are a couple of issues with your code, but the probable reason
remove fails is that the file is open; Windows will not delete an open
file. You should probably refactor a lot of this into separate
functions. If you used a function like the following, for example:
bool
fileExists( std::string const& filename )
{
return std::ifstream( filename.c_str() );
}
, the problem wouldn't occur. There are other reasons why the open
might fail, but this is a good rough first approximation. (There are
better ways of testing the existance of a file, but they are system
dependent.)

C++ program snippet: what is this doing?

I'm trying to figure out how to output hOCR using Tesseract. Documentation is limited, so I am looking into the code. I found this in the main() function:
bool output_hocr = tessedit_create_hocr;
outfile = argv[2];
outfile += output_hocr ? ".html" : tessedit_create_boxfile ? ".box" : ".txt";
A typical command for Tesseract is this: tesseract input.tif output_file.txt (the output file will be appended with another .txt in this example). main()'s signature is int main(int argc, char **argv).
What exactly is the code snippet doing?
It's generating the output filename.
bool output_hocr = tessedit_create_hocr;
Saves the tessedit_create_hocr flag in a locally scoped variable.
outfile = argv[2];
Initializes the outfile variable with the base filename from the command line. Something like "Scann0000.tif".
outfile += output_hocr ? ".html" : tessedit_create_boxfile ? ".box" : ".txt";
Appends the appropriate extension based on flags. Could be re-written as
if( ouput_hocr )
outfile += ".html";
else if( tessedit_create_boxfile )
outfile += ".box";
else
outfile += ".txt";
It's taking a base filename from the second command-line argument (output_file.txt in your example) then choosing the extension with the ternary operator.
If output_hocr, ".html"
Otherwise, if tessedit_create, ".box"
Otherwise, ".txt"
Note that this is C++.
If the output_hocr variable is true it appends ".html" to outfile.
If it is false it checks tessedit_create_boxfile if it is true, it appends ".box" to outfile, otherwise it appends ".txt".
This code is just deciding what file extension to give outfile based on the value of tessedit_create_hocr (it is unclear how or where this variable is initialized given the code snippet provided).
If the value is true, the program will name the output file ".html". Otherwise, it will be ".box" or ".txt", depending on the value of tessedit_create_boxfile (it is also unclear where this is initialized).