![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Нетипизированные файлы [D7, XP]
!_SM_! © (2006-06-20 21:00:00)Здраствуйте! Подскажите пожалуйста как правильно работать с нетипизированными файлами т.е. запись/чтение данных своего типа.
Измучился уже с этой бедой
Вот как я делаю:
что здесь не так?
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, RXSpin, ExtCtrls;
type TData = record //Мой тип данных
Str1, Str2, Str3: PChar; //Здесь бы лучше тип String но сним вообще непонятка
Val1, Val2: Integer;
B1, B2: Byte;
Val3, Val4: LongInt;
end;
type
TForm1 = class(TForm)
edit1: TLabeledEdit;
edval1: TRxSpinEdit;
edval2: TRxSpinEdit;
Label2: TLabel;
Label3: TLabel;
edval3: TRxSpinEdit;
edval4: TRxSpinEdit;
Label4: TLabel;
Label5: TLabel;
edit2: TLabeledEdit;
Button1: TButton;
Button2: TButton;
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
DT: TData;
FL: TStream;
FlNm: String;
Dir: String;
implementation
{$R *.dfm}
procedure SaveData;
var N: Integer;
begin
with Form1 do begin
DT.Str1:=PChar(edit1.Text);
DT.Str2:=PChar(edit2.Text);
DT.Val1:=edVal1.AsInteger;
DT.Val2:=edVal2.AsInteger;
DT.Val3:=edVal3.AsInteger;
DT.Val4:=edVal4.AsInteger;
Fl:=TFileStream.Create(FlNm, fmOpenWrite or fmCreate);
N:=StrLen(DT.Str1); //Здесь пробовал
Fl.WriteBuffer(N, SizeOf(LongInt)); //разные варианты.
Fl.WriteBuffer(DT.Str1^, N); //Этот более менее работает
N:=StrLen(DT.Str2); //Но тоже не правильно
Fl.WriteBuffer(N, SizeOf(LongInt));
Fl.WriteBuffer(DT.Str2^, N);
Fl.WriteBuffer(DT.Val1, SizeOf(LongInt));
Fl.WriteBuffer(DT.Val2, SizeOf(LongInt));
Fl.WriteBuffer(DT.Val3, SizeOf(LongInt));
Fl.WriteBuffer(DT.Val4, SizeOf(LongInt));
Fl.Free;
end;
end;
procedure LoadData;
var N: Integer;
begin
with Form1 do begin
Fl:=TFileStream.Create(FlNm, fmOpenRead);
Fl.ReadBuffer(N, SizeOf(LongInt)); //И здесь пробовал
Fl.ReadBuffer(DT.Str1^, N); //соответственно
Fl.ReadBuffer(N, SizeOf(LongInt)); //пробовал по разному
Fl.ReadBuffer(DT.Str2^, N);
Fl.ReadBuffer(DT.Val1, SizeOf(LongInt));
Fl.ReadBuffer(DT.Val2, SizeOf(LongInt));
Fl.ReadBuffer(DT.Val3, SizeOf(LongInt));
Fl.ReadBuffer(DT.Val4, SizeOf(LongInt));
edit1.Text:=DT.Str1;
edit2.Text:=DT.Str2;
edVal1.AsInteger:=DT.Val1;
edVal2.AsInteger:=DT.Val2;
edVal3.AsInteger:=DT.Val3;
edVal4.AsInteger:=DT.Val4;
Fl.Free;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
GetDir(0, Dir);
FlNm:=Dir+'\Data.dat';
//if FileExists(FlNm) then LoadData else SaveData; //Вот так можно делать или нет т.е. в OnCreate формы присваивать полям разных едитов значения (LoadData)?
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
SaveData;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
if FileExists(FlNm) then LoadData;
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
SaveData;
end;
end.
Вопрос наверное про файлы нираз ставился. Все перерыл, перепробовал - ничего не получаеться. Раньше с нетипизированными файлами не работал. Ответьте пожалуйста.
Спасибо.
!_SM_! (2006-06-22 16:08:00) [1]
> Германн © (22.06.06 02:43) [39]
Были советы без разъяснения, а у Плохиша пример с коментарием и рабочий и по моемУ тИпу и малясь начал я въезжать в это дело и....
Спасибо Вам всем огромное!
Отдельно Германну и Плохишу. Спасибо.
Плохиш (2006-06-22 02:51:00) [2]
> !_SM_! (21.06.06 21:46) [37]
> А вот если объявлена переменная:
> FDT: array of TData
Тогда, по аналогии, сначала пишешь размер массива, а после в цикле пишепь каждую запись FTD[i].
> Германн © (22.06.06 02:43) [39]
"Повторение - мать учения" (c) ... :-)
Германн (2006-06-22 02:43:00) [3]Я рад, что ты наконец-то последовал моим советам из Германн © (21.06.06 02:23) [7] :-)
!_SM_! (2006-06-21 21:47:00) [4]
> Плахиш Большое спасибо! Всем спасибо.
Извеняюсь, конечно же Плохиш.
!_SM_! (2006-06-21 21:46:00) [5]
> begin...end © (21.06.06 14:00) [36]
> DT.Str1^ - указатель на описание строки.DT.Str1^ не скомпилируется
> -- требуется приведение к указательному типу. Но в Str1
> лежит адрес именно тела строки (т.е. первого символа), а
> не описания.
Блин, мало чего понял из этого....
Попробовал как подсказал Плохиш. Работает! Вот:
..................
type TData = record
Str1, Str2, Str3: String;
Val1, Val2: Integer;
B1, B2: Byte;
Val3, Val4: LongInt;
end;
..........
procedure SaveData;
var N: Integer;
begin
with Form1 do begin
DT.Str1:=edit1.Text;
DT.Str2:=edit2.Text;
DT.Val1:=edVal1.AsInteger;
DT.Val2:=edVal2.AsInteger;
DT.Val3:=edVal3.AsInteger;
DT.Val4:=edVal4.AsInteger;
Fl:=TFileStream.Create(FlNm, fmOpenWrite or fmCreate);
N:=Length(DT.Str1);
Fl.WriteBuffer(N, SizeOf(N));
Fl.WriteBuffer(DT.Str1[1], N);
N:=Length(DT.Str2);
Fl.WriteBuffer(N, SizeOf(N));
Fl.WriteBuffer(DT.Str2[1], N);
Fl.WriteBuffer(DT.Val1, SizeOf(LongInt));
Fl.WriteBuffer(DT.Val2, SizeOf(DT.Val2));
Fl.WriteBuffer(DT.Val3, SizeOf(Integer));
Fl.WriteBuffer(DT.Val4, SizeOf(LongInt));
Fl.Free;
end;
end;
procedure LoadData;
var N: Integer;
begin
with Form1 do begin
Fl:=TFileStream.Create(FlNm, fmOpenRead);
Fl.ReadBuffer(N, SizeOf(N));
SetLength(DT.Str1, N);
Fl.ReadBuffer(DT.Str1[1], N);
Fl.ReadBuffer(N, SizeOf(N));
SetLength(DT.Str2, N);
Fl.ReadBuffer(DT.Str2[1], N);
Fl.ReadBuffer(DT.Val1, SizeOf(LongInt));
Fl.ReadBuffer(DT.Val2, SizeOf(LongInt));
Fl.ReadBuffer(DT.Val3, SizeOf(LongInt));
Fl.ReadBuffer(DT.Val4, SizeOf(LongInt));
edit1.Text:=DT.Str1;
edit2.Text:=DT.Str2;
edVal1.AsInteger:=DT.Val1;
edVal2.AsInteger:=DT.Val2;
edVal3.AsInteger:=DT.Val3;
edVal4.AsInteger:=DT.Val4;
Fl.Free;
end;
end;
Плахиш Большое спасибо! Всем спасибо.
Будем дальше ковырять, изучать.
А вот если объявлена переменная:
FDT: array of TData
......
SetLength(FDT, 10);
Fl.ReadBuffer(FDT[1], 10);
Читать из файла так надо? Соответственно писать в файл наверное так:
FDT: array of TDataНу это понятно, что все целиком запишеться - я имею ввиду я правильно думаю - на счет дин. массивов?
.....
SetLength(FDT, 10);
Fl.WriteBuffer(FDT[1], 10);
Еще раз спасибо. Буду пробовать.
begin...end (2006-06-21 14:00:00) [6]> Плохиш © (21.06.06 13:33) [34]
> DT.Str1^ - указатель на описание строки.
DT.Str1^ не скомпилируется -- требуется приведение к указательному типу. Но в Str1 лежит адрес именно тела строки (т.е. первого символа), а не описания.
!_SM_! (2006-06-21 13:53:00) [7]> DT.Str1[1] - указатель на первый символ строки.
Тогда
Fl.ReadBuffer(DT.Str1[1], N);
ShowMessage(DT.Str1) что покажет?...
Спасибо... буду вечером пробовать...
Плохиш (2006-06-21 13:33:00) [8]
> Блин, извеняюсь за настойчивость - Что такое Буфер строки?
"Буфер строки" - хм, даже не знаю как на пальцах объяснить :-( Строки - это частный случай массивов символов, так вот этот массив я и подразумевал под "Буфер строки".
> > и что такое шопочки т.е. это не одно и тоже
> > Fl.ReadBuffer(DT.Str1[1], N);
> > Fl.ReadBuffer(DT.Str1^, N);
Нет не одно и то же.
DT.Str1^ - указатель на описание строки.
DT.Str1[1] - указатель на первый символ строки.
!_SM_! (2006-06-21 13:24:00) [9]
> Плохиш © (21.06.06 12:56) [32]
Блин, извеняюсь за настойчивость - Что такое Буфер строки?
и...
> и что такое шопочки т.е. это не одно и тоже
> Fl.ReadBuffer(DT.Str1[1], N);
> Fl.ReadBuffer(DT.Str1^, N);
???
Плохиш (2006-06-21 12:56:00) [10]
> Можно пояснить почему DT.Str1[1] и при чтении и при записи
> Вроде бы это получается у Stringa мы обращаемся к первому
> символу
Буфер строки начинается с первого символа.
!_SM_! (2006-06-21 12:49:00) [11]
> Ega23 © (21.06.06 12:38) [30]
> Формирование твоего буффера данных.
Ну наверное тогда мой вопрос именно в (.....)....
Попробую как предложил Плохиш, а как вы его пример прокомментируете...
Прсто попробовать его вот сейчас не смогу, к сожалению.
Ega23 (2006-06-21 12:38:00) [12]
> Что должно быть в (.....)? У меня в коде собственно наверное
> так и есть тока не работает, блин. :((
Формирование твоего буффера данных.
!_SM_! (2006-06-21 12:36:00) [13]
> Плохиш © (21.06.06 12:27) [27]
Спасибо. Но сейчас попробовать не смогу, приду домой вечером обязательно поробую.
> Fl.ReadBuffer(DT.Str1[1], N);
Можно пояснить почему DT.Str1 [1]и при чтении и при записи
Вроде бы это получается у Stringa мы обращаемся к первому символу....
или так-как ReadBuffer работает с указателями то такое обращение и есть
обращение к строке в целом а не на указатель... вообще не пойму.... и что такое шопочки т.е. это не одно и тоже
Fl.ReadBuffer(DT.Str1[1], N);
Fl.ReadBuffer(DT.Str1^, N);
?
!_SM_! (2006-06-21 12:29:00) [14]
> Ega23 © (21.06.06 12:23) [25]
Что должно быть в (.....)? У меня в коде собственно наверное так и есть тока не работает, блин. :((
Спасибо.
Плохиш (2006-06-21 12:27:00) [15]
> procedure LoadData;
> var N: Integer;
> begin
> with Form1 do begin
> Fl:=TFileStream.Create(FlNm, fmOpenRead);
> Fl.ReadBuffer(N, SizeOf( LongInt)); //И здесь пробовал
> Fl.ReadBuffer(DT.Str1^, N); //соответственно
Оригинально, описывать переменные одного типа, а размер брать у другого типа. Глюкодром программируем?
PChar заменить на String;
Чтение
Fl.ReadBuffer(N, SizeOf(N)); //как уже и говорили
SetLength(DT.Str1, N); //распределить память
Fl.ReadBuffer(DT.Str1[1], N); //как уже и упоминалось
Запись
N:=Length(DT.Str1);
Fl.WriteBuffer(N, SizeOf(N));
Fl.WriteBuffer(DT.Str1[1], N);
!_SM_! (2006-06-21 12:26:00) [16]
> MBo © (21.06.06 07:59) [19]
И, кстати, в инете по поводу работы с нетипизированными файлами в основном везде один и тот-же пример копирования файлов из helpa - переведенный на русский. С него я и начал пробовать с файлами, но запутался... в частности как правильно работать с типом String (длинная строка, указатель, или как там ее еще).
Ega23 (2006-06-21 12:23:00) [17]ЗАмени TMemoryStream на TFileSteam и будет то же самое...
!_SM_! (2006-06-21 12:20:00) [18]
> palva © (21.06.06 10:56) [20]
> То есть вам придется для каждой строки записать в файл сначала
> ее длину, а затем символы.
Вот собственно над этим я и бьюсь....и .... пока ничего хорошего....
> Ega23 © (21.06.06 12:15) [22]
> With TMemoryStream.Create do
> begin
> SetSize(....);
> Write(.....);
> SaveToFile(....);
> Free;
> end;
Тут тока начал с типом File и FileStream разбираться поэтому Ваш пример мне мало чего говорит. Спасибо.
!_SM_! (2006-06-21 12:16:00) [19]
> MBo © (21.06.06 07:59) [19]
Это и много других примеров смотрел уже, ничего толком не понял.
конкретно в этом примере (по ссылке) там только запись данных а чтения нет. Ни могу въехать в суть поэтому и обратился сюда с этим вопросом и код выложил как я делаю и как, наверное, делать ненадо. Если напишите пару строк для записи/чтения данных моего типа (из кода в начале сразу после uses) буду очень благодарен.
Все равно спасибо.
Ega23 (2006-06-21 12:15:00) [20]With TMemoryStream.Create do
begin
SetSize(....);
Write(.....);
SaveToFile(....);
Free;
end;