Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Dateiinfos lesen (schnellste Variante?) (https://www.delphipraxis.net/203243-dateiinfos-lesen-schnellste-variante.html)

MicMic 27. Jan 2020 23:40

Dateiinfos lesen (schnellste Variante?)
 
Hallo,
ich muss so schnell es geht Dateiinfos lesen.
Also z.B. die Bildgröße von Grafikdateien. JPG geht schon mal und beim NEF (Nikon RAW) bekomm ich noch 160x120.
Da muss ich wohl im Abschnitt "4.1 IFD#0, subIFD#0" lesen. (http://lclevy.free.fr/nef/). Wie muss ich noch schauen.

Aber gehe ich richtig davon aus, dass ich hier stets den Header immer lesen muss, wenn es schnell gehen soll? Ich habe schon weiter geschaut, z.B. bei MP4 (für Videogröße). Viel gelesen habe ich nicht, weil wieder alles in Englisch ist. Aber hier scheint es schon recht schwer zu werden. Auch will ich immer neue Dateitypen hinzufügen. Zum Beispiel die Anzahl von Seiten eines PDF-Dokuments oder die Musiklänge von MP3 Dateien.

Geht's auch einfacher? :) Oder muss ich hier doch immer neuen Dateitypen studieren, damit ich die Infos herauslesen kann, so wie ich sie möchte. Es gibt ja tausende Dateitypen... je nach Sinn und Zweck sollen immer wieder neue in mein Programm dazukommen.

Vielleicht hat ja jemand eine super Idee für mich? :)

hoika 28. Jan 2020 00:18

AW: Dateiinfos lesen (schnellste Variante?)
 
Hallo,
ich muss so schnell es geht Dateiinfos lesen.
Also z.B. die Bildgröße von Grafikdateien

z.B.
ist leider so nichtssagend, weil je Dateiormat wohl verschiedene Infos gewünscht werden (?)

immer wieder neue
Baue Plugins pro Dateityp, die die gewünschten Informationen ermitteln,
und schon ist es erweiterbar.

himitsu 28. Jan 2020 01:01

AW: Dateiinfos lesen (schnellste Variante?)
 
Im Explorer nisten sich manche Plugins ein, welche sowas anzeigen und als Spalte anzeigen können, oder die eine Seite/Tabsheet im Eigenschaftendialog der Datei darstellen.
Ich hoffe mal die lesen auch nur die Headerinfos aus, anstatt die Datei zu laden.
Nur den Wert der Spalten zu laden wird wohl einfacher sein, als ein ganzes Tabsheet, sich dort durch die Controls zu kämpfen und deren Werte rauszusuchen.

Im Prinzip kann man all diese Plugins auflisten, sich die passenden raussuchen (welche Spalten kommen von dort) und jenes Plugin dann dann selbst aufrufen/ausführen.



Ansonsten gibt es auch grlßer Image-Libraries, die Infos zu vielen Dateiformaten lieferen, können.



Im Linux gibt es eine Consolenanwendung, die Dateiinfos anzeigt (hab vergessen wie die heißt, aber kennt hier bestimmt wer),
das Ding ist OpenSource und man könnte deren innere Funktion es bestimmt auch nach Pascal übersetzen,
aber da in Windows 10 sich nun auch ein Linux-Subsystem installieren und dessen Programme sichwie die Windows-Konsolenanwendungen aufrufen lassen ... die Vermutung besteht nun, dass dieses Programm dort auch drin ist, oder sich zumindestens nachinstallieren lässt.
Das Ding parst scriptmäßig die Dateiheader und gibt verschiedenste Infos als Text raus, darunter auch die Bild-Größe vieler Dateiformate.

[edit] "file" war es, glaub ich :angle:
https://superuser.com/questions/2755...x-command-line

MicMic 28. Jan 2020 22:56

AW: Dateiinfos lesen (schnellste Variante?)
 
Da ich ja immer wieder Infos aus neue Dateitypen lesen möchte, habe ich auch schon daran gedacht, dies als Plugin zu machen. Wie, weiß ich noch nicht. Aber das ist ja die 2. Anlaufstelle. Erst mal muss ich ja einen Datei-Header richtig lesen können. Dafür braucht man Dokumentationen und natürlich "das können" :)

Ich scheitere schon beim NEF-Format.
Es baut ja auf TIFF auf aber für mich ist das alles noch nicht so einfach.

