I want to read a huge text file in which I will be dividing the strings according to the comma (,) and store the strings in the array. So how to do this. Is there any class which does the action as StringTokenizer as in badaOS. I have tried QFile but it is not able to read whole file.
QTextStream lets you read line by line
QFile file(hugeFile);
QStringList strings;
if (file.open(QIODevice::ReadOnly | QIODevice::Text))
{
QTextStream in(&file);
while (!in.atEnd()) {
strings += in.readLine().split(";");
}
}
You can use file streams.
QFile file = new QFile(hugeFile);
file.open(QIODevice.OpenModeFlag.ReadOnly);
QDataStream inputStream = new QDataStream(file);
QStringList array;
QString temp;
while(!inputStream.atEnd()) {
inputStream >> temp;
array << temp.split(";");
}
Note that this is untested (pseudo) code, hope it helps.
You can always read a part of file:
QFile file( ... );
file.read(1000); // reads no more than 1000 bytes
Or you car read Your file line by line:
file.readLine();
but You'll have to handle cases when one string was splitted in two pieces.
If it's a really huge file then you can read with the file.read(an_appropriate_number) while file.atEnd() is false.
Read a chunk (with file.read()), add it to a temporary string buffer and search for a ',' (e.g. with QString's contains() method). If it contains a ',' then split it (with QString's split() method): the first X parts (the read 1000 characters may contain more than 1 tokens) will contain the found tokens and the last one is not a complete token yet. So switch the temporary string to the last part of the split and read another chunk (until you hit file.atEnd()) and append it to the temporary string buffer. This will work efficiently unless your tokens are huge. And don't forget to handle the last buffered text after you hit file.atEnd() :)
Or as an alternative you can read the file character-by-character and check for ',' manually, but it's always better to read more than 1 character (it's more efficient if you read more).
This won't capture whitespace after a comma. If that's not acceptable, feel free to optimize the regex. You can probably also reduce the amount of includes at the top. I was just being thorough. I tested this on a 1600 line file, and it seemed to handle it well in Qt 5.6
#include <QCoreApplication>
#include <QFile>
#include <QIODevice>
#include <QRegularExpression>
#include <QRegularExpressionMatch>
#include <QRegularExpressionMatchIterator>
#include <QString>
#include <QStringList>
#include <QTextStream>
int main(int argc, char * argv[])
{
QCoreApplication app(argc, argv);
QFile file("C:\\PathToFile\\bigFile.fileExt");
QStringList lines;
QStringList matches;
QString match;
file.open(QIODevice::ReadOnly | QIODevice::Text);
while(!file.atEnd())
{
lines << file.readLine();
}
file.close();
QRegularExpression regex("(^|\\s|,)\\K\\w.*?(?=(,|$))");
QRegularExpressionMatchIterator it;
foreach (QString element, lines)
{
it = regex.globalMatch(element);
while(it.hasNext())
{
QRegularExpressionMatch qre_match = it.next();
match = qre_match.captured(0);
matches << match;
}
}
return 0;
}
Related
My txt file (CopyBook.txt) contains for example 10 lines. I want to delete the third one.
I have this code:
QString fname = "C://Users//Tomahawk//Desktop//copy//CopyBook.txt";
QFile file(fname);
if (file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append))
{
QTextStream edit(&file);
QString line;
int reachForLine = 0;
int neededLine = 3;
while (reachForPage != pageCounter)
{
line = edit.readLine();
reachForPage++;
}
}
So you can see I use "while" to reach for the line i want to delete. But I haven't found any method in Qt that allows me to do it. In future I want to use the ability of deleting lines to replace them with another ones. So how do I delete it?
One way to do it would be to read all of the lines into a QStringList, modify the QStringList, and then turn around and write its contents back to the file again, like this:
int main(int argc, char ** argv)
{
const QString fname = "C:/Users/Tomahawk/Desktop/copy/CopyBook.txt";
QStringList lines;
// Read lines of text from the file into the QStringList
{
QFile inputFile(fname);
if (inputFile.open(QIODevice::ReadOnly | QIODevice::Text))
{
QTextStream edit(&inputFile);
while (!edit.atEnd()) lines.push_back(edit.readLine());
}
inputFile.close();
}
// Delete the third line from the QStringList
if (lines.length() > 2) lines.removeAt(2); // 0==first line, 1==second line, etc
// Write the text in the QStringList back to the file
{
QFile outputFile(fname);
if (outputFile.open(QIODevice::WriteOnly | QIODevice::Text))
{
QTextStream edit(&outputFile);
for (int i=0; i<lines.size(); i++) edit << lines[i] << Qt::endl;
}
outputFile.close();
}
return 0;
}
You could also perform any replacements/insertions you want to make on the QStringList object, before writing it back to the file.
Note that this approach does use up RAM proportional to the size of the file, so for very large files (e.g. gigabytes long) you would probably want to use the create-a-second-file-and-then-rename approach proposed by #TedLyngmo in his comment, instead. For small files, OTOH, buffering in RAM is somewhat easier and less error-prone.
As you can probably tell I am new to QT and I am attempting to import my console app's src code and headers to qt to build a GUI. I am stuck on one particular function which is supposed to load a file and read it in word by word. I know how to do this in C++, but in QT I have been at it for hours and I am not quite sure how to go about it. Along with reading in the file, I have to insert a string (or in this case type T) by using my own personal insert function (irrelevant to the question).
As of right now i am doing which I know is not working for conversion reasons etc:
template <typename T>
bool HashTable<T>::load(const char* filename)
{
QString word;
QFile inputFile(filename);
QTextStream fin(filename);
// std::ifstream iss;
QString line;
// iss.clear();
// iss.open(filename);
while (fin >> word)
{
insert(word);
}
fin.close();
return true;
}
QTextStream does (to my knowledge) not support word-by-word reading of files, it only support reading a certain number of characters (via read(qint64 maxlen)), reading entire lines (via readLine(qint64 maxlen = 0)) or a combination of the above. An example on how to do this is described in this answer.
What you might do - in order to get a list of words - is reading line-by-line, and splitting each read line with QString's split() function, using space as separator.
template <typename T>
bool HashTable<T>::load(const char* filename)
{
QFile inputFile(filename);
if(!inputFile.open(QIODevice::ReadOnly)) {
QMessageBox::information(0, "error", inputFile.errorString());
}
QTextStream fin(&inputFile);
while(!fin.atEnd()) {
QString line = in.readLine();
QStringList words = line.split(" ");
foreach(QString word, words){
insert(word);
}
}
filename.close();
return true;
}
You have to first open your file for reading. Then textstream should be read line by line. In above code I read a line and then split it to words using space (" ") as the token. Then you can read words from the QStringlist.
In C++, I have a text file that contains Arabic text like:
شكلك بتعرف تقرأ عربي يا ابن الذين
and I want to parse each line of this file into a string and use string functions on it (like substr, length, at...etc.) then print some parts of it to an output file.
I tried doing it but it prints some garbage characters like "\'c7\'e1\'de\'d1\"
Is there any library to support Arabic characters?
edit: just adding the code:
#include <iostream>
#include <fstream>
using namespace std;
int main(){
ifstream ip;
ip.open("d.rtf");
if(ip.is_open() != true){
cout<<"open failed"<<endl;
return 0;
}
string l;
while(!ip.eof()){
getline(ip, l);
cout<<l<<endl;
}
return 0;
}
Note: I still need to add some processing code like
if(l == "كلام بالعربي"){
string s = l.substr(0, 4);
cout<<s<<" is what you are looking for"<<endl;
}
You need to find out which text encoding the file is using. For example, to read an UTF-8 file as a wchar_t you can (C++11):
std::wifstream fin("text.txt");
fin.imbue(std::locale("en_US.UTF-8"));
std::wstring line;
std::getline(fin, line);
std::wcout << line << std::endl;
The best way to deal with this, in my opinion, is to use some UNICODE helper. The strings in C or even in C++ are just an array of bytes. When you do, for example, a strlen() [C] or somestring.length() [C++] you will only have the number os bytes of that string instead of number os characters.
Some auxiliar functions can be used help you on it, like mbstowcs(). But my opinion is that they are kinda old and hard to use.
Another way is to use C++11, that, in theory, has support for many things related to UTF-8. But I never saw it working perfectly, at least if you need to be multi-platform.
The best solution I found is to use ICU library. With this I can work on UTF-8 strings easily and with the same "charm" as working with a regular std::string. You have a string class with methods, for length, substrings and so on... and it's very portable. I use it on Window, Mac and Linux.
You can use Qt too .
Simple example :
#include <QDebug>
#include <QTextStream>
#include <QFile>
int main()
{
QFile file("test.txt");
file.open(QIODevice::ReadOnly | QIODevice::Text);
QTextStream stream(&file);
QString text=stream.readAll();
if(text == "شكلك بتعرف تقرأ عربي يا ابن الذين")
qDebug()<<",,,, ";
}
It is better to process an Arabic text line by line. To get all lines of Arabic text from file, try this
std::wifstream fin("arabictext.txt");
fin.imbue(std::locale("en_US.UTF-8"));
std::wstring line;
std::wstring text;
while ( std::getline(fin, line) )
{
text= text+ line + L"\n";
}
I need to find and replace some text in the text file. I've googled and found out that easiest way is to read all data from file to QStringList, find and replace exact line with text and then write all data back to my file. Is it the shortest way? Can you provide some example, please.
UPD1 my solution is:
QString autorun;
QStringList listAuto;
QFile fileAutorun("./autorun.sh");
if(fileAutorun.open(QFile::ReadWrite |QFile::Text))
{
while(!fileAutorun.atEnd())
{
autorun += fileAutorun.readLine();
}
listAuto = autorun.split("\n");
int indexAPP = listAuto.indexOf(QRegExp("*APPLICATION*",Qt::CaseSensitive,QRegExp::Wildcard)); //searching for string with *APPLICATION* wildcard
listAuto[indexAPP] = *(app); //replacing string on QString* app
autorun = "";
autorun = listAuto.join("\n"); // from QStringList to QString
fileAutorun.seek(0);
QTextStream out(&fileAutorun);
out << autorun; //writing to the same file
fileAutorun.close();
}
else
{
qDebug() << "cannot read the file!";
}
If the required change, for example is to replace the 'ou' with the american 'o' such that
"colour behaviour flavour neighbour" becomes "color behavior flavor neighbor", you could do something like this: -
QByteArray fileData;
QFile file(fileName);
file.open(stderr, QIODevice::ReadWrite); // open for read and write
fileData = file.readAll(); // read all the data into the byte array
QString text(fileData); // add to text string for easy string replace
text.replace(QString("ou"), QString("o")); // replace text in string
file.seek(0); // go to the beginning of the file
file.write(text.toUtf8()); // write the new text back to the file
file.close(); // close the file handle.
I haven't compiled this, so there may be errors in the code, but it gives you the outline and general idea of what you can do.
To complete the accepted answer, here is a tested code. It is needed to use QByteArray instead of QString.
QFile file(fileName);
file.open(QIODevice::ReadWrite);
QByteArray text = file.readAll();
text.replace(QByteArray("ou"), QByteArray("o"));
file.seek(0);
file.write(text);
file.close();
I've being used regexp with batch-file and sed.exe (from gnuWin32, http://gnuwin32.sourceforge.net/). Its good enough for replace one-single text.
btw, there is not a simple regexp syntax there. let me know If you want to get some example of script.
I am making a small program I have done before in Java however I want to try and get the same working in C++. The idea is to merge two text files
file1:
a
b
c
file2:
1
2
3
output file should read:
a1
b2
c3
I have looked at the QTextStream docs and this was the suggested code to read a file by line into strings
QFile file(input); // this is a name of a file text1.txt sent from main method
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
{
return 1;
}
QTextStream in(&file);
QString line = in.readLine();
while (!line.isNull())
{
line = in.readLine();
}
Yet for some reason nothing is being loaded from the file at all. I proved this by printing 'line' to console and got nothing.
So any ideas? All I want is to read the file and end up with a string like this
QString text1 = "a\n2\n3"
I'd do this for both files, split the strings into QStringList (most likely) join them together in the format I want and write them to a 3rd txt file.
Why do you read line by line if you want the entire file?
QString line = in.readAll();
ALso, your while loop is wrong, you need to while (!in.atEnd()) for the text stream instead of checking if the string is null.
readLine won't include the new line symbol.
Anyway, it would be much easier to open both files at the same time and construct your string on the go instead of splitting and joining.
QFile f1("h:/1.txt");
QFile f2("h:/2.txt");
f1.open(QIODevice::ReadOnly | QIODevice::Text);
f2.open(QIODevice::ReadOnly | QIODevice::Text);
QString s;
QTextStream s1(&f1);
QTextStream s2(&f2);
for (int i = 0; i < 3; ++i) {
s.append(s1.readLine());
s.append(s2.readLine());
if (i != 2)s.append("\n");
}
If the file name does not contain full path, but you are very sure that the file is located in the same directory as your application, use the applications path like this:
QString filename = QCoreApplication::applicationDirPath() + "/" + input;
Try this block-:
while(!in.atEnd())
{
QString line = in.readLine();
....
}
do you get output using this while loop?