我有一个.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条信息。 我创建了一个由三名成员组成的“城市”课程。 _名称,_经度,_纬度。然后我想创建一个向量来保护里面的每个城市。这种方法有效吗? 但更重要的是,请告诉我我如何才能阅读每一行的泰斯语3粗体信息,因为我不知道该怎么做。 (我想遍历字符串的每个字符并搜索制表符,但花了很长时间)。 所以,如果您向我展示一种快速的方法,我将非常高兴。程序是使用C ++在Qt中开发的。
PS:我还注意到一个问题,某些城市名称由2个单词组成,以空格分隔。
答案 0 :(得分:1)
基本上,您只需要划定界线:
QStringList delimited = line.split(" ");
QString town = delimited[2];
为了在您的示例中获得Tettau或Schipkau,其他项目也是如此。
也就是说,对于您的示例中的“ SchipkauHö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]或经度或纬度的行可能会导致分段错误,我没有发现这种情况。)
之后,您可以通过某种方式存储它,例如使用具有结构vector<TownData>
的{{1}}来存储所需的数据,并在每次迭代中将其附加到向量上。我认为这样做的方法很明确,但是请问是否是这样。
通常,在Qt中,查看当前正在使用的类是值得的。在这种情况下,TownData
具有很多功能。
由于矢量在更改其保留大小时会被复制,并且您特别询问了效率,因此最好在输入迭代之前为矢量保留足够的空间。我不知道有什么方法可以获取文件中的行数而无需实际对其进行遍历,因此您可能需要在实际使用其中的数据之前进行一次操作,或者需要创建一些估算器,例如根据文件大小估算线数或将其估算为16k。然后在引导程序上调用QString
。也就是说,16k行听起来并不多,可能是过早的优化。我可能首先会毫无保留地去看看它是否能顺利运行。
答案 1 :(得分: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 data{elements[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