Qt读取文本文件的一些信息

Posted

技术标签:

【中文标题】Qt读取文本文件的一些信息【英文标题】:Qt reading some infomation of a textfile 【发布时间】:2018-06-24 20:38:45 【问题描述】:

我有一个.txt 文件,需要从中读取。该文件包含城市、经度、纬度和其他一些内容的数据。

这是数据格式:

DE  01945   **Tettau**  Brandenburg BB      00  Landkreis Oberspreewald-Lausitz 12066   **51.4333   13.7333**

DE  01968   **Schipkau Hörlitz**    Brandenburg BB      00  Landkreis Oberspreewald-Lausitz 12066   **51.5299   13.9508**

...

文件的每一行都是一个城市,但对我来说只有粗体信息很重要(名称、纬度、经度)。总而言之,文件中有 16k 行。 你能解释一下我是如何获得这些信息的吗?

QFile file ("path");
QTextStream in (&file);
while (!in.atEnd()) 
    QString line = in.readLine();
    std::string s = line.toLocal8Bit().constData();
    std::cout << s << endl;

file.close();

到目前为止,我只能阅读整行,但我不知道如何获取每行的这 3 个信息。 我创建了一个包含三个成员的“城市”类。 _name,_longitude,_latitude。然后我想创建一个向量来保护里面的每个城市。这种方法有效吗? 但更重要的是,请告诉我如何阅读每行的 3 个粗体信息,因为我不知道该怎么做。 (我想遍历字符串的每个字符并搜索制表符,但花了很长时间)。 所以如果你告诉我一个快速的方法,我真的很高兴。程序是在Qt中用c++开发的。

PS:我还注意到一些城市名称由两个单词组成,用空格分隔的问题。

【问题讨论】:

城市名称后面是Brandenburg这个词,code ABCDE?之前,除了纬度和经度在末尾行?,终于可以分享文件了。 如果我知道如何在这里上传文件,我可以分享文件:D。但我也可以分享文件的链接。 download.geonames.org/export/zip 只需从德国城市的地理坐标下载 DE.zip 它是一个开源代码 【参考方案1】:

你的文件是制表符分隔值(TSV),所以逻辑是通过制表符获取每一行并分隔,然后选择元素如下图:

#include <QFile>
#include <QTextStream>

#include <iostream>

struct CityData

    std::string city;
    float latitude;
    float longitude;
;

int main()

    QFile file("/path/of/DE.txt");
    if(!file.open(QFile::ReadOnly | QFile::Text))
        return -1;

    QTextStream stream(&file);
    QString line;

    std::vector<CityData> datas;

    while (stream.readLineInto(&line)) 
        QStringList elements = line.split("\t");

        CityData dataelements[2].toStdString(),
                    elements[9].toFloat(),
                    elements[10].toFloat()
                     ;
        datas.push_back(data);
    
    for(const CityData & data: datas)
        std::cout<< "city: "<< data.city <<"\t" << "latitude: "<< data.latitude <<"\t" << "longitude: "<<data.longitude<<"\n";
    
    return 0;

输出:

city: Tettau    latitude: 51.4333   longitude: 13.7333
city: Guteborn  latitude: 51.4167   longitude: 13.9333
city: Hermsdorf latitude: 51.4055   longitude: 13.8937
city: Grünewald latitude: 51.4  longitude: 14
city: Hohenbocka    latitude: 51.431    longitude: 14.0098
city: Lindenau  latitude: 51.4  longitude: 13.7333
city: Ruhland   latitude: 51.4576   longitude: 13.8664
city: Schwarzbach   latitude: 51.45 longitude: 13.9333
city: Kroppen   latitude: 51.3833   longitude: 13.8
city: Schipkau Hörlitz  latitude: 51.5299   longitude: 13.9508
city: Senftenberg   latitude: 51.5252   longitude: 14.0016
city: Schipkau  latitude: 51.5456   longitude: 13.9121
...

在这类材料中你应该阅读readme.txt

...

The data format is tab-delimited text in utf8 encoding, with the following fields :

