Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.07.09;
Скачать: CL | DM;

Вниз

Нетипизированные файлы   Найти похожие ветки 

 
!_SM_!   (2006-06-20 21:00) [0]

Здраствуйте! Подскажите пожалуйста как правильно работать с нетипизированными файлами т.е. запись/чтение данных своего типа.
Измучился уже с этой бедой
Вот как я делаю:
что здесь не так?

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.


Вопрос наверное про файлы нираз ставился. Все перерыл, перепробовал - ничего не получаеться. Раньше с нетипизированными файлами не работал. Ответьте пожалуйста.
Спасибо.


 
Alien1769 ©   (2006-06-20 21:02) [1]


> Здраствуйте! Подскажите пожалуйста как правильно работать
> с нетипизированными файлами т.е. запись/чтение данных своего
> типа

Как это записывать данные своего типа в нетипизированный файл ?!


 
!_SM_!   (2006-06-20 21:16) [2]

Извиняюсь если неправильно выразился.
т.е есть тип (см. выше по коду)
егошним полям присваиваются значения
записываються в файл потом эти значения нужно считать и присвоить
полям моего типа. Вот.


 
Alien1769 ©   (2006-06-20 21:22) [3]


> т.е есть тип

Так создать надобно переменную этого типа,
далее читать/писать одну переменную а, потом можно ее уже юзать!


 
!_SM_!   (2006-06-20 21:27) [4]

Переменная кстати есть.
DT: TData;
Так в том то и дело не надо целиком...
ну или например часть ее считать и/или записать.
Собственно вопрос - как правильно работать с нетипизированными файлами
в частности со строками.
Спасибо.


 
palva ©   (2006-06-20 22:41) [5]

> как правильно работать с нетипизированными файлами
Насколько я вижу, вы в программе вообще не работаете с нетипизированными файлами. У вас файловые потоки.
А нетипизированный файл - это такой тип с именем File. То есть вы где-то должны объявить переменную:
var f: File;

> в частности со строками.
Строки не являются частным случаем нетипизированных файлов. Строки это отдельная группа типов.


 
!_SM_!   (2006-06-21 01:54) [6]

Подскажите тогда пожалуйста как мне лучше работать с типом
type TData = record        //Мой тип данных
 Str1, Str2, Str3: PChar; //Здесь бы лучше тип String но сним вообще непонятка
 Val1, Val2: Integer;
 B1, B2: Byte;
 Val3, Val4: LongInt;
end;

