Qt читает некоторую информацию из текстового файла - PullRequest
0 голосов
/ 24 июня 2018

У меня есть .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**

...

В каждой строке файла есть один город, но для меня важна только жирная информация (имя, широта, долгота).Всего в файле 16 тыс. Строк.Не могли бы вы объяснить, как я могу получить эту информацию.

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: Я также заметил проблему, что некоторые названия городов состоят из 2 слов, разделенных пробелом.

Ответы [ 2 ]

0 голосов
/ 25 июня 2018

Файл, который у вас есть, представляет собой значения, разделенные табуляцией (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
0 голосов
/ 24 июня 2018

По сути, вам нужно только разделить вашу строку:

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

чтобы получить Теттау или Шипкау в вашем примере, аналогично с другими предметами.

Тем не менее, я не уверен насчет «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] или значения для долготы или широты могут привести к ошибке сегментации, если нет.)

После этого вы каким-то образом сохраняете его, например, vector<TownData> со структурой TownData, в которой хранятся нужные вам данные, и на каждой итерации вы добавляете вектор. Я предполагаю, что как это сделать, понятно, но спросите, не так ли.

В общем, в Qt стоит посмотреть, какие классы вы используете в данный момент. В этом случае, QString, который имеет много функций.

Поскольку вектор копируется, когда он меняет размер резервирования, а вы, в частности, спрашиваете об эффективности, было бы неплохо зарезервировать достаточно места для вектора, прежде чем вводить итерации. Я не знаю ни одного метода для получения количества строк в файле без их фактической итерации, поэтому вам может потребоваться сделать это один раз, прежде чем вы на самом деле будете работать с данными в нем, или вам нужно будет создать некоторую оценщику Например, оцените строки по размеру файла или оцените его как 16k. Затем позвоните vector::reserve(size_type n) на ваш вектор. Тем не менее, 16k строк звучат не так много, возможно, это преждевременная оптимизация. Я бы, наверное, сначала обошелся без резервирования и просто посмотрел, работает ли он без сбоев.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...