Delphi-PRAXiS
Seite 2 von 3     12 3      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Turbo Pascal 6 erzeugte Dateien mit Delphi XE4 lesen (https://www.delphipraxis.net/182543-turbo-pascal-6-erzeugte-dateien-mit-delphi-xe4-lesen.html)

Sir Rufo 31. Okt 2014 00:33

AW: Turbo Pascal 6 erzeugte Dateien mit Delphi XE4 lesen
 
Bei einem
Delphi-Quellcode:
File of Record
gibt es Index-Dateien?

Aber nur wenn man die selber gebaut hat und zum Auslesen sind die dann auch nicht wichtig

Hansa 31. Okt 2014 02:03

AW: Turbo Pascal 6 erzeugte Dateien mit Delphi XE4 lesen
 
Gerade bei Records gibt es die Index-Daeien. .

Dejan Vu 31. Okt 2014 07:15

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:
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;
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.

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.

p80286 31. Okt 2014 09:39

AW: Turbo Pascal 6 erzeugte Dateien mit Delphi XE4 lesen
 
Zitat:

Zitat von Sir Rufo (Beitrag 1278123)
Bei einem
Delphi-Quellcode:
File of Record
gibt es Index-Dateien?

Aber nur wenn man die selber gebaut hat und zum Auslesen sind die dann auch nicht wichtig

Es soll ja ältere Datenbanken geben, die mit
Delphi-Quellcode:
File of Record
und Index-dateien gearbeitet haben, vielleicht meint er so etwas.

Gruß
K-H

Klaus01 31. Okt 2014 09:44

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

Warp 31. Okt 2014 10:11

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

Hansa 31. Okt 2014 11:44

AW: Turbo Pascal 6 erzeugte Dateien mit Delphi XE4 lesen
 
Zitat:

Zitat von Warp (Beitrag 1278168)
...eine Datei enthält immer nur einen Record (einen einzigen Datensatz des betreffenden Typs)...

Das da ist aber jetzt kein Witz ? Tsts. :mrgreen:

Warp 31. Okt 2014 12:17

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

Sir Rufo 31. Okt 2014 13:11

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:
FooNew.Assign( FooOld );
deine Daten konvertieren und auch in Zukunft noch die alten Daten lesen und (prinzipiell) sogar noch schreiben.

Delphi-Quellcode:
// 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.
Implementierung eines alten Daten-Records
Delphi-Quellcode:
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.
Implementierung eines neuen Daten-Objekts
Delphi-Quellcode:
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.
ein kleiner Test zum Hin- und Herumschubsen der Daten
Delphi-Quellcode:
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.
In der Anwendung selber würde ich immer mit
Delphi-Quellcode:
TSettings
arbeiten, weil es dann egal ist, wie und woher die Einstellungen denn nun wirklich kommen.

Hansa 31. Okt 2014 13:13

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);


Alle Zeitangaben in WEZ +1. Es ist jetzt 23:39 Uhr.
Seite 2 von 3     12 3      

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