Записывать в файл и читать из файла.
Здесь в "программе" я собственно привел пример что мне нужно
Пример НЕ РАБОЧИЙ. :(
Хотелось бы знать как надо правильно работать с файловыми потоками.


 
Германн ©   (2006-06-21 02:23) [7]

1. А тип ShortString  чем не подходит?
2. Придирка, но всё же. Зачем писАть ReadBuffer(N, SizeOf(LongInt));?
Логичнее писАть ReadBuffer(N, SizeOf(N));
3. В целом, принцип записи/чтения длинных строк правильный. Сначала пишется/читается длина, затем сама строка. Вот токмо где выделение памяти под PChar в примере? (Для String - SetLength).
4. Могу быть не прав, но сам предпочитаю в подобных случаях вместо DT.Str1^ писАть DT.Str1[1].


 
!_SM_!   (2006-06-21 02:55) [8]


> Германн ©   (21.06.06 02:23) [7]


> 1. А тип ShortString  чем не подходит?

В том то и дело что хочется научится с длинными строками
или например с такими данными как Arr = array of TData
т.е. динамически изменяемыми

> Логичнее писАть ReadBuffer(N, SizeOf(N));

Пробывал и так разницы нет.
Если есть возможность попробуйте код который я написал
там почему-то при чтении обрезаются строки

3 Блин, а я чет и забыл про выделение памяти просто сначала я пробовал
со Stringo"м (типом) вместо PChar. Башню рвет уже. Пример выше хоть и криво но работает что-то пишет в файл - Блокнотом смотришь вроде то че надо там есть (имею ввиду строки) - читаешь - тут херь какая-то.
Никак не въеду как правильно делать


 
!_SM_!   (2006-06-21 03:00) [9]

С прошедшим днем рождения!


 
Германн ©   (2006-06-21 03:39) [10]


> С прошедшим днем рождения!

Спасибо.

> Если есть возможность попробуйте код который я написалтам
> почему-то при чтении обрезаются строки

Увы нет такой возможности! И не столько потому что у меня нет времени на пробу, сколько потому что без dfm, нет смысла пробовать. Т.е. пробовать в рамках Дельфи можно лишь, в данном случае, проект. Либо процедуру/функцию не имеющую связи с какой-либо формой.


 
!_SM_!   (2006-06-21 03:55) [11]


>  потому что без dfm, нет смысла пробовать.


Здесь собственно пробовать нужно 2 процедуры LoadData и SaveData
а значения брать/отоброжать в любых доступных компанентах
Моя форма (файл dfm) содержит два Edita и 4 TRxSpinEdita
Первые 2 стандартные Едиты Остальные из RXLib можно заменить чемнить похожим. И две кнопки. Вызывающие при нажатии соответственно одну из процедур. В процедуре записи - Числа можно генерить случайно т.е.
DT.Val1:=Random(100);
при чтении можно вообще их опустить просто, ну, пусть в файле Data.dat будут присутствовать. Вообщем с формой я думаю ничего сложного нет.


 
Германн ©   (2006-06-21 04:08) [12]


> !_SM_!   (21.06.06 03:55) [11]


Т.е. тестовый проект должен написАть я! А мне это нужно?

Кстати. RxLib заменять не нужно. Эта библитотека одна из самых лучших библиотек для Дельфи. Она у меня установлена уже давно.


 
Германн ©   (2006-06-21 04:19) [13]

И ещё. Ну напишу я тестовый проект. И у меня всё будет как-то работать или не работать. Где гарантия, что у тебя тоже самое?


 
!_SM_!   (2006-06-21 04:23) [14]

Могу на мыло выслать весь этот пример. Тем более Rx установлен...
И у меня она установлена давно.


 
!_SM_!   (2006-06-21 04:33) [15]


> Германн ©   (21.06.06 04:19) [13]

Я хоть посмотрю как это делаеться... Если ты конечно здесь напишешь проверенные тобой процедуры или функции.....


 
Lex_! ©   (2006-06-21 05:13) [16]

var f: file of TData;
    td:TData;
....
begin
....
Read(f,td);
Write(f,td);
...
end;


 
Lex_! ©   (2006-06-21 05:14) [17]

При этом файл типизированный....


 
Lex_! ©   (2006-06-21 05:16) [18]


> Кстати. RxLib заменять не нужно. Эта библитотека одна из
> самых лучших библиотек для Дельфи. Она у меня установлена
> уже давно.


Jedi Visual Сomponent Library (JVCL) помоему лучше ... :)


 
MBo ©   (2006-06-21 07:59) [19]

http://www.delphikingdom.ru/lyceum/seminar.asp?ID=2


 
palva ©   (2006-06-21 10:56) [20]

> Подскажите тогда пожалуйста как мне лучше работать с типом...
Record можно записать файл и прочитать из файла, здесь, как я понял у вас трудностей нет. Но дело в том, что ваш record содержит указатели на другие данные (String и PChar занимают 4 байта и содержат только указатель на символьные данные). Конечно, вы хотите сохранить и эти данные тоже. В этом случае я не вижу другого выхода как аккуратно написать самому программу чтения и программу записи, продумать формат хранения такой записи. То есть вам придется для каждой строки записать в файл сначала ее длину, а затем символы. Тогда при чтении файла вы сможете восстановить первоначальный вид строки. Может быть, для этого есть какие-то стандартные средства, но я их не знаю.


 
!_SM_!   (2006-06-21 12:10) [21]


> Lex_! ©   (21.06.06 05:14) [17]

С типизированными легче, понятно, но в том то и дело что надо с нетипизированными.


 
Ega23 ©   (2006-06-21 12:15) [22]

With TMemoryStream.Create do
begin
  SetSize(....);
  Write(.....);
  SaveToFile(....);
  Free;
end;


 
!_SM_!   (2006-06-21 12:16) [23]


> MBo ©   (21.06.06 07:59) [19]

Это и много других примеров смотрел уже, ничего толком не понял.
конкретно в этом примере (по ссылке) там только запись данных а чтения нет. Ни могу въехать в суть поэтому и обратился сюда с этим вопросом и код выложил как я делаю и как, наверное, делать ненадо. Если напишите пару строк для записи/чтения данных моего типа (из кода в начале сразу после uses) буду очень благодарен.
Все равно спасибо.


 
!_SM_!   (2006-06-21 12:20) [24]


> 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 разбираться поэтому Ваш пример мне мало чего говорит. Спасибо.


 
Ega23 ©   (2006-06-21 12:23) [25]

ЗАмени TMemoryStream на TFileSteam и будет то же самое...


 
!_SM_!   (2006-06-21 12:26) [26]


> MBo ©   (21.06.06 07:59) [19]

И, кстати, в инете по поводу работы с нетипизированными файлами в основном везде один и тот-же пример копирования файлов из helpa - переведенный на русский. С него я и начал пробовать с файлами, но запутался... в частности как правильно работать с типом String (длинная строка, указатель, или как там ее еще).


 
Плохиш ©   (2006-06-21 12:27) [27]


