Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2006.07.09;
Скачать: [xml.tar.bz2];

Вниз

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

 
!_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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.57 MB
Время: 0.011 c
3-1147255459
samalex
2006-05-10 14:04
2006.07.09
Зависание Firebird


2-1150900068
fast2
2006-06-21 18:27
2006.07.09
Подскажите, как реализовать такое.


2-1150387058
Тимофей Юрьевич
2006-06-15 19:57
2006.07.09
лохонулся,как быть с формой


1-1148593159
Munchner
2006-05-26 01:39
2006.07.09
Скин и Png


15-1149840196
Ketmar
2006-06-09 12:03
2006.07.09
LUA 5.1 -- сборка в виде .obj...





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский