AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Delphi MemoryMapped File Zugriff auf großes XML File...
Thema durchsuchen
Ansicht
Themen-Optionen

MemoryMapped File Zugriff auf großes XML File...

Offene Frage von "pertzschc"
Ein Thema von pertzschc · begonnen am 7. Okt 2009 · letzter Beitrag vom 7. Okt 2009
Antwort Antwort
pertzschc

Registriert seit: 29. Jul 2005
Ort: Leipzig
309 Beiträge
 
Delphi 12 Athens
 
#1

MemoryMapped File Zugriff auf großes XML File...

  Alt 7. Okt 2009, 19:02
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;
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#2

Re: MemoryMapped File Zugriff auf großes XML File...

  Alt 7. Okt 2009, 19:12
Du solltest vielleicht nochmal die Hilfe zu MSDN-Library durchsuchenCreateFileMapping durchgehn.

Die Datei wird da nicht direkt im letzen Parameter übergeben!
Öffne der Datei mit MSDN-Library durchsuchenCreateFile und übergibt CreateFileMapping im 1. Parameter das Datei-Handle.


[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.
$2B or not $2B
  Mit Zitat antworten Zitat
pertzschc

Registriert seit: 29. Jul 2005
Ort: Leipzig
309 Beiträge
 
Delphi 12 Athens
 
#3

Re: MemoryMapped File Zugriff auf großes XML File...

  Alt 7. Okt 2009, 20:08
Zitat von himitsu:
Du solltest vielleicht nochmal die Hilfe zu MSDN-Library durchsuchenCreateFileMapping durchgehn.
Danke für den Tipp, das hat geholfen.

Zitat von himitsu:
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),
Nun das verstehe ich nicht ganz. Du kannst dem XMLScanner mittels SetBuffer() einen Pointer geben und das LoadFile weglassen.

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
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#4

Re: MemoryMapped File Zugriff auf großes XML File...

  Alt 7. Okt 2009, 21:19
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.
$2B or not $2B
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:14 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz