I have a table view with three columns; I have just passed to write into text file using this code
QFile file("/home/hamad/lesson11.txt");
if(!file.open(QIODevice::WriteOnly)) {
QMessageBox::information(0,"error",file.errorString());
}
QString dd;
for(int row=0; row < model->rowCount(); row++) {
dd = model->item(row,0)->text() + ","
+ model->item(row,1)->text() + ","
+ model->item(row,2)->text();
QTextStream out(&file);
out << dd << endl;
}
But I'm not succeed to read the same file again, I tried this code but I don't know where is the problem in it
QFile file("/home/hamad/lesson11.txt");
QTextStream in(&file);
QString line = in.readLine();
while(!in.atEnd()) {
QStringList fields = line.split(",");
model->appendRow(fields);
}
Any help please ?
You have to replace string line
QString line = in.readLine();
into while:
QFile file("/home/hamad/lesson11.txt");
if(!file.open(QIODevice::ReadOnly)) {
QMessageBox::information(0, "error", file.errorString());
}
QTextStream in(&file);
while(!in.atEnd()) {
QString line = in.readLine();
QStringList fields = line.split(",");
model->appendRow(fields);
}
file.close();
Related
Problem description
I want to be able to recognize the corresponding Chinese person name and complete the prompt by entering a short Chinese phonetic alphabet.
For example, I have a map (("lvbu", "吕布"), ("lvbuwei", "吕不韦")) , then enter "lv" or "bu",The completer should pop up "吕布" and "吕不韦", but it seems that the stringlist must contain the content currently being entered to complete the prompt. The completer cannot recognize the mapping relationship.
How can I solve it? I can hardly find a solution on the Internet because it involves Chinese.
My code
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "Pinyin2Hanzi/myPinyin.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
QString N = "吕布 吕不韦 南宫问天";
QStringList Names = N.split(" ");
// qDebug() << Names;
ui->comboBox->addItem("");
ui->comboBox->addItems(Names);
ui->comboBox->lineEdit()->setClearButtonEnabled(true);
CreateCompleter(Names, ui->comboBox->lineEdit());
ui->comboBox->setMaxCount(ui->comboBox->count()); //这行代码可以防止按回车键自动往combobox里addItem
}
MainWindow::~MainWindow()
{
delete ui;
}
std::map<std::string, std::vector<QString>> pinyin2NameMap; // This is a private variable
// 把所有人名按照拼音分类并存入map中
void MainWindow::PreparePinyinData(const QStringList &names)
{
for (auto & name : names)
{
QString outFristPy,outFullPy;
getComPingyinForStr(name, outFristPy, outFullPy);
// QString pinyin = GetPinyin(name);
QString pinyin = outFullPy;
// qDebug() <<"FristPy:" << outFristPy << "FullPy:" << outFullPy;
// qDebug() <<"pinyin:" << pinyin;
// QString fist, last;
// myNameSplit(name, last, fist); // 自动切分 [姓、名]
// last = getNamePingyin(last, true); // 获取 [姓] 的拼音
// fist = getNamePingyin(fist, false);// 获取 [名] 的拼音
// qDebug() << name + " : " + last + " " + fist << endl;
pinyin2NameMap[pinyin.toStdString()].push_back(name);
}
}
// 根据输入的拼音进行匹配并获取提示列表
QStringList MainWindow::GetMatchByPinyin(const QString &pinyin)
{
QStringList result;
if("" == pinyin.trimmed()){
return QStringList();
}
for (const auto & iter : pinyin2NameMap){
if (iter.first.find(pinyin.toStdString()) != std::string::npos){
auto vec = iter.second;
for(const auto & name : vec){
result.append(name);
}
}
}
return result;
}
// 创建QCompleter并设置自动补全模型
void MainWindow::CreateCompleter(const QStringList &names, QLineEdit *lineEdit)
{
PreparePinyinData(names);
QStringListModel *model = new QStringListModel(names);
QCompleter *completer = new QCompleter(model, lineEdit);
completer->setCaseSensitivity(Qt::CaseInsensitive);
completer->setFilterMode(Qt::MatchContains);
completer->setCompletionMode(QCompleter::PopupCompletion);
lineEdit->setCompleter(completer);
connect(lineEdit, &QLineEdit::textEdited, [this,completer,lineEdit, model](const QString &text)
{
QStringList matchList = GetMatchByPinyin(text);
qDebug() << "listmodel:" << matchList;
// QString N = "lv不bu 可lvbuwei nan够gongwentian";
// QStringList matchList = N.split(" ");
model->setStringList(matchList);
completer->setModel(model);
completer->complete();
});
}
I am saving the QAbstract tree model to a dat file
void saveTreeStructureToFile(const QModelIndexList &indexes , const std::string stdstrFilePath)
{
QMimeData *mimeData = new QMimeData;
QByteArray data; //a kind of RAW format for datas
QDataStream stream(&data, QIODevice::WriteOnly);
QList<TreeItem *> nodes;
foreach(const QModelIndex &index, indexes) {
TreeItem *node = getItem(index);
if (!nodes.contains(node))
nodes << node;
}
stream << nodes.count();
foreach(TreeItem *node, nodes) {
buildTree(node, stream);
}
mimeData->setData(s_treeNodeMimeType, data);
std::string st = stdstrFilePath.substr(0, stdstrFilePath.size() - 3);
st.append("dat");
const QString path = st.c_str();
QFile file(path);
file.open(QIODevice::WriteOnly);
QDataStream out(&file);
out << *mimeData;
}
How can i prepend the size of total bytes to be written to the start of dat file.
You can retrieve the size of the data and append it to your data stream at the beginning, like:
out << data.size() << *mimeData;
I am beginner in UI design using Qt. My project now is doing comparison. For example: if I have 2 text file.
How can I compare the number line by line? Because I have so many text file like this, and I need compare them on by one.What I can do now is only read the text file by line order. Thank you so much!
The procedure is simple
Read both files (always make sure they are opened successfully)
Read files line by line and convert strings to numbers for comparison.
Quit if there is no data left.
Moreover, you need to make sure that the format of files is consistent otherwise, you need to make sure what you manipulate is a real number. I assume numbers are integers but of course you can change it. Extra precautions are required in this kind of project. I will leave it to you. The simplified code for the above procedure is
#include <QString>
#include <QFile>
#include <QDebug>
#include <QTextStream>
int main()
{
QFile data1("text1.txt");
if (!data1.open(QIODevice::ReadOnly | QIODevice::Text)){
qDebug() << "text1.txt file can't be opened...";
return -1;
}
QFile data2("text2.txt");
if (!data2.open(QIODevice::ReadOnly | QIODevice::Text)){
qDebug() << "text2.txt file can't be opened...";
return -1;
}
QTextStream in1(&data1), in2(&data2);
while ( !in1.atEnd() && !in2.atEnd() ) {
QString num1 = in1.readLine();
QString num2 = in2.readLine();
if ( num1.toInt() > num2.toInt() )
qDebug() << num1.toInt() << ">" << num2.toInt();
// do the rest of comparison
}
return 0;
}
Now in my case, the txt files are
text1.txt
1
2
3
4
text2.txt
3
5
1
6
The output is
3 > 1
Edit: the OP is looking for the difference and its sum.
int sum(0);
while ( !in1.atEnd() && !in2.atEnd() ) {
QString num1 = in1.readLine();
QString num2 = in2.readLine();
int result = num1.toInt() - num2.toInt();
qDebug() << num1.toInt() << "-" << num2.toInt() << " = " << result;
sum += result;
}
qDebug() << "sum = " << sum;
Basic approach would be something like this:
QString filename1("C:/Users/UserName/Downloads/t1.txt");
QString filename2("C:/Users/UserName/Downloads/t2.txt");
QFile file(filename1);
file.open(QIODevice::ReadOnly);
QTextStream in(&file);
QStringList textOfFile1;
while (!in.atEnd()) {
QString line = in.readLine();
textOfFile1.append(line);
}
QFile file2(filename2);
file2.open(QIODevice::ReadOnly);
QTextStream in2(&file2);
QStringList textOfFile2;
while (!in.atEnd()) {
QString line = in.readLine();
textOfFile2.append(line);
}
if(textOfFile1.size() != textOfFile2) return false;
for(int i = 0; i < textOfFile1.size(); i++)
{
if(textOfFile1[i] != textOfFile2[i]) return false;
}
return true;
i.e. You read the files into a QStringList and you compare the lists line by line. This way you can also catch the firs # of line where there was a mismatch. Note that such comparison also considers white spaces such as \n \t etc.
PS: wrap the readers into functions, to avoid duplication like me. :)
Hope this helps ;)
Recently I programmed to do file transmission with Qt. Thought it worked now, I'm still curious about what happened. Please help me find out the reason. Many thanks.
Why the size of head is bigger than the sum of sizeof(qin32), sizeof(qint32) and length of file name?(I guess it is the reason of function - setVersion())
QFileInfo info(file_to_send.fileName());
QByteArray head;
QDataStream out(&head, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_5_0);
out << qint32(file_to_send.size() + info.fileName().length() + sizeof(qint32)*2)
<< qint32(info.fileName().length())
<< info.fileName();
tcpClient.write(head);
You have made it to complicated. Pattern is like that:
QFileInfo info(file_to_send.fileName());
QByteArray head;
QDataStream out(&head, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_5_0);
out << qint32(0)
<< info.fileName(); // << YouCanAddMoreStuffHere;
out.device()->seek(0);
out << qint32(out.length());
tcpClient.write(head);
and read code:
void SomeClass::slotReadClient() { // slot connected to readyRead signal of QTcpSocket
QTcpSocket *tcpSocket = (QTcpSocket*)sender();
QDataStream clientReadStream(tcpSocket);
while(true) {
if (!next_block_size) {
if (tcpSocket->bytesAvailable() < sizeof(qint32)) { // are size data available
break;
}
clientReadStream >> next_block_size;
}
if (tcpSocket->bytesAvailable() < next_block_size) {
break;
}
QString fileName;
clientReadStream >> fileName; // >> YouCanAddMoreStuffHere; // same as above
next_block_size = 0;
}
}
info.filename() writes out its own length
if you don't want that then you can do
QFileInfo info(file_to_send.fileName());
QByteArray head;
QDataStream out(&head, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_5_0);
QByteArray filename = info.fileName().toLatin1();
out << qint32(file_to_send.size() + filename .length() + sizeof(qint32)*2);
<< qint32(filename .length())
out.writeRawData(fileName.constData(), filename.length());
tcpClient.write(head);
using writeRawData which bypasses any built in encoding
Simple problem, I just can't open/create a file. It's supposed to save some settings in an xml-file to a given path.
I call the method like this:
xmlwriter->write_settings("./settings.xml");
int XmlWriter::write_settings(QString path)
{
qDebug() << "Path is: " + path;
QDomDocument document;
QDomElement root = document.createElement("settings");
document.appendChild(root);
QDomElement node;
node.setAttribute("name", "Its me!");
node.setAttribute("series", "25");
node.setAttribute("PMT", "200");
root.appendChild(node);
QFile file(path);
if(!file.open(QIODevice::ReadWrite, QIODevice::Text))
{
qDebug() << "Opening file failed!";
return 1;
}
else
{
QTextStream stream(&file);
stream << document.toString();
file.close();
qDebug() << "wrote file to " + path;
return 0;
}
}
You don't pass parameters correctly, so you probably invoke a polymorphic version of QFile::open
Try this:
QFile file(path);
if(!file.open(QIODevice::ReadWrite | QIODevice::Text))
{
qDebug() << "Opening file failed!";
return 1;
}
else
{
QTextStream stream(&file);
stream << document.toString();
file.close();
qDebug() << "wrote file to " + path;
return 0;
}