Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Сохранение StringList большого объема в файл [D2005, 2003]


Страницы:   1 2 3 4

_guest_ ©   (2013-09-16 16:33:00) 

Есть StringList с объемом текста в полгига. При попытке сохранить в файл или поток (что в общем то одно и то же) получаю "аут оф мемори", так как SaveTo... пытается сохранить его одним куском. А уже обращение к StringList.Text вызывает эту ошибку.  Построчно в текстовый файл - пожалуйста, только времени не один час. Помогите, пожалуйста, буферизировать сохранение в поток. Для меня проблемой является уже даже получить размер результирующей строки. Рассмотрю любые альтернативные варианты. StringList формируется из кусков в количестве от десятков до сотен тысяч размером около 5 килобайт. Можно бы их сразу по получении сливать на диск, но мне перед этим надо их обработать все вместе, а обработка следующих кусков зависит от результатов обработки предыдущих.


_guest_   (2013-09-19 12:14:00) [1]


> DVM ©   (19.09.13 12:10) [78]

В очередной раз могу, только поблагодарить всех и особенно Вас.


DVM   (2013-09-19 12:10:00) [2]


> _guest_   (19.09.13 12:01) [77]


>  Я заглянул в реализацию методов парсера, но никаких перекодировок
> там не увидел и поэтому нахожусь в сомнениях, а как же он
> разделители то узнает.

Как правило текстовые данные передаваемые по сети имеют либо однобайтную кодировку, например, cp1251, либо UFT-8. По крайней мере остальное встречается крайне редко. В любом случае символы, которые критичны для парсера, все имеют размер по одному байту. Парсер как правило читает по одному байту и переводит свою машину состояний в нужное состояние, попутно аккумулируя необходимые себе данные во внутренних структурах. Непосредственно на парсинг кодировка в этом случае не влияет. Но может получиться, что строки которые он выдаст перекодировать легко не получится. Вот если бы парсер выдавал строки в RawByteString тогда все было бы проще. Но попробуй.


_guest_   (2013-09-19 12:01:00) [3]


> DVM ©   (19.09.13 11:47) [75]

Ну в целом, понял. Но уж для полной ясности: если данные в потоке приходят не в той кодировке, которую хочется получить при выводе данных, то без строчного преобразования не обойтись? Функции перекодировки ведь только со строками работают? Я заглянул в реализацию методов парсера, но никаких перекодировок там не увидел и поэтому нахожусь в сомнениях, а как же он разделители то узнает. И если все-таки ему все равно с какой кодировкой работать, то может тогда пусть он отработает, а уже те строки, что он возвращает перекодировать куда надо, ведь теоретически перекодируемых данных становится меньше.


DVM   (2013-09-19 11:50:00) [4]


> Попутно, еще вопрос: это, конечно, не принципиально, но
> после парсинга в перечислителе данные идут в совершенно
> другом порядке, чем в исходнике. На это можно как-то влиять?
>

Зависит от парсера, свой парсер если написать если только.


DVM   (2013-09-19 11:47:00) [5]


> _guest_   (19.09.13 11:39) [74]

По уму надо делать так (вариант для Indy):

Кодировка возможно указана в HTTP заголовках сервера. У TIdHTTP есть событие OnHeadersAvailable кажется, там ты еще до получения данных в свой стрим сможешь получить имя кодировки. Далее возможны 2 варианта:

1) Получаем данные TStringStream, указывая кодировку для него, далее забираем строку из нее в Unicode и отдаем парсеру. Будет копирование данных, что неизбежно при декодировании.

2) Более сложный. Делаем наследника от TMemoryStream, переопределяем в нем метод Write таким образом, чтобы поток при записи данных в него сразу перекодировал их, используя кодировку переданную ему скажем в конструктор, которую в свою очередь мы получили из HTTP заголовков.
Сложность тут в том, чтобы конвертировать данные, нужно получить их некое минимальное количество, определяемое кодировкой (для UTF8 например один символ может занимать различное число байт).

