【问题标题】:Read a file created in Delphi读取在 Delphi 中创建的文件
【发布时间】:2011-04-27 08:18:50
【问题描述】:

我将把一个旧的 Delphi 应用程序移植到 C#,需要帮助才能读取 Delphi 创建的文件。

我的 C# 程序将使用序列化来读取和写入文件,但该程序还必须能够读取 Delphi 创建的旧文件,而这正是我需要帮助的。

简而言之,我需要帮助才能读取使用 BlockWrite 创建的文件

创建文件的Delphi代码:

sys: SystemRecord;

procedure SaveSystem;
var
  fileType,
  fileVersion: Byte;
  IORes:       Integer;
  fileName:    String;
  f:           File;
begin
  fileType:=1;    { system file }
  fileVersion:=1; { Version on the file}
  fileName:=GetSystemFileName;
  {$I-}
  if IOResult = 0 then;  { Read IOResult }
  Assign(f,fileName);
  Rewrite(f,1);
  IORes:=IOResult;
  if IORes = 0
  then begin
    BlockWrite(f,fileType,1);
    BlockWrite(f,fileVersion,1);
    BlockWrite(f,sys,SizeOf(sys));
    Close(f);
    IORes:=IOResult;
  end;
  {$I+}
  if IORes <> 0
  then begin
    LogHnd(_SaveSystem,'');
    MainForm.SetInfo(INFO_SaveSystem_ERR,'');
  end
  else begin
    MainForm.SetInfo(INFO_SaveSystem_OK,'');
  end;
end;

读取文件的Delphi代码:

procedure LoadSystem;
var
  fileType,
  fileVersion: Byte;
  IORes:       Integer;
  fileName:    String;
  f:           File;
  fileOK:      Boolean;
begin
  fileOK:=FALSE;
  fileName:=GetSystemFilename;
  {$I-}
  if IOResult = 0 then;  { Read IOResult }
  Assign(f,fileName);
  Reset(f,1);
  IORes:=IOResult;
  if IORes = 0 then begin
    BlockRead(f,fileType,1);
    BlockRead(f,fileVersion,1);
    IORes:=IOResult;
    if (fileType = 1) AND (IORes = 0) then begin
      case fileVersion of
        1: begin
          BlockRead(f, sys, SizeOf(sys));
          IORes:=IOResult;
          if IORes = 0 then if EOF(f) then fileOK:=TRUE;
        end; { 1 }
      end; { case }
    end;
    Close(f);
    IORes:=IOResult;
    if IORes <> 0 then; { Skip waring  }
  end
  else begin { system file missing => load default settings }
    InitSystem;
    fileOK:=TRUE;
  end;
  {$I+}
  if (NOT fileOK)
  then begin
    InitSystem;          { Read error => Load default settings }
    LogHnd(_LoadSystem,''); { To event log }
    MainForm.SetInfo(INFO_LoadSystem_ERR,'');
  end
  else MainForm.SetInfo(INFO_LoadSystem_OK,'');
end;

要保存的结构/枚举:

SystemRecord = record
    verk: Array[1..MAXVERK] of VerkRecord;
    activeVerk: Integer;
    com: ComRecord;
    hastighet: THastighet;
    tipStatus:  Array[1..MAXTIP] of TipStatusRecord;
    brus: Integer; { 1..50 }
    TIPcolor: Array[1..3,1..2] of Byte;
    dummy: Array[1..494] of Byte; { For backward compatibility }
  end;

VerkRecord = record
    active:    boolean;
    name:      string[40];
    shortname: string[10];
    formula:   string[100];
    antalKanaler: Array[1..MAXTIP] of Integer; 
    sondXref: Array[1..MAXTIP,1..MAXKANAL] of Integer;
    TOCtime: Array[1..MAXTIP,1..MAXKANAL] of TDateTime;
    BOCtime: Array[1..MAXTIP,1..MAXKANAL] of TDateTime;
    blockerad: Array[1..MAXSOND] of Boolean; 
    tipIsDigit: Boolean; 
    sondLength: Integer; 
    power: Integer;     
    dummy: Array[1..200] of Byte; { For backward compatibility }
  end;

  ComRecord = record
    port: Word;
    baud: Word;
    stop: Word;
    data: Word;
    par:  Word;
  end;

TipStatusRecord = record
    position: 1..9; 
    riktning: 0..2; 
    ATIP: 1..6;     
    ATCU: 1..4;     
    SelfTest: 0..1; 
    ATCUStatus: 0..1;
    measurePos: Integer; 
    kanal: Integer;
  end;

THastighet = (normal, brus, dubbel, trippel, snabb);

【问题讨论】:

  • 使用您熟悉的任何 C# 原始二进制写入功能。顺便说一句,这个来源没有完全定义文件格式。记录未打包且未另外指定打包,因此记录的打包由 IDE 中的编译器设置定义,在源代码之外
  • 我现在如何打包记录?我可以在项目文件中看到它吗?我没有 Delphi 的 IDE。
  • 记录类型本身的声明。如果未使用 packed 键,则不会打包。
  • 不,不使用打包密钥。那么“Matthias Alleweldt”写的代码是否正确?

标签: c# delphi


【解决方案1】:

假设文件是​​使用 unicode delphi 之前的版本编写的,这为您提供了一个起点:

const int MAXVERK = 10;
const int MAXTIP = 5;
const int MAXKANAL = 3;

private void LoadSystem() {
  BinaryReader reader;

  reader = new BinaryReader(File.OpenRead("E:\\test.dat"));

  if (reader.ReadByte() != 1) {
    throw new Exception("Wrong file type");
  }

  if (reader.ReadByte() != 1) {
    throw new Exception("Wrong file version");
  }

  ReadSystemRecord(reader);    
}

private void ReadSystemRecord(BinaryReader Reader) {
  for (int i = 0; i < MAXVERK; ++i) {
    ReadVerkRecord(Reader);
  }
  Int32 activeVerk = Reader.ReadInt32();
  ReadComRecord(Reader);
  byte hastighet = Reader.ReadByte();  // TODO: convert byte to the enum
  //...
}

private void ReadVerkRecord(BinaryReader Reader) {
  bool active = Reader.ReadByte() != 0;
  string name = ReadDelphiString(Reader, 40);
  string shortname = ReadDelphiString(Reader, 10);
  string formula = ReadDelphiString(Reader, 100);
  for (int i = 0; i < MAXTIP; ++i) {
    Int32 antalKanaler = Reader.ReadInt32();
  }
  for (int i = 0; i < MAXTIP; ++i) {
    for (int j = 0; j < MAXKANAL; ++j) {
      Int32 sondXref = Reader.ReadInt32();
    }
  }
  //...
}

private void ReadComRecord(BinaryReader Reader) {
  Int16 port = Reader.ReadInt16();
  Int16 baud = Reader.ReadInt16();
  Int16 stop = Reader.ReadInt16();
  Int16 data = Reader.ReadInt16();
  Int16 par = Reader.ReadInt16();
}

private string ReadDelphiString(BinaryReader Reader, int Length) {
  byte strlength = Reader.ReadByte();
  return System.Text.ASCIIEncoding.ASCII.GetString(Reader.ReadBytes(Length), 0, strlength);
}

不是一个完整的阅读器,也没有任何错误处理。您必须添加您的 C# 数据存储、缺失值和 TDateTime/Enum 转换。但这应该不是很困难。也许您必须在 delphi 中测试值的大小。

【讨论】:

  • 对于二维数组,字节按什么顺序存储?
  • @magol:我添加了sondXref读数以显示二维数组的数组组织。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多