country code      : iso country code, 2 characters
postal code       : varchar(20)
place name        : varchar(180)
admin name1       : 1. order subdivision (state) varchar(100)
admin code1       : 1. order subdivision (state) varchar(20)
admin name2       : 2. order subdivision (county/province) varchar(100)
admin code2       : 2. order subdivision (county/province) varchar(20)
admin name3       : 3. order subdivision (community) varchar(100)
admin code3       : 3. order subdivision (community) varchar(20)
latitude          : estimated latitude (wgs84)
longitude         : estimated longitude (wgs84)
accuracy          : accuracy of lat/lng from 1=estimated to 6=centroid

【讨论】:

谢谢你们,你们都帮了我很多,我不能把你的答案标记为有用,因为我的声望不到 15,但我真的很感激 :) @Domooo93 将答案标记为正确是一回事,而给予支持则是另一回事。将回复标记为正确不需要声誉,请这样做,如果您不知道该怎么做,请查看tour,这是最好的感谢方式。 @Domooo93 我已经给你投了赞成票,所以你可以投赞成票并将我的答案标记为正确。 :)【参考方案2】:

基本上,你只需要划定你的行:

QStringList delimited = line.split(" ");
QString town = delimited[2];

为了在您的示例中获得 Tettau 或 Schipkau,其他项目也是如此。

也就是说,我不确定你的示例中的“Schipkau Hörlitz”是什么,假设这是一个城镇的名称,或者是一个有组合名称的城镇的四分之一。这取决于你的格式。一种选择是从索引 2 开始并添加任何出现的内容,只要它不是德国州的名称即可。当然,这仅适用于德国。您还可以尝试找出仅是数字的下一个索引,在您的示例中为“00”,然后从该索引开始工作。同样,这取决于您的格式,我希望我给了您足够的帮助。

可能看起来像:

QStringList delimited = line.split(" ");
QString town = delimited[2];
size_t pos = 3;
while(not is_german_state(delimited[pos]))

    town += " "  + delimited[pos];
    pos++;

QString longitude = delimited[pos+6];
QString latitude= delimited[pos+7];

(请注意,当行格式不正确并因此分隔 [pos] 或经度或纬度的行可能导致分段错误时,我没有发现这种情况。)

之后,您以某种方式存储它,例如拥有一个带有 TownData 结构的 vector&lt;TownData&gt; 来存储您需要的数据,并且在每次迭代中,您附加到向量。我认为如何做到这一点很清楚,但请询问是否不是。

在 Qt 中,一般来说,查看您当前使用的类是值得的。在这种情况下,QString,它有很多功能。

由于向量在更改其保留大小时被复制,并且您特别询问了效率,因此在进入迭代之前为向量保留足够的空间是个好主意。我不知道有任何方法可以在不实际迭代文件的情况下获取文件中的行数,因此您可能需要在实际使用其中的数据之前执行一次,或者您需要创建一些估算器,例如按文件大小估计行数或估计为 16k。然后在您的矢量上调用vector::reserve(size_type n)。也就是说,16k 行听起来并不多,可能是过早的优化。我可能会先毫无保留地去看看它是否顺利运行。

【讨论】:

我试过你的建议,你写的两行一模一样。程序已编译但当我运行控制台时出现错误“QList::operator[] 中的 ASSERT 失败:索引超出范围,文件 C:\Qt\5.10.1\mingw53_32\include/QtCore/qlist. h,第 549 行 @Domooo93 可能是读取了空行之类的。也许在每次迭代中检查那个。为了调试,您可能希望打印当前行和列表的大小。 @Domooo93 或者,正如其他人所说,使用标签。 谢谢你们,你们都帮了我很多,我不能把你的答案标记为有用,因为我的声望不到 15,但我真的很感激 :) @Domooo93 不过,您应该可以选择一个并接受它作为答案(分数下方的灰色复选标记)

以上是关于Qt读取文本文件的一些信息的主要内容,如果未能解决你的问题,请参考以下文章

QT读取文本文件

QT中怎样读取中文文本文件!

Qt读取文本文件乱码怎么办

从文本文件读取,然后写入 QT 中的同一文件(高分功能)

在Qt中以二进制形式读取0和1文本文件[重复]

通过Qt中的程序对文本文件进行排序