Это первое что пришло в голову, придумаю еще варианты - напишу.


_guest_   (2013-09-19 11:39:00) [6]


> DVM ©   (19.09.13 10:58) [73]

Хороший вопрос...  Когда получил первые данные, вставил в мемо, увидел проблемы, в онлайн-декодере посмотрел исходную кодировку и utf8 в cp1251 тем или и иным способом. Хотя понятно, что тот же браузер кодировку уже знает перед отображением данных, так как кириллица сразу читается нормально.
Попутно, еще вопрос: это, конечно, не принципиально, но после парсинга в перечислителе данные идут в совершенно другом порядке, чем в исходнике. На это можно как-то влиять?


DVM   (2013-09-19 10:58:00) [7]


> _guest_   (19.09.13 09:25) [72]


> строкой - подал на вход нужную кодировку - в ней и получил
> ответ

Как ты определяешь кодировку JSON данных?


_guest_   (2013-09-19 09:25:00) [8]

Я извиняюсь, и уж последний вопрос, хотя уже и офтоп. А если данные скармливать парсеру в потоке, как он будет разбираться с кодировкой? Или кодировку править при получении из перечислителя? В случае со строкой - подал на вход нужную кодировку - в ней и получил ответ. А подал я поток и получил нечто, для чего не могу подобрать кодировку ни я, ни онлайн перекодировщики.


_guest_   (2013-09-18 15:37:00) [9]


> DVM ©   (18.09.13 13:30) [70]

Спасибо, возьму на заметку. Но время, как обычно, поджимает, посмотрю позже.


DVM   (2013-09-18 13:30:00) [10]

Кстати, по поводу SSL/TLS. Недавно обнаружил, что всем давно известная библиотека Delphi Fundamentals весьма сильно преобразилась в лучшую сторону и обрела поддержку SSL/TLS (причем нативную, без сторонних dll!). JSON парсер там тоже имеется. Можно ее попробовать. SSL я проверял - отлично работает: http://sourceforge.net/p/fundementals/code/HEAD/tree/trunk/


_guest_   (2013-09-18 10:46:00) [11]


> Плохиш ©   (18.09.13 10:32) [66]

Нет, структура неизвестна. Т.е. можно, конечно, на какой то выборке посмотреть глазами, составить структуру и пользоваться ей. Но я уже натыкался на то, что обязательно встретится что-нибудь не учтенное. Но решение у меня почти готово. Что такое "стандартный" Text ? файл?

> DVM ©   (18.09.13 10:36) [68]

Да, спасибо, именно его и нашел уже. обычно предлагаются 4: JSON delphi library
Delphi Web Utils
json-superobject
tiny-json
но все советуют именно его.


DVM   (2013-09-18 10:36:00) [12]


> _guest_   (18.09.13 08:44) [60]


> Спасибо за подсказки, сейчас поищу парсер, работающий с
> потоком.

Delphi SuperObject лучший имхо: https://code.google.com/p/superobject/


_guest_   (2013-09-18 10:35:00) [13]


> stas ©   (18.09.13 10:14) [64]

Он отпал, начиная с [10], но все что было дальше - было крайне полезным для меня.

> stas ©   (18.09.13 10:18) [65]

Речь не идет о выкачанных процентах, я всегда могу продолжить с любого места, так как это происходит в режиме запрос-ответ и запрос посылаю я. Речь о том, что у меня есть некий эталон по количеству данных - общее количество участков. И если на сайте их значительно меньше, то они не могут использоваться при анализе.


Плохиш   (2013-09-18 10:32:00) [14]


> _guest_   (18.09.13 08:44) [60]
>
> > Плохиш ©   (17.09.13 18:04) [58]
>
> Ничего, на месте пустого поля пропуск, разделитель и поехали
> дальше.

Т.е. структура известна. Тогда совершенно не понятна проблема. Загружаешь данные, парсируешь, сохраняешь. Никаких гигабайтов в памяти. Открою страшную тайну, даже в стандартный Textможно дописывать данные.


