![]() |
Delphi-Version: XE4
Turbo Pascal 6 erzeugte Dateien mit Delphi XE4 lesen
Hallo zusammen,
nach langer Zeit nochmal eine Frage zu Delphi. Ich möchte mit Delphi XE4 alte Dateien lesen/bearbeiten, die mal mit einem Turbo Pascal 6 Programm unter DOS in Form von typisierten Dateien erzeugt wurden. Beispiel der Record-Deklaration unter TP6: T_Settings = Record ID: Byte; Baud: Byte; Line: Byte; TSN1: Byte; TSN2: Byte; TSN3: Byte; TSN4: Byte; TSN5: Byte; TSN6: Byte; Description: String; ConnectionDef: String; end; Die "Byte"-Elemente lassen sich bei entsprechend deklarierten Typ im XE4-Prog auch scheinbar korrekt lesen, die Dateiinhalte vom Typ String allerdings nicht (was ja vermutlich u.a. daran liegt, dass Delphi >= 2009 den Typ String eben als Unicode String behandelt (DBC). Ich habe es jetzt mit folgender Typdeklaration in XE4 versucht: T_Settings_XE4 = Record ID: Byte; Baud: Byte; Line: Byte; TSN1: Byte; TSN2: Byte; TSN3: Byte; TSN4: Byte; TSN5: Byte; TSN6: Byte; Description: ShortString; ConnectionDef: ShortString; end; Diese führt bezüglich der Stringelemente nicht zu richtig zugeordneten Dateninhalten. Ich bis jetzt hier noch keinen Thread gefunden, der dafür eine Lösung hat... Welche Entsprechung hätte heute unter den Gegebenheiten von Delphi >= 2009 (XE4 halt) der TP6-Typ String, um die Daten richtig lesen zu können? Hat da jemand von euch Erfahrung? Gruss, Warp |
AW: Turbo Pascal 6 erzeugte Dateien mit Delphi XE4 lesen
Hallo,
stimmt der String überhaupt nicht, oder sind es die Sonderzeichen (AsciToOem, OemToAsci nehmen). Ausserdem könntest du noch per SizeOf prüfen, ob die Record-Variablen nicht anders ausgerichtet sind (packed record wäre viel. eine Lösung). The ShortString type holds sequences of characters up to 255 in length. Der TP6 String war aber immer ein String[255], probier mal Shortstring[255] (habe gerade keine XE4 hier). Heiko |
AW: Turbo Pascal 6 erzeugte Dateien mit Delphi XE4 lesen
|
AW: Turbo Pascal 6 erzeugte Dateien mit Delphi XE4 lesen
Zitat:
Vor D2009 war String ein Alia für den AnsiString und danach für den UnicodeString. Gaaaaaaanz früher war der String das, was seit Einführung der LongStrings, nun der ShortString ist. String[x] ist ein ShortString mit Längenangabe (maximale Länge). Und String[255] ist der größt mögliche ShortString, also somit direkt der Typ ShortString. Wie sehen denn die binären Daten eines Records in der Datei aus? Bzw. was steht denn nun im ersten Record, nach dem Auslesen? (die Bytes stimmen also, aber was steht in dem ersten String) Eventuell kann man es auch mal mit einem
Delphi-Quellcode:
versuchen, bzw. mit
T_Settings = packed Record
Delphi-Quellcode:
rumspielen.
{$ALIGN ...}
Kann es sein, daß er erste Record noch stimmt, aber die nachfolgenden nicht mehr? Auch das könnte am Align liegen, denn die Daten in deinem Record sind 9*1+2*256 Byte groß. (1 Byte zu groß, für ein Align von 4 oder 8) Du hast nicht zufällig noch TP6 installiert? Wie groß ist dort denn ein SizeOf(T_Settings) und wie groß im Delphi? |
AW: Turbo Pascal 6 erzeugte Dateien mit Delphi XE4 lesen
Erstmal danke für die schnellen Antworten.
@Hoika & Himizu Die Inhalte sind ohne Probleme lesbar, allerdings verschoben. Beginnen also nicht am Anfang des Elements (StringElement[01]), sondern irgendwo in der Mitte. So als wenn "ein Zeiger irgenwo in die Mitte der Daten gegriffen hätte" bei Einlesen der Inhalte. Ich werde das jedenfalls morgen auch noch mal mit ShortString[255] probieren (auch wenn ich meine, der wäre - wie Himizu schon sagt - eh schon mit Länge 255 vorbelegt. Die Ausrichtung kann mir allerdings sicher auch ein Schnippchen schlagen. Ich muss mir die einzeknen Datenverschiebungen noch genauer ansehen. Da haben ja selbst die einzelnen Delphi-Versionen der letzten Jahre ihre Unterschiede. Jede Datei hat übrigens nur einen Record gespeichert. "Verschiebungsbilder" zwischen einzelnen Records dahinter kann es also nicht geben. Ja und die Byteinhalte stimmen halt Byte für Byte, was sich mit einem Hexeditor ja einfach nachprüfen lässt. @Günther Keine Ahnung ob man sie nicht mehr verwenden darf. XE4 compiliert jedenfalls ein solches Konstrukt ohne Probleme durch. Grüsse, Warp |
AW: Turbo Pascal 6 erzeugte Dateien mit Delphi XE4 lesen
Zitat:
|
AW: Turbo Pascal 6 erzeugte Dateien mit Delphi XE4 lesen
Zitat:
> Nimm das PACKED. |
AW: Turbo Pascal 6 erzeugte Dateien mit Delphi XE4 lesen
@Günther
Nicht das das falsch rüberkommt, ich möchte deinen Input (File of Record benutzen "ja/nein") nicht ignorieren o.ä.. Ich will nur erstmal hören, was andere für Erfahrungen mit dem Thema gemacht haben. Was dann als möglicher Weg für mich herauskommt, wird sich dann zeigen (hoffentlich). Mir würde es eventuell schon reichen, wenn ich die vorhandenen alten Daten in ein akuelles (zukunfsträchtigeres) Format konvertieren könnte. Der zu treibende Aufwand entscheidet halt auch (wie immer) mit. Gruss, Warp |
AW: Turbo Pascal 6 erzeugte Dateien mit Delphi XE4 lesen
Zitat:
Leider weiß ich nicht mehr mit welchem Allignment TP6 arbeitet, darum wäre es ganz gut zu wissen was an Daten vorhanden ist. Liegt kein Alignment vor (packed Record) sollte die Daten so aussehen
Ggf. mußt Du ein PackedRecord mit eingeschobenen Dummy-Bytes definieren um das richtige Format zu erreichen. Gruß K-H |
AW: Turbo Pascal 6 erzeugte Dateien mit Delphi XE4 lesen
Ist bekannt, wieviele Datensätze in der alten Datei vorhanden sind ? Wenn ja : teile die Dateigrösse durdh Anzahl Datensätze + 1. Kommt Ganzzahl dabei raus, dann ist das die Datensatzgrösse. Die + 1 kommt daher, weil im Datensatz Nr. 0 eventuell die Datensatz Definition enthalten ist. Dann gehts eben weiter mit tüfteln. Bevor ich aber anfange, einzelne Datensätze zu zerpflücken (wegen Feldgrösse), ist erst mal wichtig, ob das alles überhaupt linear läuft, also bei gleichen Datensatzgrössen oder ob da tatsächlich packed und ähnliche Spezialitäten zum Einsatz kommen. Glaubs eher nicht.
Aber Achtung ! Das Ganze funktioniert nur (wenn überhaupt) mit dateien mit eigener Index-Datei. Zuerst also mal gucken, ob es nur eine Datenbank-Datei gibt, oder ob da noch DATENBANK.IX, *.IDX usw. Dateien vorhanden sind. Bei nur einer datei siehts schlecht aus, |
AW: Turbo Pascal 6 erzeugte Dateien mit Delphi XE4 lesen
Bei einem
Delphi-Quellcode:
gibt es Index-Dateien?
File of Record
Aber nur wenn man die selber gebaut hat und zum Auslesen sind die dann auch nicht wichtig |
AW: Turbo Pascal 6 erzeugte Dateien mit Delphi XE4 lesen
Gerade bei Records gibt es die Index-Daeien. .
|
AW: Turbo Pascal 6 erzeugte Dateien mit Delphi XE4 lesen
Also mir ist auch neu, das es Indexdateien gibt. Zumindest finde ich sie nicht.
Dessenungeachtet würde ich einen vollständig anderen Ansatz verfolgen, der sämtliche eventuell vorhandenen Inkompatibilitäten ausräumt: Lies die Daten per Stream ein:
Delphi-Quellcode:
Auf diese Weise kann man sich Byte für Byte an die Richtige Einleseroutine herantasten. Bei mir hat das so immer geklappt. Ich habe es nämlich nicht hinbekommen, alle Auffüllbytes (word-alignment) mit einem Record richtig hinzubekommen. Aber das waren auch Daten von einer Siemenssteuerung, soweit ich mich erinnere.
Procedure TMyRecord.Read(aStream : Stream);
Begin myByte := aStream.ReadByte; myInteger := aStream.ReadIntger; myString := aStream.ReadAnsiString(bytesToRead); // Wäre denkbar, das ein String Wortweise abgelegt wird, d.h. wenn der String eine ungerade Anzahl // An Zeichen hat, wird mit einem Byte aufgefüllt if Odd(Length(myString)) then aStream.ReadByte; mySecondByte := aStream.ReadByte; mySubRecord := mySubRecord.Read(aStream); myPadding := aStream.ReadByte; End; Na auf jeden Fall ist o.g. Verfahren idiotensicher und führt immer zum Erfolg. PS: Ich glaube nicht, das ein Stream Methoden wie 'ReadByte, ReadString, ReadInteger' hat, aber die kann man sich leicht selbst als Class Helper bauen. |
AW: Turbo Pascal 6 erzeugte Dateien mit Delphi XE4 lesen
Zitat:
Delphi-Quellcode:
und Index-dateien gearbeitet haben, vielleicht meint er so etwas.
File of Record
Gruß K-H |
AW: Turbo Pascal 6 erzeugte Dateien mit Delphi XE4 lesen
.. hast Du dir die Daten schonmal mit einem HexViewer (HxD) angeschaut?
Kannst Du dann ein sich wiederholendes Muster erkennen? Grüße Klaus |
AW: Turbo Pascal 6 erzeugte Dateien mit Delphi XE4 lesen
Hallo zusammen,
klasse welche Resonanz da erzeugt wird:thumb:! Kurz zu den Fragen/Antworten bezgl. Index-Dateien: Nein, es sind ganz normal über TP6 erzeugte typisierte, einzelne, Dateien. Index-Dateien gibt es dazu nicht - das gehört in's Datenbankfach. Und - wie schon erwähnt - eine Datei enthält immer nur einen Record (einen einzigen Datensatz des betreffenden Typs). Ich denke ich werde mich in Richtung der Streams (@Dejan Vu: Danke für den Vorschlag) bewegen. Ich teste im Moment noch verschiedene Typzusammenstellungen des Records und das mit ALIGN ON/OFF und PACKED (will mal wissen, ob das etwas bringt). Wenn ich da Ergebnisse habe, melde ich mich wieder. Grüsse, Warp |
AW: Turbo Pascal 6 erzeugte Dateien mit Delphi XE4 lesen
Zitat:
|
AW: Turbo Pascal 6 erzeugte Dateien mit Delphi XE4 lesen
Also,
hier ein paar Ergebnisse. Ich habe das jetzt allerdings nur auf einer Win 7 VM, 32 Bit, mit XE2 testen können: Versuch 1: T_Settings_XE4 = Packed Record ID: Byte; Baud: Byte; Line: Byte; TSN1: Byte; TSN2: Byte; TSN3: Byte; TSN4: Byte; TSN5: Byte; TSN6: Byte; Description: ShortString; ConnectionDef: ShortString; end; Ergibt: Daten passen, Zeichenfolge wie gewünscht. (Keine Ahnung warum das gestern mit meinen XE4 Tests daneben ging ...) Versuch 2: {$H-} T_Settings_XE4 = Record ID: Byte; Baud: Byte; Line: Byte; TSN1: Byte; TSN2: Byte; TSN3: Byte; TSN4: Byte; TSN5: Byte; TSN6: Byte; Description: String[255]; //Dieser String[255] wird durch vorheriges {$H-} wie ein TP6 String behandelt (nur Win 32 Bit!!) ConnectionDef: String[255]; end; {$H+} Zu {$H-} noch Auszug aus Delphi Online Hilfe: "Auf der Win32-Plattform können Sie mit der Direktive {$H-}string in ShortString umwandeln. Dieses Vorgehen ist möglicherweise bei der Verwendung von älterem 16-Bit-Delphi-Code oder Turbo-Pascal-Code mit aktuellen Programmen hilfreich." Ergibt: = Das passt ebenso, die Daten werden passend übergeben, Zeichenfolge wie gewünscht. @Hansa Ja - toll. Ist aber nicht als Witz gemeint. Es ist damals so gemacht worden (so Anfang der 90er) und die Frage nach dem Inhalt (Datensätze) pro Datei war ja vorher im Thread gestellt worden (=> Antwort geben). Was mach ich jetzt daraus (nach aktuellem Stand der Dinge): Ich denke ich werde auf dieser Basis die Daten konvertieren in ein anderes Format, ggf. aber den Streams auch eine Chance geben (ist so schön flexibel) Schöne Grüsse, Warp |
AW: Turbo Pascal 6 erzeugte Dateien mit Delphi XE4 lesen
Ich würde dir empfehlen eine abstrakte Klasse zu bauen, wo die konkreten Ableitungen jeweils die alten und neuen Varianten kapseln.
Bei geschickter Implementierung kannst du mit
Delphi-Quellcode:
deine Daten konvertieren und auch in Zukunft noch die alten Daten lesen und (prinzipiell) sogar noch schreiben.
FooNew.Assign( FooOld );
Delphi-Quellcode:
Implementierung eines alten Daten-Records
// Der abstrakte Teil, der auch immer wieder erweitert wird, und den aktuellen Stand repräsentiert
unit Settings; interface uses System.Classes; type TSettings = class abstract( TPersistent ) private procedure AssignToSettings( Dest: TSettings ); protected // der Getter kann hier auch virtuell implementiert werden // damit bei neuen Eigenschaften wenigstens ein Default-Wert // übermittelt wird, wenn der in den alten Informationen // gar nicht verfügbar oder ableitbar ist function GetBaud: Byte; virtual; abstract; procedure SetBaud( const Value: Byte ); virtual; abstract; procedure AssignTo( Dest: TPersistent ); override; public property Baud: Byte read GetBaud write SetBaud; end; implementation { TSettings } procedure TSettings.AssignTo( Dest: TPersistent ); begin if Dest is TSettings then AssignToSettings( Dest as TSettings ) else inherited; end; procedure TSettings.AssignToSettings( Dest: TSettings ); begin Dest.SetBaud( Self.GetBaud ); end; end.
Delphi-Quellcode:
Implementierung eines neuen Daten-Objekts
unit Settings.v1_0;
interface uses Settings; type T_Settings_XE4 = Packed Record ID: Byte; Baud: Byte; Line: Byte; TSN1: Byte; TSN2: Byte; TSN3: Byte; TSN4: Byte; TSN5: Byte; TSN6: Byte; Description: ShortString; ConnectionDef: ShortString; end; TSettings_V1_0 = class( TSettings ) private FData: T_Settings_XE4; protected function GetBaud: Byte; override; procedure SetBaud( const Value: Byte ); override; public constructor Create( Data: T_Settings_XE4 ); end; implementation { TSettings_V1_0 } constructor TSettings_V1_0.Create( Data: T_Settings_XE4 ); begin inherited Create; FData := Data; end; function TSettings_V1_0.GetBaud: Byte; begin Result := FData.Baud; end; procedure TSettings_V1_0.SetBaud( const Value: Byte ); begin FData.Baud := Value; end; end.
Delphi-Quellcode:
ein kleiner Test zum Hin- und Herumschubsen der Daten
unit Settings.v2_0;
interface uses Settings; type T_Settings_Data = class private FBaud: Integer; public property Baud: Integer read FBaud write FBaud; end; TSettings_v2_0 = class( TSettings ) private FData: T_Settings_Data; FOwnsObject: Boolean; protected function GetBaud: Byte; override; procedure SetBaud( const Value: Byte ); override; public constructor Create( Data: T_Settings_Data; OwnsObject: Boolean = True ); destructor Destroy; override; end; implementation { TSettings_v2_0 } constructor TSettings_v2_0.Create( Data: T_Settings_Data; OwnsObject: Boolean ); begin inherited Create; FData := Data; FOwnsObject := OwnsObject; end; destructor TSettings_v2_0.Destroy; begin if FOwnsObject then FData.Free; inherited; end; function TSettings_v2_0.GetBaud: Byte; begin Result := FData.FBaud; end; procedure TSettings_v2_0.SetBaud( const Value: Byte ); begin FData.FBaud := Value; end; end.
Delphi-Quellcode:
In der Anwendung selber würde ich immer mit
program dp_182543;
{$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils, Settings in 'Settings.pas', Settings.v1_0 in 'Settings.v1_0.pas', Settings.v2_0 in 'Settings.v2_0.pas'; procedure Main; var LOldSetting: T_Settings_XE4; LNewSetting: T_Settings_Data; LSettingOld, LSettingNew: TSettings; begin // die try..finally Blöcke habe ich der Übersichtlichkeit halber weggelassen! LOldSetting.Baud := 24; // Wert im alten Format gespeichert LSettingOld := TSettings_V1_0.Create( LOldSetting ); // Wrapper drumherum LNewSetting := T_Settings_Data.Create; // neues Format LSettingNew := TSettings_v2_0.Create( LNewSetting ); // Wrapper drumherum LSettingNew.Assign( LSettingOld ); // einfach zuweisen Writeln( LNewSetting.Baud ); // und schon ist auch im neuen Format der Wert :o) end; begin try Main; except on E: Exception do Writeln( E.ClassName, ': ', E.Message ); end; end.
Delphi-Quellcode:
arbeiten, weil es dann egal ist, wie und woher die Einstellungen denn nun wirklich kommen.
TSettings
|
AW: Turbo Pascal 6 erzeugte Dateien mit Delphi XE4 lesen
Also echt pro Datensatz eine Extra-Datei ? Ja, dann stellt sich die Frage nach Indexdateien in der Tat nicht. Ich würde, die betreffenden Dateien zuerst einmal in separates Unterverzeichnis isolieren, wo sonst nichts ist und dann eben mühselig per FindFirst/Findnext die Dateien lesen und den Inhalt zeilenweise in Textdatei übertragen. Aus der Textdatei würde ich dann die daten in SQL-datenbank übernehmen im Stile von :
Delphi-Quellcode:
DbNeutable.FieldByname ('NR').Asinteger := StrToInt (AltesFeld);
|
AW: Turbo Pascal 6 erzeugte Dateien mit Delphi XE4 lesen
Zitat:
Warum gleich eine DB für 5-500 Datensätze bemühen? Du Tut's XML genauso gut. Gruß K-H |
AW: Turbo Pascal 6 erzeugte Dateien mit Delphi XE4 lesen
Wo steht was von 5 Datensätzen ? @TE : wieviele sind es denn ? Rest bleibt jedenfalls so stehen. 8-)
|
AW: Turbo Pascal 6 erzeugte Dateien mit Delphi XE4 lesen
Was wollte der TE nochmal?
Zitat:
Mit meiner Variante kann er beides haben und das neue Format kann sein was will, das ist dann völlig transparent, wohin, woher, warum ... |
AW: Turbo Pascal 6 erzeugte Dateien mit Delphi XE4 lesen
Ich würde da erst einmal gar nichts konvertieren, aber das lesen/schreiben in zwei Klassen (TReader, TWriter) auslagern. Dann kann man das austauschen und konvertieren/exportieren/importieren, wie man lustig ist (DB, XML, JSON, INI, Binär, tertiär :shock: was auch ummer)
|
AW: Turbo Pascal 6 erzeugte Dateien mit Delphi XE4 lesen
Hallo zusammen,
erstmal Danke an alle für euren Input. Ich werde die Dateien vorerst in ein anderes Format, allgemeineres, konvertieren, um sie für zukünftige Verwendung im Zugriff halten zu können (dann kann mit Typen/Kompatibilität passieren was will). Benötigt werden sie eigentlich nur noch für den Support aber das noch für längere Zeit. Vielleicht noch zur Info: Man hat das damals in einzelne Dateien gepackt, weil die damit konfigurierten Geräte diese Datei mitgeliefert bekommen haben (wäre wohl wenig sinnvoll gewesen, da eine DB mitzuliefern, die X Datensätze enthielt von denen dann nur einer relevant gewesen wäre). Etwas später (mit Beginn von Delphi für Win) hätte man dafür wohl INI-Dateien gewählt. Naja - that's History. Schönes Wochenende, Warp |
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:52 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