Delphi-PRAXiS
Seite 1 von 5  1 23     Letzte »    

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Delphi Binärdatei Record auslesen\zuweisen (https://www.delphipraxis.net/196036-binaerdatei-record-auslesen%5Czuweisen.html)

EWeiss 17. Apr 2018 12:10


Binärdatei Record auslesen\zuweisen
 
Der record..
Delphi-Quellcode:
  TSTChannel = record
    ID         : Integer;
    streamName : Array [0..250] of AnsiChar;
    freq       : single;
    volume     : single;
    pan        : single;
    mute       : byte;
    solo       : byte;
    duration   : Integer;
    percent    : Integer;
    grouplevel : single;
    led        : byte;
    rMeterValue : single;
    reserved   : Array [0..25] of AnsiChar;
  end;
Wenn ich die Datei öffne dann ist FileSize = Buffersize, die Bytes die gelesen wurden sind genauso groß.
Aber irgendwie bekomme ich nicht die werte die eigentlich zurück geliefert werden müssten.

Wenn ich das Array des streamName vergrößere funktioniert so gut wie gar nicht.

warum hat das so einen Einfluss?
Eigentlich dürfte es doch egal sein wie groß der Speicher für den Namen zugewiesen wird.
Delphi-Quellcode:
streamName : Array [0..MASX_PATH] of AnsiChar;


Wieder so ein Mysterium für mich.

gruss

DeddyH 17. Apr 2018 12:15

AW: Binärdatei Record auslesen\zuweisen
 
Wo kommt die Datei denn her? Schreibst Du die selbst? Hilft es evtl., den Record als packed zu deklarieren?

EWeiss 17. Apr 2018 12:18

AW: Binärdatei Record auslesen\zuweisen
 
Zitat:

Zitat von DeddyH (Beitrag 1399519)
Wo kommt die Datei denn her? Schreibst Du die selbst? Hilft es evtl., den Record als packed zu deklarieren?

Nein ich schreibe sie nicht selbst. (noch nicht) ;)
Ich kenne nur die Definition.

Und öffne sie so.
Delphi-Quellcode:
var
  Channel: array[1..MAXCHANNEL] of TSTChannel;