stas   (2013-09-18 10:18:00) [15]

по поводу 98%, я к тому что, допустим качали качали, вырубили электричество, но 98% на диске закачаны, и теперь не качаем все заново, а делаем докачку 2%, но тут надо запоминать точку остановки,и докачать.
Правда не знаю все сервера это могут делать или нет.


stas   (2013-09-18 10:14:00) [16]

_guest_   (18.09.13 09:55) [63]

т.е. вопрос о том что не получается сохранить большой кусок текста отпадает, т.к. можно сохранять кусками по ходу? или нет? )


_guest_   (2013-09-18 09:55:00) [17]


> stas ©   (18.09.13 09:33) [62]
> Я так и не понял, Вам надо все выкачать, а потом обработать
> или получил часть обработал, сохранил ?

На конечный результат последовательность действий не влияет, можно и так и этак. Как я получаю данные, я писал уже несколько раз, повторюсь: данные получаю в виде небольших законченных json-объектов, пример в [57]. И, имхо, нет особой разницы все ли выкачать и сохранить, а потом обрабатывать и сохранять снова или же получил-обработал-сохранил, за исключением того, что во втором случае исключается промежуточная запись/чтение, но повторюсь: на сам результат это не влияет. Не надо кидать в меня камнями за первый вариант. Объясняю: данные нужны все или не нужны вовсе. Поэтому если я скачал и обработал 98% информации, значит я проделал лишнюю (в основном по времени) работу. А если я скачал, увидел, что 2% не хватает, то я могу и не обрабатывать. По-хорошему, надо реализовывать оба варианта и давать оператору выбор, чтобы он поработав на реальных данных смог определится, каким способом он хочет пользоваться.


stas   (2013-09-18 09:33:00) [18]

_guest_   (18.09.13 08:50) [61]
А если поток сделаете TFileStream, то будет напрямую писаться на диск, только не понятно как парсер будет работать, забирать все в ОЗУ или частями.

Я так и не понял, Вам надо все выкачать, а потом обработать или получил часть обработал, сохранил ?


_guest_   (2013-09-18 08:50:00) [19]

ЗЗЫ. Вот сейчас, когда Вы меня замотивировали, я обнаружил, что и synapse может вернуть поток, так что все упрощается, дело за парсером.


_guest_   (2013-09-18 08:44:00) [20]


> Плохиш ©   (17.09.13 18:04) [58]

Ничего, на месте пустого поля пропуск, разделитель и поехали дальше. Просто у разных объектов могут отсутствовать разные поля. Поэтому общую структуру надо или считывать после загрузки всех данных или создавать в процессе загрузки, правда при этом связанные по смыслу поля могут разъехаться друг от друга, плюс структура в выходных файлах в этом случае будет варьироваться и как то придется их потом склеивать, очевидно за два прохода.

> DVM ©   (17.09.13 22:21) [59]

Вот. Аргументированный ответ. Блестяще и убедительно. И если бы мне удалось подобрать openssl к тому indy что в 2007-й на работе, я прямо сейчас бы стал переделывать. А так придется ждать до вечера.
А насчет парсера, никакой кустарщины не будет. Я прямо сейчас не гоню данные на выход, только оцениваю их количество и качество. Т.е. вполне возможна ситуация, что я выдам не программу, а вывод, что данных на сайте недостаточно и программа не нужна. И только поэтому на этапе оценки использую такую ерунду. И да, лишние или недостающие пробелы, прямые и обратные слеши в данных - все это встречается. Я пока просто отсекаю - полпроцента потерь пока несущественны. Все что не прошло входной контроль - в отдельный файл, и потом буду разбираться с этим.
Спасибо за подсказки, сейчас поищу парсер, работающий с потоком.


Страницы:   1 2 3 4

Наверх

Титульная страница Поиск, карта сайта Написать письмо