#c# #delphi
#c# #delphi
Вопрос:
Я перенесу старое приложение 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:=IOResu<
if IORes = 0
then begin
BlockWrite(f,fileType,1);
BlockWrite(f,fileVersion,1);
BlockWrite(f,sys,SizeOf(sys));
Close(f);
IORes:=IOResu<
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:=IOResu<
if IORes = 0 then begin
BlockRead(f,fileType,1);
BlockRead(f,fileVersion,1);
IORes:=IOResu<
if (fileType = 1) AND (IORes = 0) then begin
case fileVersion of
1: begin
BlockRead(f, sys, SizeOf(sys));
IORes:=IOResu<
if IORes = 0 then if EOF(f) then fileOK:=TRUE;
end; { 1 }
end; { case }
end;
Close(f);
IORes:=IOResu<
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);
Комментарии:
1. Используйте любую функциональность записи двоичных файлов в C # raw, с которой вам удобно. Кстати, этот источник не полностью определяет формат файла. Записи не упакованы, и упаковка не указана иначе, и, таким образом, упаковка записей определяется настройками компилятора в IDE, за пределами исходного кода
2. Как мне теперь узнать, как упакованы записи? Могу ли я увидеть это в файле проекта? У меня нет IDE для Delphi.
3. Объявление самого типа записи. Если
packed
ключ не используется, значит, он не упакован.4. Нет, упакованный ключ не используется. Является ли код, который написал «Matthias Alleweldt», правильным?
Ответ №1:
Предполагая, что файл написан с использованием версии delphi до unicode, это дает вам отправную точку:
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.
Комментарии:
1. В каком порядке хранятся байты для двумерных массивов?
2. @magol: Я добавил значение sondXref, чтобы показать организацию массива в двумерном массиве.