Ich muss ja von (http://lclevy.free.fr/nef/) den Abschnitt "4.2 IFD#0, subIFD#1" lesen. Aber schaffe nur den Abschnitt "3. IFD#0" … was mir ein wenig klarer erscheint durch eine TIFF-Dokumentation.

Jedenfalls lese ich die Anzahl Tags und in der For-Schleife immer 12 Bytes. So kann hier der Abschnitt "3. IFD#0" gelesen werden.

Hier mal bissl Code. Bin ein wenig am herumprobieren aber hier mal das Zeugs für den normalen IFD Abschnitt. Den eigentlichen Aufbau habe ich im Netz gefunden und probiere gerade herum.

Code:
Type
  TTifHeader = Record
     Signature : Word;  
     Version   : Word;  
     IFD       : DWord;
  End;
  TIDF_Field  = Record
    Tag      : Word;
    FieldType : Word;
    ValCount : DWord;
    ValOffset : DWord;
  End;

VAR
  TifFile   : TFileStream;
  Header    : tTifHeader;
  DirEntries : Word;
  Field     : TIDF_Field;
  Cnt       : Integer;

  TifFile := TFileStream.Create (sFileName, fmOpenRead);
  Try
    TifFile.Read ( Header,8);
    // Prüfen auf TIFF Format (Ist bei NEF gleich)
    If ((Header.Signature = $04949) And (Header.Version = $0002A)) Or
       ((Header.Signature = $04D4D) And (Header.Version = $02A00)) Then
    Begin
      TifFile.Position := Header.IFD;
      TifFile.Read ( DirEntries, 2 ); // Anzahl Tags im ersten IFD
      For Cnt := 1 To DirEntries Do
      Begin
        TifFile.Read (Field,12);
        Case Field.Tag OF
          $0100 : iWidth := Field.ValOffset;
          $0101 : iHeight := Field.ValOffset;
          //  34665  : Break;
        End;
        // If (iWidth<>0) and (iHeight<>0) Then Break;
      End;
    End;
  Finally
    FreeAndNil ( TifFile );
  End;

Gausi 29. Jan 2020 09:30

AW: Dateiinfos lesen (schnellste Variante?)
 
Da du auch mp3 ansprichst: da gibt es keine einfache und schnelle Methode, die zu 100%ig die richtigen Ergebnisse liefert. Ein Grund ist, dass es im MP3-Dateiformat keinen Header im eigentlichen Sinne gibt. Am Anfang kann der ID3v2-Tag stehen (hat mit Spieldauer in fast allen Fällen nichts zu tun), direkt der erste MPEG-Frame (der hat dann einen Header, der aber auch wenig bis nichts über die Dauer des Stückes aussagt), oder einfach ein paarhundert Nullbytes (z.B. durch einen Quick&Dirty gelöschten ID3v2-Tag). Der erste MPEG-Frame kann dann ein XING-oder INFO-Header sein, in dem die Anzahl der Frames stehen können, die für die Berechnung der Dauer sinnvoll sein kann (ein MPEG-Frame hat eine klar definierte Dauer) - besonders bei Dateien mit variabler Bitrate. Dort ist meistens so ein XING-Header drin, muss aber nicht. Diese Frame-Anzahl muss aber nicht mit der tatsächlichen Anzahl an Frames in der Datei übereinstimmen. Eine Kontrollmöglichkeit ist dort nicht vorgesehen ... kurz: Spieldauer von MP3-Dateien ist ein Krampf. :lol:

Ich habe hier z.B. ein Album, das ursprünglich in eine Datei gerippt wurde. Dabei wurde ein INFO-Header eingefügt, der die Frame-Anzahl angibt. Diese 60-Minuten-Datei wurde dann nachträglich geschnitten, ohne dass der Info-Header angepasst wurde, sodass dieser nur beim 1-Minuten-Intro stehen blieb, was bei der Berechnung der Dauer dann zu Fehlern führt. Könnte man durch eine Heuristik abfangen, weil dann (wegen der kleinen Dateigröße) die daraus folgende Bitrate unmöglich richtig sein kann, aber .... nun ja.

Dafür gibt es einige Libraries, die viele Fälle ganz gut abfangen (das genannte kaputt geschnittene Album allerdings nicht). z.B. die ID3Lib von Muetze1 oder meine Mp3FileUtils, die später zur AudioWerkzeugeBibliothek erweitert wurden, mit der man mit wenigen Zeilen Code die Spieldauer von recht vielen Audioformaten auslesen kann.

Wenn aber Menschenleben davon abhängen hilft bei MP3 nur, die ganze Datei zu parsen.

jobo 29. Jan 2020 10:41

AW: Dateiinfos lesen (schnellste Variante?)
 
Dir wird wohl nichts anderes übrig bleiben, als die Infos, die Du anzeigen willst, Stück für Stück aus den Files zu kitzeln (meist).
Im Extremfall ist das aufwändig und es entstehen (schon betriebssystemseitig) Hilfskonstruktionen wie z.B. die Thumbnails Dateien für Bilder oder formatspezifisch eben das, wo Du gerade baggerst, Headerinfos oder auch Embedded Preview Images. (nebenbei, solche Mechanismen kannst Du natürlich auch nutzen-also mühsam erungene Dateiinfos puffern, solange die Datei unverändert bleibt)
Wenn du das so schnell es geht auslesen möchtest finde ich das schon mal löblich. Man sieht trotz dieses relativ selbstverständlichen Gedankens immer wieder schlechte Lösungen, die auch noch so frech sind, sich im Explorer einzuzecken und die Anzeige eines Ordners zum Geduldspiel werden lassen.
Wie auch immer die formatspezifische Implementierung bei Dir aussehen wird, ich empfehle Dir Multithreading sowie Nebenläufigkeit als Implementierungsbasis des Gesamtprozess. Dass man nicht ungefragt vorhandene (Ordner)Einstellungen überschreibt, sollte ja selbstverständlich sein.

KodeZwerg 29. Jan 2020 12:03

AW: Dateiinfos lesen (schnellste Variante?)
 
Ich nutzte damals mehrere 4KB puffer, datenköpfe einlesen, parallel die puffer nach headern/signaturen prüfen, die dann wiederum an entprechende implementierungen weitergeleitet wurden.
Spezialfall bei mir waren halt die typen wo infos eher am dateiende hinterlegt sind. Da ging ich genauso vor allerdings mit 8 - 10 kb puffer und hab meine signaturen rückwärts gegengeprüft.
Am schlimmsten sind multimedia daten die sich aus den vorhanden chunks zusammensetzen und aufgerechnet werden müssen, die hab ich außen vor gelassen. (realmedia war des glaube ich)

edit
Am schlimmsten...*
sind auch dateien die nur über sprungziele zum ergebnis führen und mittendrinn "kaputte" vorkommen. Diesen fall hatte ich bei Entwicklung nicht berücksichtigt, also das sollte auch gecheckt werden nicht das man übers dateiende hinaus was lesen mag :-)

