Форум программистов, компьютерный форум CyberForum.ru

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
CAXOPOK
1 / 1 / 0
Регистрация: 29.03.2013
Сообщений: 59
#1

Слишком медленное чтение wstring из файла - C++

05.05.2014, 14:59. Просмотров 506. Ответов 6
Метки нет (Все метки)

Необходимо прочитать из файла некоторое количество строк(внутри них может содержаться всё что угодно: буквы цифры иероглифы). Строка представляет собой твит-сообщение вида:
[38.276866179999999, -122.03544617] 6 2011-08-28 19:03:01 I'm at Liberty Christian Center (2641 N. Texas Street, Fairfield)
Твиты могут быть многострочные. Возможно наличие ссылок, хештегов.
Её надо разбить на составные части в структуру (геолокация, время отправки, никнейм, и само сообщение) и сохранить в бинарном файле, чтоб в следующий раз (для анализа) не пришлось повторять разбиение в структуру.
Столкнулся уже сразу же с проблемой чтения.
C++
1
2
3
4
wifstream input;
input.open(nameoffile);
vector<wstring> tmp;
copy(istream_iterator<std::wstring, wchar_t, std::char_traits<wchar_t>>(input), istream_iterator<std::wstring, wchar_t, std::char_traits<wchar_t>>(),back_inserter(tmp));
Этот код вроде и работает, но работает очень медленно. Файл на ~300кб и ~2500 строк обрабатывает 30 секунд, а основная задача обработать файл 200мб на 1700000 строк, да и этот алгоритм считывает не по строкам, а разбивает по пробелам.
Изначально делал с использованием Qt, но надо это сделать с STL и не используя сторонних библиотек вроде Boost-а.
Вот что вышло в Qt
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
struct twit
{
    double x;
    double y;
    int year;
    int month;
    int day;
    int hour;
    int minuts;
    int secodns;
    QString sender;
    QString i;
};
 
void createBinaryFile(QVector<twit> & twitBase)
{
 
    QFile input(nameoffile);
    input.open(QIODevice::ReadOnly);
    QString data(input.readAll());
    input.close();
    data.remove(0,1);
    QRegExp exp("\\n\\0133");
    QStringList database = data.split(exp, QString :: SkipEmptyParts);
    twit twitBUF;
    QStringList listBuf;
    foreach(QString str, database)
    {
        listBuf = str.split(", ");
        twitBUF.x = listBuf[0].toDouble();
        listBuf = listBuf[1].split("\t");
        listBuf[0].remove(distance(listBuf[0].begin(),listBuf[0].end())-1,1);
        twitBUF.y = listBuf[0].toDouble();
        listBuf = listBuf[2].split("-");
        twitBUF.year = (listBuf[0]).toInt();
        twitBUF.month = listBuf[1].toInt();
        listBuf = listBuf[2].split(" ");
        twitBUF.day = listBuf[0].toInt();
        listBuf = listBuf[1].split(":");
        twitBUF.hour = listBuf[0].toInt();
        twitBUF.minuts = listBuf[1].toInt();
        listBuf = listBuf[2].split("\t");
        twitBUF.secodns = listBuf[0].toInt();
        listBuf = str.split("\t");
        if(listBuf[3][0] != '@')
        {
            twitBUF.sender = "NULL";
            twitBUF.i=listBuf[3];
        }
        if(listBuf[3][0] == L'@')
        {
 
            listBuf = listBuf[3].split(' ');
            listBuf[0].remove(0, 1);
            twitBUF.sender = listBuf[0];
            listBuf.removeFirst();
            str = listBuf.join(' ');
            twitBUF.i = str;
        }
        twitBase.push_back(twitBUF);
    }
    writeBinaryFile(twitBase);
}
void writeBinaryFile(QVector<twit> &twitBase)
{
    QFile output("G:/output.dat");
    output.open(QIODevice::WriteOnly);
    QDataStream stream(&output);
    stream.setVersion(QDataStream::Qt_5_2);
    foreach(twit tmp, twitBase)
    {
        stream << tmp.x << tmp.y << tmp.year << tmp.month << tmp.day << tmp.hour << tmp.minuts << tmp.secodns << tmp.sender << tmp.i;
    }
    output.close();
}
Вкратце: считываю целиком функцией input.readAll() в строку QString и потом с помощью split разбиваю в QStringList, конвертирую в числа при необходимости, заполняю структуру и добавляю её в QVector. Всё это вместе с записью в бинарный файл занимает около минуты для файла 200мб (1700000 твитов), меня такая скорость устраивала. Но как коснулось, в используя только stl и стандартные средства с++, такая схема не работает: нет ни readall(), ни split().
Подскажите пожалуйста, как хотя бы ускорить чтение до адекватных скоростей.
P.S. извиняюсь за много букв
P.P.S 1 курс, основная задача потом по координатам определить место отправления твита... И это 1 курс и срок 2 недели.

Добавлено через 1 час 40 минут
И никто ничего не подскажет?

Добавлено через 15 часов 4 минуты
И что, никто не сталкивался с такой проблемой?
Лучшие ответы (1)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
05.05.2014, 14:59
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Слишком медленное чтение wstring из файла (C++):

Запись и чтение из файла wstring - C++
Всем привет! Ребята, работаю с Юникод и встал вопрос как считать из файла и записать в файл wstring name; Погуглив нашел вот...

Объясните, что означает wstring input = L""; и wstring output = L""; ? - C++
Непонятно особенно L&quot;&quot;.