Delphi-Quellcode:
    fHandle := CreateFile(PWideChar(sFile), GENERIC_READ, 0, nil, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
    if (fHandle <> INVALID_HANDLE_VALUE) then
    begin
      FillChar(Channel, sizeof(TSTChannel) * MAXCHANNEL, 0);

      BufferSize := sizeof(TSTChannel) * MAXCHANNEL;
      FileSize := GetFileSize(fHandle, @FileSize);
      if (FileSize = INVALID_HANDLE_VALUE) then
        FileSize := 0;

      if (FileSize div sizeof(TSTChannel) = 8) then
        BufferSize := FileSize;

      if (FileSize < BufferSize) then
        BufferSize := 0
      else
      bErrorFlag := ReadFile(fHandle, Channel[1], BufferSize, dwBytesReaden, nil);

      CloseHandle(fHandle);
    end;
Der wert im Channel[1].Volume müsste 50 sein ist er aber nicht.

gruss

Neutral General 17. Apr 2018 12:18

AW: Binärdatei Record auslesen\zuweisen
 
Zeig mal etwas Code. Bin mir nicht ganz sicher wo dein Problem liegt.
Wenn du das streamName-Array vergrößert rutschen alle anderen Felder im Array entsprechend viele Bytes nach hinten und nichts ist mehr am richtigen Ort.

Woher hast du denn die Record-Definition von TSTChannel? Du hast gesagt du schreibst das Record noch nicht.
Wer schreibt es denn und bist du dir sicher, dass deine Record-Definition richtig ist?

EWeiss 17. Apr 2018 12:21

AW: Binärdatei Record auslesen\zuweisen
 
Zitat:

Zitat von Neutral General (Beitrag 1399521)
Zeig mal etwas Code. Bin mir nicht ganz sicher wo dein Problem liegt.
Wenn du das streamName-Array vergrößert rutschen alle anderen Felder im Array entsprechend viele Bytes nach hinten und nichts ist mehr am richtigen Ort.

Woher hast du denn die Record-Definition von TSTChannel? Du hast gesagt du schreibst das Record noch nicht.
Wer schreibt es denn und bist du dir sicher, dass deine Record-Definition richtig ist?

Ich sagte ich schreibe die Binäre Datei nicht selbst. Oder?

EDIT:
Zitat:

dass deine Record-Definition richtig ist?
Wenn der Filesize die Bytes die gelesen werden und der Buffersize das gleiche sind sollte es stimmen.
Aber wie gesagt kommen falsche werte an.

Wenn ich packed nehme dann ist der Buffersize und Bytesread kleiner wie Filesize.


gruss

Daniel 17. Apr 2018 12:23

AW: Binärdatei Record auslesen\zuweisen
 
Die Felder des Records liegen im Speicher hintereinander. Wenn Du eines der vorderen Felder - z.B. streamName - vergrößerst, rutscht alles Folgende nach hinten. Das ist schon plausibel.
Die Felder des Array können, müssen aber nicht zwingend /direkt/ hintereinander liegen. Das kannst Du mit dem Thema "Alignment" steuern. Oder eben mit dem Schlüsselwort "packed", dann liegt das Zeugs wirklich dicht an dicht im Speicher.
Entscheidend aber ist, dass Du dasselbe Alignment verwendest wie die Software, die die Datei schreibt. Da es letztlich nur 1, 2, 4, und 8 als gängige Möglichkeiten gibt, ist ausprobieren ggf. die schnellste Lösung.

EWeiss 17. Apr 2018 12:33

AW: Binärdatei Record auslesen\zuweisen
 
Zitat:

Zitat von Daniel (Beitrag 1399524)
Die Felder des Records liegen im Speicher hintereinander. Wenn Du eines der vorderen Felder - z.B. streamName - vergrößerst, rutscht alles Folgende nach hinten. Das ist schon plausibel.
Die Felder des Array können, müssen aber nicht zwingend /direkt/ hintereinander liegen. Das kannst Du mit dem Thema "Alignment" steuern. Oder eben mit dem Schlüsselwort "packed", dann liegt das Zeugs wirklich dicht an dicht im Speicher.
Entscheidend aber ist, dass Du dasselbe Alignment verwendest wie die Software, die die Datei schreibt. Da es letztlich nur 1, 2, 4, und 8 als gängige Möglichkeiten gibt, ist ausprobieren ggf. die schnellste Lösung.

Habe es versucht wie gesagt dann verändern sich die Daten im vergleiche zum FileSize.
Hmm.. kann jetzt aber auch nicht sehen was falsch sein könnte.
Die Datei ist von fly-worship 3KB

Danke.

gruss

Zacherl 17. Apr 2018 12:36

AW: Binärdatei Record auslesen\zuweisen
 
Ist nicht das eigentliche Problem, aber
Delphi-Quellcode:
OPEN_ALWAYS
solltest du zu
Delphi-Quellcode:
OPEN_EXISTING
ändern (bei MSDN-Library durchsuchenCreateFile) und bei MSDN-Library durchsuchenGetFileSize statt
Delphi-Quellcode:
INVALID_HANDLE_VALUE
auf
Delphi-Quellcode:
INVALID_FILE_SIZE
prüfen (ist der selbe Wert, nur nicht so verwirrend beim lesen :P). Den zweiten Parameter kannst du hier auch auf
Delphi-Quellcode:
nil
setzen statt
Delphi-Quellcode:
@FileSize
(den Wert überschreibst du ja eh wieder sobald das Resultat der Funktion zugewiesen wird).

Zitat:

Zitat von EWeiss (Beitrag 1399526)
Habe es versucht wie gesagt dann verändern sich die Daten im vergleiche zum FileSize.

Wie meinst du das "im Vergleich zu FileSize"? Welches Alignment hast du probiert?
Delphi-Quellcode:
{$A1}
, also
Delphi-Quellcode:
packed
?

Edit: Kannst du mal die originale (unveränderte) Definition von
Delphi-Quellcode:
TSTChannel
verlinken?

EWeiss 17. Apr 2018 12:44

AW: Binärdatei Record auslesen\zuweisen
 
Zitat:

Welches Alignment hast du probiert? {$A1} , also packed ?
sorry habe vergessen wie man das Alignment zuweist. (Befehl von Delphi)
glaube das hatten wir schon mal.

Das andere werde ich ändern Danke.

Code:
TYPE STChannel
    ID         AS LONG
    streamName AS ASCIIZ * %MAX_PATH
    freq       AS SINGLE
    volume     AS SINGLE
    pan        AS SINGLE
    mute       AS BYTE
    solo       AS BYTE
    duration   AS LONG
    percent    AS LONG
    grouplevel AS SINGLE
    led        AS BYTE
    rMeterValue AS SINGLE
    reserved   AS ASCIIZ * 25 '// Total 320 bytes.
END TYPE
EDIT:
Geänderte Teil
Delphi-Quellcode:
    fHandle := CreateFile(PWideChar(sFile), GENERIC_READ, 0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
    if (fHandle <> INVALID_HANDLE_VALUE) then
    begin
      FillChar(Channel, sizeof(TSTChannel) * MAXCHANNEL, 0);

      BufferSize := sizeof(TSTChannel) * MAXCHANNEL;
      FileSize := GetFileSize(fHandle, nil);
      if (FileSize = INVALID_FILE_SIZE) then
        FileSize := 0;

      if (FileSize div sizeof(TSTChannel) = 8) then
        BufferSize := FileSize;

      if (FileSize < BufferSize) then
        BufferSize := 0
      else
      bErrorFlag := ReadFile(fHandle, Channel[1], BufferSize, dwBytesReaden, nil);

      CloseHandle(fHandle);
    end;
Hab zwei shots angehängt.
Bei Packed ist der ganze Speicher verschoben.

gruss

himitsu 17. Apr 2018 13:07

AW: Binärdatei Record auslesen\zuweisen
 
PS: das "gute" alte
Delphi-Quellcode:
file of TMyRecord
funktioniert immernoch.

Externe Records NIEMALS pur definiert, sondern ausschließlich PACKED oder mit explizitem
Delphi-Quellcode:
{$ALIGN x}
(direkt davor oder über die ganze Datei)
und
Delphi-Quellcode:
{$ALIGN 1} = PACKED
, egal ob Datei, Stream oder sonstwas.
denn du willst ja nicht, dass sich die Ausrichtugn irgendwann mal ändert und es dann nicht mehr zu deiner Datei passt.

Extern = von/nach außerhalb deines Programms.
(mit der Ausnahme, dass wenn die Datei/Stream ausschließlich nur von der eigenen EXE geschrieben/gelesen wird und das nicht über Programminstanzen hinweg)


AnsiChar war schonmal gut (kann auch für UTF-8 genutzt werden) oder eben WideChar, wegen Unicode.
Denn dynamische/compilerabhängige Typen sind auch verboten.


Alle Zeitangaben in WEZ +1. Es ist jetzt 14:23 Uhr.
Seite 1 von 5  1 23     Letzte »    

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