MicMic 31. Jan 2020 12:16

AW: Dateiinfos lesen (schnellste Variante?)
 
Naja, noch probiere ich ein wenig herum an verschiedenen Dateitypen aber werde wohl schon für andere Ideen Ausschau halten :)
Es kommt ja auch noch dazu, dass es zu manchen Dateitypen noch verschiedene Versionen gibt. Dies muss man alles prüfen. Also doch viel viel Arbeit wenn man es richtig machen will. Danke für Eure Tipps und Anregungen.

Gruß Mike

Luckie 31. Jan 2020 12:37

AW: Dateiinfos lesen (schnellste Variante?)
 
Wozu brauchst du das denn?

KodeZwerg 31. Jan 2020 12:45

AW: Dateiinfos lesen (schnellste Variante?)
 
Ps: Je nach Anzahl der Dateien könnte es schneller über CreateFile / THandleStream abgearbeitet werden, da die Daten von Windows (soweit ichs in Erinnerung habe) nicht gecached werden... einfach mal rumprobieren / benchen.

himitsu 31. Jan 2020 15:09

AW: Dateiinfos lesen (schnellste Variante?)
 
TFileStream und auch alles andere im Delphi arbeitet ebenfalls mit nur CreateFile.
Und da nirgendwo explizit angegeben wird, dass dort der Cache deaktiviert werden soll, wird somit immer durch den Cache gegangen, auch wenn es sich um einen Datenträger mit deaktivertem Schreibcache handelt, geht es erst durch den Cache des Windows, nur wird da dann eben sofort das Speichern angestoßen.

Also eher andersrum. Man müsste den FileCache deaktivieren, aber dann musst du aufpassen, dass du nur komplette Sektoren ausliest, weil sonst knallt es.
Dann wäre das (einmalige) Lesen extrem vieler und/oder großer Dateien schneller, welche nicht in den Cache (RAM) passen würden, also wo der Cache ständig nachladen und rauswerfen muß und wobei vor allem der Programmspeicher kräftig ausgelagert wird.

Bzw. man könnte zumindestens dem Cache sagen, dass man nur vorwärs liest (kein Random-Access) und womit "theoretisch" der Cache dafür sein Verhalten optimieren könnte.
(Bauchgefühl bemerkt dabei allerdings keinen Unterschied, aber theoretisch könnte der Cache dabei wissen, dass man diese gecachten Daten nur einmal braucht, kann sie sofort nach dem Zugrif wieder entladen, anstatt andere Dinge aus dem RAM zu werfen, wie wenn er nur nach dem Alter/letzter Zugriff der Daten ginge)

FILE_FLAG_SEQUENTIAL_SCAN
FILE_FLAG_NO_BUFFERING
FILE_FLAG_WRITE_THROUGH


Alle Zeitangaben in WEZ +1. Es ist jetzt 18:53 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