Переделать в коде чтение из файла в чтение с клавиатуры - C++
Переделайте что бы текст считывался с клавиатуры, а не с файла! Буду благодарен за помощь! //файл должен начинаться со слова, между...

Чтение из файла. Повторное чтение файла - C++
Добрый день. Необходимо реализовать в программе функцию повторного чтения данных из файла, в случае некорректного ввода их в оный. Вот...

Можно ли как-то исправить слишком большой размер файла при подключении библиотеки iostream? - C++
Здравия всем! если откомпилировать это: #include &lt;stdio.h&gt; int main() { printf(&quot;text&quot;); return 0; ...

Преобразование текстового файла в двоичный и чтение исходных данных из двоичного файла. - C++
#include&lt;iostream&gt; #include&lt;fstream&gt; #include&lt;locale.h&gt; #include&lt;iomanip&gt; #include &lt;cstdlib&gt; using namespace std; struct...

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Кудаив
329 / 406 / 24
Регистрация: 27.05.2012
Сообщений: 1,168
Завершенные тесты: 2
05.05.2014, 15:41 #2
а если попробовать в Си - стиле?
CAXOPOK
1 / 1 / 0
Регистрация: 29.03.2013
Сообщений: 59
05.05.2014, 16:00  [ТС] #3
а по подробнее можно?
stima
464 / 313 / 26
Регистрация: 22.03.2011
Сообщений: 1,026
Завершенные тесты: 2
05.05.2014, 16:15 #4
А кто Вам сказал, что у Вас символ это wchar_t?

Добавлено через 1 минуту
Чтобы прочитать строку используйте std::getline(). ReadAll это пока std::getline(). Сплит тоже через std::getline().

Добавлено через 4 минуты
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//pseudo
 
std::istream& operator<<(std::istream& in, twit& t)
{
      //split here
}
 
std::vector<twit> readAll(std::fstream& fs);
{
    std::vector<twit> twits;
    
   std::string line; 
   for ( ; std::getline(fs, line); )
    { 
         std::stringstream ss(line);
         twit << ss;
    }
}
CAXOPOK
1 / 1 / 0
Регистрация: 29.03.2013
Сообщений: 59
05.05.2014, 16:53  [ТС] #5
Спасибо работает, но видимо я не сразу понял причину проблемы со скоростью, ваш код на чистом чтении даёт результат около 2 минут в visual studio. Я сделал .exe вручную, через консоль и результат приблизился к 4-5 секундам на чтении файла в 1700000 строк (твитов), но сдавать это нужно на VS. Если я правильно понял, то проблема из-за байт-кода создаваемого студией. Как можно решить эту проблему?

Добавлено через 4 минуты
В string проблем с иероглифами не будет? ( китайские иероглифы, арабские шрифты)
stima
464 / 313 / 26
Регистрация: 22.03.2011
Сообщений: 1,026
Завершенные тесты: 2
05.05.2014, 16:56 #6
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Перечитайте понятия и термины c++ разработки, если хотите чтобы Вас понимали:
1. Ознакомтесь что такое компилятор и что такое IDE.
2. Что такое отладчик и дебаг символы (а не байт код).


А теперь по делу. Вы не привели ни того как Вы компилировали, ни Ваш конечный код, ни то что Вы делали в IDE при запуске/отладке. Так что судить о скорости это очень "не правильно".

п.с. Чтакже прочитайте что такое кодировка.
CAXOPOK
1 / 1 / 0
Регистрация: 29.03.2013
Сообщений: 59
05.05.2014, 17:27  [ТС] #7
Учту все ваши замечания.
А ошибка моя заключалась в том, что я постоянно запускал отладчик, и это ужасно замедляло работу.
А вот и код - срабатывает за ~6 секунд на 17000000 строк.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include<string>
#include<fstream>
#include<vector>
#include<iostream>
#include<ctime>
using namespace std;
char nameoffile[] = "G:/all_tweets.txt";
 
struct twit
{
    double x;
    double y;
    int year;
    int month;
    int day;
    int hour;
    int minuts;
    int secodns;
    string sender;
    string i;
};
 
 
void readAll(vector<string>& twits)
{
    fstream input;
    input.open(nameoffile);
 
    string line;
    int i;
    while(getline(input, line))
    {
       twits.push_back(line);
    }
    cout<<twits.size();
}
 
int main()
{
    time_t t = time(NULL);
    vector<string> alltwits;
    readAll(alltwits);
    cout << endl << "end" << ' '<< time(NULL) - t;
    system("pause");
    return 0;
}
P.S. Спасибо за советы и извините на мою неграмотность.
P.P.S. Проблема снята.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
05.05.2014, 17:27
Привет! Вот еще темы с ответами:

Чтение нескольких структур и одной переменной из бинарного файла. Формат файла имеется - C++
Формат файла состоит из 3 структур и одной переменной. Подробное описание формата во вложении, просьба посмотреть его. У меня возникла...

как может корректно выполняющийся оператор >> (чтение из текстового файла) негативно влиять на открытие другого файла? - C++
Друзья! Создадим два текстовых файла, f_0.txt и f_1.txt и что-нибудь в них запизаем, например в первый запихаем 1234 а во второй 5678 и...

Чтение файла с несколькими знаками конца файла - C++
В файле несколько раз встречается ноль, и ни как не получается прочитать его полностью. Как можно решить данную проблему ?

wstring - C++
Здраствуите ,вобщем маленькая запара ,хочу узнать возможно ли под WinApi использовать wstring вот пример в чем у меня запара wstring...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
05.05.2014, 17:27
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru