:: Visual Foxpro, Foxpro for DOS
BigData: Обработка XML-файла размером 3,141,829,712 байт
rvc44
Автор

Сообщений: 2211
Откуда: Тамбов
Дата регистрации: 06.12.2005
Приветствую, коллеги!

Появилась задача распарсить XML-файл размером 3,141,829,712 байт.
Естественно, что из-за ограничений функции FileToStr не будет работать конструкция вида:

lcXMLFile = 'C:\FOX\data-20190116T0000-structure-20151217T0000.xml'
lcResponseText = FileToStr(lcXMLFile)

Функция FOPEN тоже не подойдет, поскольку она работает с файлами до 2Гб, после чего сбивается навигация по FSEEK.
Решил попытать удачу через API, используя вот эти функции:

DECLARE INTEGER CreateFile IN kernel32;
STRING lpFileName, INTEGER dwDesiredAccess,;
INTEGER dwShareMode, INTEGER lpSecurityAttributes,;
INTEGER dwCreationDisposition,;
INTEGER dwFlagsAndAttributes, INTEGER hTemplateFile
DECLARE INTEGER ReadFile IN kernel32;
INTEGER hFile,;
STRING @ lpBuffer,;
INTEGER nNumberOfBytesToRead,;
INTEGER @ lpNumberOfBytesRead,;
INTEGER lpOverlapped
DECLARE INTEGER SetFilePointer IN kernel32;
INTEGER hFile,;
INTEGER lDistanceToMove,;
INTEGER lpDistanceToMoveHigh,;
INTEGER dwMoveMethod
DECLARE INTEGER GetLastError IN kernel32
DECLARE INTEGER CloseHandle IN kernel32 INTEGER hObject

Всё бы замечательно, но у функции REPLICATE также ограничение на максимальную строку в 16,777,184 байт
То есть 20-ти мегабайтный буфер уже не создашь, не говоря про буфер размером 3,141,829,712 байт.
При выделении памяти под буфер большого размера, решил прибегнуть к хитрости, которую рекомендовал Rick Strahl:

lcBuffer = ""
&& 3141829712 / 15000000 = 209.46
For lnI = 1 To 210
lcBuffer = lcBuffer + REPLICATE(Chr(0), 15000000) && 15,000,000 из max 16,777,184
EndFor

Вот на этой строке вываливается ошибка Fatal error C0000005
Может буфер тоже выделять с помощью API-функций? Но там тоже непонятно, как в него/из него строку копировать

lnSize = 3141829712
lhMem = GlobalAlloc(GMEM_FIXED, lnSize)
If lhMem <> 0
= StrToMem(lhMem, @lcString, lnSize)
EndIf
* ...
If lhMem <> 0
= GlobalFree (lhMem)
EndIf

Опять будет Fatal error C0000005 при попытке копирования скроки lcString.
LocalAlloc будет работать с таким размером буфера? Полагаю, вряд ли.
Какие будут соображения?



Исправлено 1 раз(а). Последнее : rvc44, 17.01.19 16:56
Ratings: 0 negative/0 positive
Re: BigData: Обработка XML-файла размером 3,141,829,712 байт
of63

Сообщений: 25254
Откуда: Н.Новгород
Дата регистрации: 13.02.2008
SAX-ом надо такой XML читать, потегово, пусть сам SAX-механизм выделяет буфер, большого буфера ему и не надо, размером в самое длинное содержимое тега ему достаточно.
Ratings: 0 negative/0 positive
Re: BigData: Обработка XML-файла размером 3,141,829,712 байт
rvc44
Автор

Сообщений: 2211
Откуда: Тамбов
Дата регистрации: 06.12.2005
А из под VFP можно SAX дергать? Ни у кого нет примеров, как это делать?
Недавно Игорь Королёв демонстрировал мастер-класс по использованию SAX из VFP, чтобы сделать beautify XML-файла:

lcXMLFile = "C:\MyFolder\Request1_12345678964.xml"
lcNewFile = "C:\MyFolder\Request.xml"
oWriter = CreateObject("MSXML2.MXXMLWriter.6.0")
oWriter.indent = .T.
oReader = CreateObject("MSXML2.SAXXMLReader.6.0")
oReader.contentHandler = m.oWriter
oReader.putProperty("http://xml.org/sax/properties/lexical-handler", oWriter)
lcXMLText = FileToStr(lcXMLFile)
oReader.parse(lcXMLText)
StrToFile(oWriter.output,lcNewFile,.T.)

Для использования SAX в VFP есть много непонятным моментов, например, как установить обработчик событий SAX-паресера contentHandler или как установить обработчик ошибок errorHandler.



Исправлено 1 раз(а). Последнее : rvc44, 17.01.19 17:39
Ratings: 0 negative/0 positive
Re: BigData: Обработка XML-файла размером 3,141,829,712 байт
of63

Сообщений: 25254
Откуда: Н.Новгород
Дата регистрации: 13.02.2008
У меня нет. Использую самодельный (читает последовательно файл через буфер небольшой, вызывает подпрограмму обработки на каждый тэг). Громоздкий велосипед получился )
Ratings: 0 negative/0 positive
Re: BigData: Обработка XML-файла размером 3,141,829,712 байт
rvc44
Автор

