I have a ".dat" file that contains "1"s and "-1"s as a sequence in a vertical representation (i.e.: each element is in a single line.).
I am trying to read the file as follow:
char buf[30];
QFile sequence("Sequences.dat");
sequence.open(QFile::ReadOnly);
for(int sym=0; sym<29; sym++){
char c = symbols[sym] = sequence.readLine(buf,sizeof(buf));
symbols[sym] = c;
}
sequence.close();
however, the result is nothing like my sequence as seen below:
what did I did wrong ?
Check the readLine API doc: the return value is the number of bytes read, while the line is read into the buf array, which is overwritten at each iteration. Note that the first symbol of the inspected array is a '\0' (empty string), probably because the last line of your file is empty.
Related
I am new to c++ and am still figuring out file streams. I am trying to put a character array into a file that I will be viewing with a hex editor.
I have done different strings, but whenever I put in a null byte, the file ends.
ofstream stream;
char charArray[256];
for (int i = 0; i <= 255; i++)charArray[i] = i;
stream.open("C:\\testfile.myimg");
if (!stream.is_open()) exit(1);
stream << charArray << endl;
return 0;
I want to output bytes with ascending values, but if I start with the null byte, then c++ thinks the character array ends before it starts
Instead of:
stream << charArray << endl;
use:
stream.write(charArray, sizeof(charArray));
stream.write("\n", 1); // this is the newline part of std::endl
stream.flush(); // this is the flush part of std::endl
The first one assumes that you are sending a null-terminated string (because you're passing a char* - see the end of the answer why). That's why when the code encounters the very first char with value 0, which is '\0' (the null-terminator), it stops.
On the other hand, the second approach uses an unformatted output write, which will not care about the values inside charArray - it will take it (as a pointer to its first element) and write sizeof(charArray) bytes starting from that pointer to the stream. This is safe since it's guaranteed that sizeof(char) == 1, thus sizeof(charArray) will yield 256.
What you need to consider is array decaying. It will work in this case (the sizeof thing), but it will not work if you simply pass a decayed pointer to the array's first element. Read more here: what's array decaying?
I'm using a function that reads a spooled file and sets a buffer with the output.
The function returns OK state and sets readBytes correctly. It also notifies that the reading operation has reached the end of the file.
char* splFileContent = new char[3000];
ULONG readBytes;
int z = cwbOBJ_ReadSplF(splFile, splFileContent, 500, &readBytes, 0);
//z value is REACHED END OF FILE or OK if read but didn't reach the end of the file.
The trouble comes when trying to convert the char buffer to string, I'm getting "4Ä" as string value...
I convert the char buffer to string this way:
stringstream s;
s << splFileContent;
string bufferContent = s.str();
What I'm doing wrong?
It looks like splFileContent is binary content and not printable characters.
The start of the file may contain a BOM of some sort, e.g. unicode indicator. If it is, you should read in the BOM first and then the rest of the file.
Note: unless the file read function here adds a NULL, be sure to append one as well.
I am trying to find a string in the given file (actually the file is tar file(please pay attention here) and i opened the file in notepad++ and took randomly a string from that opened file) and i stored that full tar file in a buffer and now i want to find the position of the string i copied using strstr function in the stored buffer.
The code to do is this(which is absolutely correct)-
char *compare= "_.png"; //suppose this is the copied string
//which is to be find out in buffer using strstr
char * StartPosition;
StartPosition = strstr (buffer,compare);
__int64 count=0;
MessageBox(m_hwndPreview,L"before the while loop",L"BTN WND6",MB_ICONINFORMATION);
while (StartPosition!=NULL)
{
MessageBox(m_hwndPreview,L"hurr inside the while loop",L"BTN WND6",MB_ICONINFORMATION);
MessageBoxA(m_hwndPreview,strerror(errno),"BTN WND4", MB_ICONINFORMATION);
count=StartPosition-buffer+1;
return 0;
}
and suppose if i have content of tar file in notepad like as below from where i copied this string stored in compare-
3_VehicleWithKinematicsAndAerodynamics_.000.png IHDR (here is some strange data which can't be copied and also there are lot of NULL but we have to find out the position of "_.png" so not so difficult in this case ).
The question is my code works fine until i store the data before the .png then i am able to find its position using strstr the problem is when i try to find out the string postion which is appearing after
`3_VehicleWithKinematicsAndAerodynamics_.000.png IHDR ...suppose here we have strange data (which is data block if we see the tar parser)...after this we have another file like..."3_VehicleWithKinematicsAndAerodynamics_.html"`
and if i want to find this "3_VehicleWithKinematicsAndAerodynamics_.html" using strstr then i am not able to find it due to strange data in between them.(because i think that those data are not recognized by the compiler and dut to that i am not able to access the file which is located after the strange data)
to make more clear see the location of file in tar file is as follows-
3_VehicleWithKinematicsAndAerodynamics_.000.png IHDR ............(its data blocl-which is strange contents if you open in tar file)....3_VehicleWithKinematicsAndAerodynamics_.000.html
i have to access the .html file using strstr . why it is not accessing it ?? any ideas ?? *
PLEASE GIVE THE ALTERNATIVES TO ACHIEVE IT..I am sure what i try won't work..
A C style string is a number of characters terminated by a zero-character (NUL character - the value zero, not the character '0'). This means that strstr will stop as soon as it hits such a byte.
One solution that is quite plausible is to simply write a function that searches through binary data based on it's length, not on a "terminating character".
Something like this (this still assumes that the str is a C style string):
char *find_str_in_data(const char *str, const char *data, int length)
{
int pos = 0;
int slen = strlen(str);
while(pos < length-slen)
{
int i = 0;
while(i < slen && str[i] = data[pos+i])
{
i++;
}
if (i == slen)
return data + pos;
}
return NULL;
}
If you really want to use strstr then you need to escape the string contained in buffer with '\0'. If you know the size of data that was put into the buffer (let's say, sizeOfData), than you could do something like this before you use strstr:
buffer[sizeOfData] = '\0';
Warning: if sizeOfData is equal to the size of buffer, then you will either need a greater buffer or overwrite the last character with '\0' (in the second case you should check the buffer tail manually, because the character you've overwritten could be one of the characters of sequence you are looking for).
The following code I am using to find the number of read bytes from QFile. With some files it gives the correct file size, but with some files it gives me a value that is approximatively fileCSV.size()/2. I am sending two files that have same number of characters in it, but have different file sizes link text. Should i use some other objects for reading the QFile?
QFile fileCSV("someFile.txt");
if ( !fileCSV.open(QIODevice::ReadOnly | QIODevice::Text))
emit errorOccurredReadingCSV(this);
QTextStream textStreamCSV( &fileCSV ); // use a text stream
int fileCSVSize = fileCSV.size());
qint64 reconstructedCSVFileSize = 0;
while ( !textStreamCSV.atEnd() )
{
QString line = textStreamCSV.readLine(); // line of text excluding '\n'
if (!line.isEmpty())
{
reconstructedCSVFileSize += line.size(); //this doesn't work always
reconstructedCSVFileSize += 2;
}
else
reconstructedCSVFileSize += 2;
}
I know that reading the size of QString is wrong, give me some other solutions if you can.
Thank you.
I guess it is because QString::size() returns the number of characters. If your text file is in UTF16 and , say, x bytes long, this will correspond with x/2 characters.
Edit: If you want to know the exact size of a read line, you can just use QFile::readLine(). This returns a QByteArray of which the number of bytes can be queried using size().
I made a solution with QByteArray. The solution is:
QFile fileCSV("someFile.txt");
if ( !fileCSV.open(QIODevice::ReadOnly | QIODevice::Text))
emit errorOccurredReadingCSV(this);
while ( !fileCSV.atEnd())
{
QByteArray arrayCSV = fileCSV.readLine();
reconstructedCSVFileSize += arrayCSV.size();
QTextStream textStreamCSV(arrayCSV);
QString line = textStreamCSV.readLine();
}
But there is a problem. Look close the files that I am sending files2.zip.
When i am reading biggerFile.csv with this approach, the first line is properly read, the size of the string is 108, also the number of characters is 108. The number returned by arrayCSV.size() is 221.
When i am reading the second line, the size of the string is 50, but the number of characters is 25. The number returned by arrayCSV.size() is 51. When i open the string with debuger, the string is empty, although its size is 50. I guess this behavior is because the first line is written with one encoding, while the other is written with different encoding, causing QTextStream to behave non properly.
When i am reading smallerFile.csv, everything is ok. The size of the string is 16, also the number of characters is 16(without the \n character). The number returned by arrayCSV.size() is 18.
The second line is also properly read. The size of the string is 25, also the number of characters is 25. The number returned by arrayCSV.size() is 25.
The first code that i have posted, reads the strings properly from both files.
There is a similar question: QTextStream behavior searching for a string not as expected
. You may check my answer for that.
Briefly: to do correct calculation you should mark begin of line with pos() and end of line after reading with pos(). Like this:
qint64 newFileSize = 0;
while ( !f.atEnd() )
{
const qint64 begin = f.pos();
const QString line = f.readLine();
const qint64 end = f.pos();
// TODO: some your actions
// ...
const qint64 realLengthOfLine = end - begin;
newFileSize += realLengthOfLine;
}
What is an efficient, proper way of reading in a data file with mixed characters? For example, I have a data file that contains a mixture of data loaded from other files, 32-bit integers, characters and strings. Currently, I am using an fstream object, but it gets stopped once it hits an int32 or the end of a string. if i add random data onto the end of the string in the data file, it seems to follow through with the rest of the file. This leads me to believe that the null-termination added onto strings is messing it up. Here's an example of loading in the file:
void main()
{
fstream fin("C://mark.dat", ios::in|ios::binary|ios::ate);
char *mymemory = 0;
int size;
size = 0;
if (fin.is_open())
{
size = static_cast<int>(fin.tellg());
mymemory = new char[static_cast<int>(size+1)];
memset(mymemory, 0, static_cast<int>(size + 1));
fin.seekg(0, ios::beg);
fin.read(mymemory, size);
fin.close();
printf(mymemory);
std::string hithere;
hithere = cin.get();
}
}
Why might this code stop after reading in an integer or a string? How might one get around this? Is this the wrong approach when dealing with these types of files? Should I be using fstream at all?
Have you ever considered that the file reading is working perfectly and it is printf(mymemory) that is stopping at the first null?
Have a look with the debugger and see if I am right.
Also, if you want to print someone else's buffer, use puts(mymemory) or printf("%s", mymemory). Don't accept someone else's input for the format string, it could crash your program.
Try
for (int i = 0; i < size ; ++i)
{
// 0 - pad with 0s
// 2 - to two zeros max
// X - a Hex value with capital A-F (0A, 1B, etc)
printf("%02X ", (int)mymemory[i]);
if (i % 32 == 0)
printf("\n"); //New line every 32 bytes
}
as a way to dump your data file back out as hex.