![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Сохранение StringList большого объема в файл [D2005, 2003]
_guest_ © (2013-09-16 16:33:00)Есть StringList с объемом текста в полгига. При попытке сохранить в файл или поток (что в общем то одно и то же) получаю "аут оф мемори", так как SaveTo... пытается сохранить его одним куском. А уже обращение к StringList.Text вызывает эту ошибку. Построчно в текстовый файл - пожалуйста, только времени не один час. Помогите, пожалуйста, буферизировать сохранение в поток. Для меня проблемой является уже даже получить размер результирующей строки. Рассмотрю любые альтернативные варианты. StringList формируется из кусков в количестве от десятков до сотен тысяч размером около 5 килобайт. Можно бы их сразу по получении сливать на диск, но мне перед этим надо их обработать все вместе, а обработка следующих кусков зависит от результатов обработки предыдущих.
_guest_ (2013-09-17 12:36:00) [41]> DVM © (17.09.13 12:16) [36]
так чтобы из меня не тянуть клещами: с сайта идет не файл, а сама страничка. Так что если я чего недопонимаю, то Вы меня поправьте.
_guest_ (2013-09-17 12:30:00) [42]
> DVM © (17.09.13 12:16) [36]
Потому что я использую делфийский компонент, любой на выбор: IdHTTP (indy), IEHTTP, HTTPSend (synapse). Похоже я сейчас узнаю что-то новое для себя. В общем то я с ними вожусь всего 3-й день, но по-моему каждый из них возвращает список строк в том или ином виде.
> stas © (17.09.13 12:17) [37]
Зачем? Чтобы текст в одном виде сохранить как текст в другом. Вся обработка исключительно строчная, ничего не надо искать, ничего выбирать или вычислять. Из-за объемов? Так пока что результирующие файлы блокнотом++ спокойно открывались, ну вот до последнего раза. Так мне смотреть на него и не надо.
stas (2013-09-17 12:17:00) [43]_guest_ (17.09.13 12:08) [33]
С такими объемами Вам придется освоить СУБД.
DVM (2013-09-17 12:16:00) [44]
> _guest_ (17.09.13 12:14) [35]
Че то я не понимаю, как с сайта может прийти дельфийский объект TStringList?
Приходит именно поток данных TStream или буфер (массив данных) из которого потом кто-то перекладывает данные за каким то лешим в TStringList, хотя парсить можно прям оригинальный буфер без лишних телодвижений.
_guest_ (2013-09-17 12:14:00) [45]
> DVM © (17.09.13 12:13) [34]
С сайта
DVM (2013-09-17 12:13:00) [46]
> Нет никаких границ и потока, данные приходят в виде StringList'ов.
Откуда они приходят в таком виде?
_guest_ (2013-09-17 12:08:00) [47]Собственно, я извиняюсь, что сразу все не написал, просто на момент обращения на форум, я решал конкретную задачу по сохранению большого списка в файл, а дискуссия вышла намного более познавательной для меня.
_guest_ (2013-09-17 12:05:00) [48]
> DVM © (17.09.13 12:02) [31]
Нет никаких границ и потока, данные приходят в виде StringList'ов.
DVM (2013-09-17 12:02:00) [49]
> _guest_ (17.09.13 11:59) [30]
> т.к. приходит не какой-то большой документ, а очень много
> маленьких
А, ну это меняет дело. Придется в потоке данных находить границы этих маленьких документов, если они известны и отдавать найденное парсеру. Несколько неоптимальный путь, но рабочий.
_guest_ (2013-09-17 11:59:00) [50]
> DVM © (17.09.13 11:44) [28]
Данные приходят небольшими законченными кусками. Их можно считать элементами какого-то общего документа, а можно и не считать. Если по аналогии с xml, то меня вполне устроит модель dom, т.к. приходит не какой-то большой документ, а очень много маленьких и данные из них нужны абсолютно все. Я потому и не заострял на этом моменте внимания, что сама структура данных простая: имя-значение, и если я выкину все скобки а двоеточие заменю на знак равенства, то получу список типа name=value, вот и весь парсинг. Логически что там приходит, мне все равно, раскидал по столбцам и сохранил.
DVM (2013-09-17 11:49:00) [51]
> _guest_ (17.09.13 11:25) [27]
Вот пример из википедии:
{
"firstName": "Иван",
"lastName": "Иванов",
"address": {
"streetAddress": "Московское ш., 101, кв.101",
"city": "Ленинград",
"postalCode": 101101
},
"phoneNumbers": [
"812 123-1234",
"916 123-4567"
]
}
<person>
<firstName>Иван</firstName>
<lastName>Иванов</lastName>
<address>
<streetAddress>Московское ш., 101, кв.101</streetAddress>
<city>Ленинград</city>
<postalCode>101101</postalCode>
</address>
<phoneNumbers>
<phoneNumber>812 123-1234</phoneNumber>
<phoneNumber>916 123-4567</phoneNumber>
</phoneNumbers>
</person>
DOM парсеры не распарсят нам данные файлы, пока в первом случае мы не получим последнюю скобочку }, а во втором тег < /person>
DVM (2013-09-17 11:44:00) [52]
> _guest_ (17.09.13 11:25) [27]
> Я не силен в этом, и мне не очень понятно зачем нужен "потоковый"
> парсер. Если данные приходят кусками, а так оно и есть,
> то: пришли данные, распарсили их обычным, не потоковым парсером,
> полученные данные сохранили.
Потоковый парсер или SAX парсит данные по мере поступления, в отличие от DOM парсера который строит некоторую структуру (дерево) в памяти из элементов. Первый не потребляет памяти вообще и работает быстро, т.к. просто из потока данных вычленяет элементы и отдает их в событиях. Что делать с найденными элементами решать тому кто парсер использует, либо отбрасывать, либо сохранять где то. Преимущество такого парсера - он может обработать сравнительно быстро любой объем данных при незначительном потреблении памяти.
DOM парсер же потребляет памяти пропорционально размеру входных данных и результат его работы мы увидим только после того, как он полностью распарсит данные, а распарсит он их только когда закроется последний тег и в стеке его тегов не останется ничего. Тогда он нам выплюнет дерево. Очевидно, что в большом документе это будет только тогда, когда мы его считаем весь.
_guest_ (2013-09-17 11:25:00) [53]
> DVM © (17.09.13 11:14) [26]
Я не силен в этом, и мне не очень понятно зачем нужен "потоковый" парсер. Если данные приходят кусками, а так оно и есть, то: пришли данные, распарсили их обычным, не потоковым парсером, полученные данные сохранили. Я не знаю что такое SAX, правда. Могу быстренько глянуть в инете для уменьшения своей безграмотности, но для xml куча обычных парсеров. Очевидно, я не уловил того, что Вы хотели донести в [24], каких то особенностей работы. Или имеется ввиду обработка в другом потоке для уменьшения времени работы? Если можно, то чуть подробнее.
DVM (2013-09-17 11:14:00) [54]
> _guest_ (17.09.13 10:54) [25]
> Какой-то json парсер есть прямо в делфи по крайней мере
> в 2010.
Я не видел JSON парсеров которые бы работали так как я описал. Да и с XML то не густо, писал сам для ограниченного применения такой.
_guest_ (2013-09-17 10:54:00) [55]
> DVM © (17.09.13 10:40) [24]
Какой-то json парсер есть прямо в делфи по крайней мере в 2010. И в финале, так и будет, как Вы описали. Со дня на день пересяду с 2007 на xe. Проблема не в этом. Вот прямо сейчас мне без разницы распарсенные у меня данные или нет (уберутся всякие скобочки и вместо двоеточия будет стоять равно), если они разные по составу, а максимально возможного состава я не узнаю, пока не получу их все.
DVM (2013-09-17 10:40:00) [56]
> _guest_ (17.09.13 10:23) [21]
Если ты говоришь, что это JSON, и он грузится долго, то имеет смысл обрабатывать его на лету по мере загрузки. Для этого нужно будет разработать потоковый JSON парсер по аналогии с SAX парсером для XML. Я бы так и поступил. Получили кусок данных отдали парсеру - он выплюнул нужные нам данные, потом следующий кусок и так далее. Это если по уму делать.
_guest_ (2013-09-17 10:37:00) [57]
> Sha © (17.09.13 10:24) [22]
Да я согласен, конечно. Только мне не посчитать, а упорядочить эти данные надо, а они, как я уже говорил, неоднородные. Где-то есть такое значение, где-то нет, но есть другое, которого нет еще где-либо - нет жестко заданной структуры. Что при преобразовании в общую таблицу доставляет определенные неудобства. Собственно, я уже придумал как это сделать, работаю над реализацией.
Ветку можно закрывать, направление работы понятно. Получил даже больше, чем хотел :) общение с умными людьми не проходит бесследно. Всем большое спасибо.
Sha (2013-09-17 10:24:00) [58]_guest_ (17.09.13 10:23) [21]
Очевидно, что если надо посчитать сумму большого объема данных,
то нет смысла сначала грузить их стринглист, а потом считать.
Похожим образом можно поступить и для поквартальных сумм.
Довольно редко попадаются так зависимые данные,
чтобы была абсолютно необходима их полная загрузка в память.
_guest_ (2013-09-17 10:23:00) [59]
> Sha © (17.09.13 10:05) [16]
> до сих пор не ясно, зачем их держать или зачем держать их все
Да, в общем то, не за чем. От инертности моего мышления. ТЗ нету, состава приходящих данных нету, в смысле "ты сам посмотри, что там приходит", а оно приходит далеко не однородное. Я уже решил разбивать на кварталы [10]. С другой стороны, не каждый же участок сразу в свой файл писать, их же сотни тысяч - даже на харде так хранить не выгодно.
DVM (2013-09-17 10:22:00) [60]
> _guest_ (17.09.13 09:17) [10]
> Да-да. Я в первую очередь FileStream и попробовал, но прироста
> скорости практически не получил. Очевидно, это обусловлено
> тем, что строк много, но они короткие типа "имя":"значение".
> Поэтому при построчной перезаписи преимуществ буферизации
> почти и нет.
Ну именно запись в файл у тебя должна была ускориться при буфере достаточного размера. Но раз ты прироста не заметил, то можно предположить, что узкое место у тебя не запись в файл или ты вообще что-то не так делаешь.