Сообщений: 2211
Откуда: Тамбов
Дата регистрации: 06.12.2005
Всё-таки FoxClub - лучший в мире сайт! Пошел читать forum.foxclub.ru
Ratings: 0 negative/0 positive
Re: BigData: Обработка XML-файла размером 3,141,829,712 байт
AndyNigmatec

Сообщений: 1573
Откуда: Волгоград
Дата регистрации: 28.06.2015
А такая фигня типа:

xmlDoc=CREATEOBJECT("MSXML2.DOMDocument")
xmlDoc.async = .F.
IF xmlDoc.Load(lcXmlFile)
node_List = xmlDoc.selectNodes("*//ITEM")
* ?node_List.Length
*-- цикл по результирующему набору
FOR intIndex = 1 TO node_List.Length
xmlNode = node_List.Item(intIndex-1).CloneNode(.T.)
m.kcode=xmlNode.getElementsByTagName("XXXXXX").Item(0).text
m.name=xmlNode.getElementsByTagName("YYYYYY").Item(0).text
...
ENDFOR
ELSE
* lcok=0
* echo1('load - false')
ENDIF
RELEASE xmlDoc


не прокатит?



Исправлено 1 раз(а). Последнее : AndyNigmatec, 17.01.19 19:34
Ratings: 0 negative/0 positive
Re: BigData: Обработка XML-файла размером 3,141,829,712 байт
rvc44
Автор

Сообщений: 2211
Откуда: Тамбов
Дата регистрации: 06.12.2005
[attachment 30550 XML-Error.jpg]

Увы, не прокатывает! Честно попробовал. Минут 25 висели песочные часы.
Нужно отметить, что аналогичный маленький файл всего с двумя записями за сотую долю секунды, причем корректно обрабатывает.



Исправлено 2 раз(а). Последнее : rvc44, 17.01.19 22:32
Ratings: 0 negative/0 positive
Re: BigData: Обработка XML-файла размером 3,141,829,712 байт
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
AndyNigmatec
А такая фигня типа:
...
не прокатит?
Конечно же нет. Даже для в 10 раз более мелкого файла (всего каких-то смешных 300Мб) скорее всего не хватит памяти. DOM грузит весь файл целиком, при том ещё и создаёт из банальных 20-50 символов XML-я полноценный объект на сотни, если не тысячи байт.
Вообще тому кто придумал складывать в XML по 3Гб данных "надо гвоздь в голову забить"


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: BigData: Обработка XML-файла размером 3,141,829,712 байт
of63

Сообщений: 25254
Откуда: Н.Новгород
Дата регистрации: 13.02.2008
И еще тому, кто придумал создавать DOM в памяти, а не в файле...
Ratings: 0 negative/0 positive
Re: BigData: Обработка XML-файла размером 3,141,829,712 байт
rvc44
Автор

Сообщений: 2211
Откуда: Тамбов
Дата регистрации: 06.12.2005
Насчет гвоздя полностью поддерживаю! ))
Вот результаты работы через SAX, спустя 18 минут после начала обработки:

[attachment 30551 IsTooLarge.png]

Уже лучше! Попробую не в DBF писать, а в CSV, чтобы потом в Excel подгрузить или сделать фильтр по региону и разбить на несколько мелких файлов. В результате работы SAX-парсера создался DBF-файл размером 2,147,482,057 байт, включающий 523648 записей. Каждая запись состоит из 41 символьного поля. Каждое символьное поле диной 100 символов (можно уменьшить размеры полей), поскольку никакого описания структуры файла не было.



Исправлено 1 раз(а). Последнее : rvc44, 18.01.19 09:32
Ratings: 0 negative/0 positive
Re: BigData: Обработка XML-файла размером 3,141,829,712 байт
AndyNigmatec

Сообщений: 1573
Откуда: Волгоград
Дата регистрации: 28.06.2015
Если не сложно, можете здесь выложить как именно через SAX ... чую тож придется по гвоздю плакать )))
Ratings: 0 negative/0 positive
Re: BigData: Обработка XML-файла размером 3,141,829,712 байт
of63

Сообщений: 25254
Откуда: Н.Новгород
Дата регистрации: 13.02.2008
() Если задача разовая (принимать файл стабильной структуры), то можно написать приемник (детектор известных тегов) на основе API-функций в первом посте, и записывать результат в текстовый файл любого размера (теми же API-функциями), или в ДБФ нужной структуры (если результат влезает в 2Г)...
Ratings: 0 negative/0 positive
Re: BigData: Обработка XML-файла размером 3,141,829,712 байт
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
Ну сделай в процедуре переключалку на новую таблицу, скажем, каждые 200к записей - потом уж по отдельности их окультурь, может конечный результат и в одну уместится


------------------
WBR, Igor
Ratings: 0 negative/0 positive


Извините, только зарегистрированные пользователи могут оставлять сообщения в этом форуме.

On-line: 32 leonid  (Гостей: 31)

© 2000-2024 Fox Club 
Яндекс.Метрика