> 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:29) [28]


> Ega23 ©   (21.06.06 12:23) [25]

Что должно быть в (.....)? У меня в коде собственно наверное так и есть тока не работает, блин. :((
Спасибо.


 
!_SM_!   (2006-06-21 12:36) [29]


> Плохиш ©   (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);
?


 
Ega23 ©   (2006-06-21 12:38) [30]


> Что должно быть в (.....)? У меня в коде собственно наверное
> так и есть тока не работает, блин. :((


Формирование твоего буффера данных.


 
!_SM_!   (2006-06-21 12:49) [31]


> Ega23 ©   (21.06.06 12:38) [30]


> Формирование твоего буффера данных.

Ну наверное тогда мой вопрос именно в (.....)....
Попробую как предложил Плохиш, а как вы его пример прокомментируете...
Прсто попробовать его вот сейчас не смогу, к сожалению.


 
Плохиш ©   (2006-06-21 12:56) [32]


> Можно пояснить почему DT.Str1[1] и при чтении и при записи
> Вроде бы это получается у Stringa мы обращаемся к первому
> символу

Буфер строки начинается с первого символа.


 
!_SM_!   (2006-06-21 13:24) [33]


> Плохиш ©   (21.06.06 12:56) [32]

Блин, извеняюсь за настойчивость - Что такое Буфер строки?
и...

> и что такое шопочки т.е. это не одно и тоже
> Fl.ReadBuffer(DT.Str1[1], N);
> Fl.ReadBuffer(DT.Str1^, N);

???


 
Плохиш ©   (2006-06-21 13:33) [34]


> Блин, извеняюсь за настойчивость - Что такое Буфер строки?

"Буфер строки" - хм, даже не знаю как на пальцах объяснить :-( Строки - это частный случай массивов символов, так вот этот массив я и подразумевал под "Буфер строки".

> > и что такое шопочки т.е. это не одно и тоже
> > Fl.ReadBuffer(DT.Str1[1], N);
> > Fl.ReadBuffer(DT.Str1^, N);

Нет не одно и то же.
DT.Str1^ - указатель на описание строки.
DT.Str1[1] - указатель на первый символ строки.


 
!_SM_!   (2006-06-21 13:53) [35]

> DT.Str1[1] - указатель на первый символ строки.
Тогда
Fl.ReadBuffer(DT.Str1[1], N);
ShowMessage(DT.Str1) что покажет?...
Спасибо... буду вечером пробовать...


 
begin...end ©   (2006-06-21 14:00) [36]

> Плохиш ©   (21.06.06 13:33) [34]

> DT.Str1^ - указатель на описание строки.

DT.Str1^ не скомпилируется -- требуется приведение к указательному типу. Но в Str1 лежит адрес именно тела строки (т.е. первого символа), а не описания.


 
!_SM_!   (2006-06-21 21:46) [37]


> 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);
Ну это понятно, что все целиком запишеться - я имею ввиду я правильно думаю - на счет дин. массивов?
Еще раз спасибо. Буду пробовать.


 
!_SM_!   (2006-06-21 21:47) [38]


> Плахиш Большое спасибо! Всем спасибо.

Извеняюсь, конечно же Плохиш.


 
Германн ©   (2006-06-22 02:43) [39]

Я рад, что ты наконец-то последовал моим советам из Германн ©   (21.06.06 02:23) [7] :-)


 
Плохиш ©   (2006-06-22 02:51) [40]


> !_SM_!   (21.06.06 21:46) [37]
> А вот если объявлена переменная:
> FDT: array of TData

Тогда, по аналогии, сначала пишешь размер массива, а после в цикле пишепь каждую запись FTD[i].

> Германн ©   (22.06.06 02:43) [39]

"Повторение - мать учения" (c) ... :-)



Страницы: 1 2 вся ветка

Текущий архив: 2006.07.09;
Скачать: CL | DM;

Наверх




Память: 0.59 MB
Время: 0.029 c
2-1150966996
Calm
2006-06-22 13:03
2006.07.09
Возможности TWebBrowser, несколько вопросов


15-1149750520
StriderMan
2006-06-08 11:08
2006.07.09
Уважаемый модератор


15-1150179797
vidiv
2006-06-13 10:23
2006.07.09
настройка количества пропускаемых звонков RAS


2-1150881191
Dmitrij_K
2006-06-21 13:13
2006.07.09
Номер выделенной строки в StringGrid


2-1150390833
learner
2006-06-15 21:00
2006.07.09
Корректное "не создание" класса