![]() |
MemoryMapped File Zugriff auf großes XML File...
Hallo zusammen,
ich habe ein ziemlich großes XML File, welches ich mittels MMF häppchenweise einem SAX Parser unterschieben möchte. D.h. der SAX Parser bekommt einen Puffer und geht dann Char für Char weiter beim Parsen. Den Puffer möchte ich aus einem MMF bedienen, so dass nicht immer das komplette File in den RAM geladen wird. Ich habe mir dazu mal 2 Methoden erstellt, die rudimentär den Zugriff machen sollen. Mein Problem ist, dass hFile immer 0 ist. Woran könnte es liegen? Danke+Gruß, Christoph
Delphi-Quellcode:
function TForm1.ReadFromMMF(Filename: PChar; Len: Int64): Pointer;
var hFile: Cardinal; begin hFile := CreateFileMapping($FFFFFFFF, nil, PAGE_READONLY, 0, Len, Filename); // das geht immer schief, file existiert aber auf platte! if hFile <> 0 then begin try Result := MapViewOfFile(hFile, FILE_MAP_READ, 0, 0, 0); finally //CloseHandle(hFile); end; end else begin Result := nil; end; end; procedure TForm1.btn1Click(Sender: TObject); var CurrTxt: PChar; FileName, Msg: string; begin // lade xml file.. FileName := ExtractFilePath(Application.ExeName) +'liste_cmg.xml'; CurrTxt := Self.ReadFromMMF(PChar(FileName), 2000); // nachfolgend nur dummycode, später zuweisung auf buffer des SAX Parsers if Assigned(CurrTxt) then begin StrLCopy(PChar(Msg),CurrTxt, 10); ShowMessage(Msg); // CopyMemory(CurrTxt, Data, Len); end; end; |
Re: MemoryMapped File Zugriff auf großes XML File...
Du solltest vielleicht nochmal die Hilfe zu
![]() Die Datei wird da nicht direkt im letzen Parameter übergeben! Öffne der Datei mit ![]() [add] aber ganz im Ernst ... nach dem Durchsehn der Unit LibXmlParser.pas kann ich nur eines Sagen Es wäre einfacher den Puffer direkt zu laden (MMF ist hier garnicht nötig und viel zu umständlich), aber es ist nahezu unmöglich dieser Komponente einen sich bewegenen Puffer unterzuschmuggeln und so die speicherbedingte Größenbegrenzung zu umgehen. "sich bewegend" = da du den Puffer nur an bestimmten (freien) Stellen im Arbeitsspeicher ablegen kannst und somit, beim Nachladen weiterer Daten, die Zugriffszeiger (Pointer) jedesmal anpassen mußt. Probleme: - es gibt nicht nur einen zentralen Zeiger (sondern viele kleiner und teilweise sind das lokale Funktions-Parameter - du hast keine richtige Kontrollmöglichkeit, um zu prüfen wo im Puffer die Funktionen im Moment wirklich sind und welche Daten nun entfernt werden können und (wichtiger) welche Daten noch nötig sind PS: Ich hab selber Monate gebraucht, bis mein System zum Nachladen der Daten halbwegs lief und hab die ganzen Parsingfunktionen auch daraufhin ausgelegt. Du willst hier soein System nachrüsten und das in eine Struktur, welche darauf nicht ausgelegt ist und an vielen Stellen sogar ein solches System nicht (oder nur mit größerem Aufwand) unterstützen würde. |
Re: MemoryMapped File Zugriff auf großes XML File...
Zitat:
Zitat:
Ich hatte es so verstanden, dass ich mittels MMF bei Zugriff auf jenseits der geladen Chars im Buffer automatisch weitere nachgeladen bekomme. Ist das falsch? Warum also nicht den Pointer mittels MMF bereitstellen? Gruß, Christoph |
Re: MemoryMapped File Zugriff auf großes XML File...
Du kannst im so einen GANZEN Puffer geben, aber wenn du vor hast via MMF die Daten "stückchenweise" Nachzuladen, dann geht das dann nicht mehr.
Es sei denn du mappst die komplette MMF in den Arbeitsspeicher und übergibst davon den Pointer, aber dann hast du nichts gekommt, da du dann wieder allles an einem Stück haben mußt, womit du ja auch so schon Probleme hast. Du müßtest also erstmal nur einen Teil der Datei mappen, dieses vom Parser parsen lassen und sobald der Parser an das Ende dieses Stücks kommt, müßtest du den nächten Teil der Datei in den Speicher mappen und den letzen vorher Teil entladen (damit du wieder genügend Speicher hast) Dafür müßtest du aber erstmal wissen, wann der Parser das Ende dieses Stücks erreicht, den Parser dort anhalten lassen, den Speicher ändern und die neuen Teile nachladen, dann die ganze Zeiger auf die Positionen im neuen Speicher verschieben und ab da den Parser weiterlaufen lassen, bis er wieder das Ende dieses Speicherblocks erreicht hat oder das komplette Ende der Datei. Dieser Parser ist aber so ausgelegt, daß er zwischendurch nicht in einem definierten Zustand anhält, sondern nonstop bis zum Dateiende ließt. Du hast es also nicht leicht den Parser definiert anhalten zu lassen, wenn er das Blockende erreicht. (das dürfte sich aber noch relativ leicht ändern lassen, da er ja schön sequentiell/linear arbeitet) Den Speicher austauschen dürfte noch leicht fallen, wenn man es sich einfach macht un die Blockgrößen begrenzt (also die maximale Länge der Nodes, Attribute und vom NodeText). Aber nun kommt das Schwierige ... jetzt mußt du "alle" Zeiger auf den neuen Speicher verschieben und davon gibt es hier genügend. Das ist schließlich der Grund, warum fast alle XML-Parser nur an einem Stück lesen, weil dieses einfach einfach ist. Wie gesagt, ich hab bei meinem Parser schon viel Zeit reinstecken müssen, um da ein funktionales System zu entwickeln. Und ich hab auch extra den Parser dafür ausgelegt, daß er eben an bestimmten Stellen einen ganz fest definierten Zustand einnimmt, wo ich dann leicht an der Speicherverwaltung rumspielen kann. Du kannst ja gern mal in meine Units reinsehn. In der neuen Version (beta) hab ich das alles jetzt mal abgekapselt und in die eigenständige Klasse TXReader (unit himXML.pas) verfrachtet und diese Klasse ist praktisch nur mit der Speicherverwaltung beschäftigt (bis auf die Funktion .Parse und die Hilfsprozedur .CloseSingleNode) ... also das Nachladen, Freigeben und Zerlegen der Daten. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:31 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz