1

Тема: Завантаження текстового файлу в wxWidgets

Намагаюся завантажити текстовий файл через wxTextInputStream ось так:

wxFileInputStream input(j);
wxTextInputStream text_file(input, wxT("\x09"), wxConvUTF8);

for (int i = 0; i < 4; i++) {
    wxString line = text_file.ReadLine();
    cout << line << endl;
}
while (input.IsOk() && !input.Eof()) {
    wxString line_next = text_file.ReadLine();
    cout << line_next << endl;
}

Цикл for працює добре, а з while — проблема в умовах.
Не можу зрозуміти як визначити кінець файлу.
wxFileInputStream, як я розумію, одразу після завантаження виставляє змінну на EOF.
А якщо спробувати використати функцію Eof() на змінній wxTextInputStream,
то компілятор каже, що wxTextInputStream не має такої функції.
При компіляції вище наведеного коду помилок немає,
але після запуску програма просто висне, наче застрягає в циклі.

2

Re: Завантаження текстового файлу в wxWidgets

Звертаю увагу, що Eof() повертає true лише після того, як ReadLine (чи щось інше) зіткнеться з помилкою читання.
Консоль завалюється символами нового рядка? Тобто це реально ваш цикл крутиться чи щось інше?

3

Re: Завантаження текстового файлу в wxWidgets

koala написав:

Звертаю увагу, що Eof() повертає true лише після того, як ReadLine (чи щось інше) зіткнеться з помилкою читання.
Консоль завалюється символами нового рядка? Тобто це реально ваш цикл крутиться чи щось інше?

Зависло, бо вивід ішов через wxStreamToTextRedirector redirect(my_console->terminal).
Я виводив через wxTextCtrl, там щось пішло не так.
Щодо Eof(), то він і має бути перед ReadLine, бо інакше губиться останній елемент.
Це в їхній документації написано.
Але завантаження все одно надто повільне.

4

Re: Завантаження текстового файлу в wxWidgets

Операції введення-виведення узагалі повільні, але часто можна багато чого прискорити. Кодом поділитеся? І метриками - що саме ви вважаєте повільним?

Подякували: leofun011

5

Re: Завантаження текстового файлу в wxWidgets

koala написав:

Операції введення-виведення узагалі повільні, але часто можна багато чого прискорити. Кодом поділитеся? І метриками - що саме ви вважаєте повільним?

Код ще сирий:

void MyApp::load_dictionaries()
{
    wxString default_paths = wxT("");
    wxString current_paths;
    current_paths = config->Read("Preference/SettingsWindow/Paths_to_dicts",
                                default_paths);
    if (current_paths != default_paths)
    {
        const wxArrayString& dict_paths = wxSplit(current_paths, '\n');
        wxStreamToTextRedirector redirect(my_console->terminal);
        for (auto i: dict_paths)
        {
            if (wxDirExists(i))
            {
                wxDir dir;
                wxArrayString* files = new wxArrayString {};
                dir.GetAllFiles(i, files);
                for (auto j: *files)
                {
                    if (j.EndsWith(wxT(".txt")))
                    {
                        wxTimer my_timer;
                        my_timer.Start();
                        auto timer_start = wxGetLocalTimeMillis();

                        wxFileInputStream* input = new wxFileInputStream(j);
                        wxTextInputStream* text_file = new wxTextInputStream(*input, wxT("\x09"), wxConvUTF8);

                        for (int i=0; i<4; i++)
                        {
                            wxString line = text_file->ReadLine();
                        
                        }
                        wxString line_next {wxT("")};
                        while (input->IsOk() && !input->Eof())
                        {
                            line_next += text_file->ReadLine() + "\n";
                           
                        }

                    
                        auto timer_stop = wxGetLocalTimeMillis();
                        const wxLongLong elapsed_time = timer_stop - timer_start;
                        cout << elapsed_time << endl;

                    }

                }

            }
        }
    }
}

Файл формату .txt і розміром 27Мб завантажується приблизно за 7 секунд.
Я розумію, що після першого завантаження варто все це до кешу запхати,
але поки що хочу максимально прискорити власне завантаження.

6

Re: Завантаження текстового файлу в wxWidgets

Купляй NVMe, буде швидше

7 Востаннє редагувалося koala (05.10.2023 15:54:40)

Re: Завантаження текстового файлу в wxWidgets

Це небуферизовані потоки, тобто кожна операція читання викликає звертання до ОС.
Спробуйте десь так:

wxFileInputStream* input = new wxFileInputStream(j);
wxBufferedInputStream* buffered_input = new wxBufferedInputStream(*input);
wxTextInputStream* text_file = new wxTextInputStream(*buffered_input, wxT("\x09"), wxConvUTF8);
Подякували: Teg Miles, leofun012

8

Re: Завантаження текстового файлу в wxWidgets

koala написав:

Це небуферизовані потоки, тобто кожна операція читання викликає звертання до ОС.
Спробуйте десь так:

wxFileInputStream* input = new wxFileInputStream(j);
wxBufferedInputStream* buffered_input = new wxBufferedInputStream(*input);
wxTextInputStream* text_file = new wxTextInputStream(*buffered_input, wxT("\x09"), wxConvUTF8);

Те, що треба. Тепер менше секунди йде на завантаження.

9

Re: Завантаження текстового файлу в wxWidgets

Можете ще спробувати збільшити буфер:

wxBufferedInputStream* buffered_input = new wxBufferedInputStream(*input, 0x4000); // 16KB

Це вже треба тестувати, який розмір краще працює у вашій системі. Усталено там 1 кілобайт.

Подякували: leofun011

10

Re: Завантаження текстового файлу в wxWidgets

koala написав:

Можете ще спробувати збільшити буфер:
wxBufferedInputStream* buffered_input = new wxBufferedInputStream(*input, 0x4000); //16KB
Це вже треба тестувати, який розмір краще працює у вашій системі. Усталено там 1 кілобайт.

Поки що не чіпатиму розмір буфера, бо треба, щоб працювало і в Віндовс, і в Лінукс.

11

Re: Завантаження текстового файлу в wxWidgets

16 KB не є аж так багато памяті щоб їх не користувати. Навіть в часи коли оперативки було 128 MB, 16 KB для буфера було цілком ок.

Збільшеня буфера з 1 KB до 16 KB збільшить швидкість читання з диска в *<16 разів, якщо не вся оперативка забита.

Точніше не так, збільшить не саму швидкість читання, а зменшить кількість звертань до файлової системи, що збільшить швидкість надходження даних потрібних для програми.

12

Re: Завантаження текстового файлу в wxWidgets

koala написав:

Можете ще спробувати збільшити буфер:
wxBufferedInputStream* buffered_input = new wxBufferedInputStream(*input, 0x4000); //16KB
Це вже треба тестувати, який розмір краще працює у вашій системі. Усталено там 1 кілобайт.

До речі, а чому в шістнадцятковій системі? Можна ж просто 16384 написати.

13

Re: Завантаження текстового файлу в wxWidgets

Це не системний буфер, це пам'ять у вашій програмі. Тому нічого страшного від виділення 16КБ масиву не станеться.
А 0x4000 мені особисто зрозуміліше за 16384. І змінювати зручніше.

Подякували: leofun011