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

Вниз

Запись в файл и чтение из файла записи: есть запись:   Найти похожие ветки 

 
EgorovAlex ©   (2008-06-16 14:54) [0]

record
 s1,
 s2: PWideChar;
end;

Как мне её записать в файл и потом прочитать из файла?

пробовал так: MS: TMemoryStream;

MS.Write(Rec^, SizeOf(Rec));
MS.Position := 0;
MS.WriteToFile...

но потом при чтении из файла (тоже через мемористрим) не читаются s1 и s2.

Что я не так делаю?


 
Поросенок Винни-Пух ©   (2008-06-16 15:25) [1]

все так. что записал то и считал.


 
Поросенок Винни-Пух ©   (2008-06-16 15:28) [2]

Поразмышляй вот над этим:
showmrssage(inttostr(SizeOf(rec)))


 
EgorovAlex ©   (2008-06-16 15:52) [3]

Я над этим уже поразмышлял :) только как применить пока не понимаю, я понял, что я пишу 2 байта указателей, а не содержимое полей записи, а вот как записать всё?


 
clickmaker ©   (2008-06-16 15:54) [4]

> как записать всё?

также. Write() каждое поле отдельно


 
Поросенок Винни-Пух ©   (2008-06-16 16:01) [5]

плюс еще записать туда же обе длины чтобы знать сколько читать в последствии


 
EgorovAlex ©   (2008-06-16 16:39) [6]

т.е. писать так?

Size: Cardinal;

MS.Write(Rec^, SizeOf(Rec));
Size := Length(Rec.s1)*SizeOf(WideChar);
MS.Write(Size, SizeOf(Size));
MS.Write(Rec.s1, Size);
Size := Length(Rec.s2)*SizeOf(WideChar);
MS.Write(Size, SizeOf(Size));
MS.Write(Rec.s2, Size);
MS.Position := 0;
MS.WriteToFile...


 
Поросенок Винни-Пух ©   (2008-06-16 16:50) [7]

записать длину первого поля.
записать само первое поле.
записать длину второго поля
записать само второе поле.


 
EgorovAlex ©   (2008-06-16 16:54) [8]

Вроде всё так и написано в приведённом коде, но считать почему-то не получается, читаю так:

MS.ReadBuffer(Size, SizeOf(Size));
if (Size > 0) then
begin
 GetMem(Rec.s1, Size);
 MS.ReadBuffer(Rec.s1, Size);
end;
MS.ReadBuffer(Size, SizeOf(Size));
if (Size > 0) then
begin
 GetMem(Rec.s2, Size);
 MS.ReadBuffer(Rec.s2, Size);
end;


 
Поросенок Винни-Пух ©   (2008-06-16 17:01) [9]

try
ms := T....Stream.create(...);
except
on E:Exception do ShowMessage("Ой, мама!"#13#10 + E.Message)
end


 
TForumHelp ©   (2008-06-16 17:02) [10]

ну еще бы читалось.


 
EgorovAlex ©   (2008-06-16 17:05) [11]

так нет никаких исключений, но и не читается :(

to TForumHelp

а как читать-то :)


 
Поросенок Винни-Пух ©   (2008-06-16 17:09) [12]

Эт я не в ту ветку запостил


 
Поросенок Винни-Пух ©   (2008-06-16 17:10) [13]

ридбуфер требует параметром адрес, а не указатель


 
EgorovAlex ©   (2008-06-17 09:50) [14]

С этим разобрался, спасибо, теперь для уточнения моих познаний :)
(т.к. старался всегда использовать только записи с фиксированными полями, а не указателями)

Если у меня есть запись Rec1 и мне нужно сделать её дубликат, то достаточно ли этих двух строк:

type
 PMyRec = ^TMyRec;
 TMyRec = record
   S: PWideChar;
 end;

var
 Rec1, Rec2: PMyRec;

GetMem(Rec2, SizeOf(Rec2));
Rec2^ := Rec1^;

или нужны ещё и эти строки:

GetMem(Rec2.S, Length(Rec1.S)*SizeOf(WideChar));
CopyMemory(Rec2.S, Rec1.S, Length(Rec1.S)*SizeOf(WideChar));


 
Поросенок Винни-Пух ©   (2008-06-17 10:41) [15]

1. New(Rec2) красивше чем гетмем в этом случае.
2. Память под строки распределять надо и надо копировать сами строки если хочешь именно дубликат записи, а не две записи с указателями на один и тот же буфер.
3. Со строками тоже лучше работать через строковые функции а не через гетмем и копимемори


 
EgorovAlex ©   (2008-06-17 10:57) [16]

Что за функции работы со строками? Какие преимущества они дадут?


 
Поросенок Винни-Пух ©   (2008-06-17 11:05) [17]

тебе перепечатать сюда штатную справку?


 
Василий Жогарев ©   (2008-06-17 11:30) [18]


>  Запись в файл и чтение из файла записи: есть запись:
>
> EgorovAlex ©   (16.06.08 14:54)  


type
 TRow = packed record
   Value1: String[32];
   Value2: String[32];
   Value3: LongInt;
 end;

var
 Rows: array[1..16] of TRow;


var
 F: file of TRow;
 i: Integer;
begin
 // Вносим значения.
 {Rows[1].Value1 := "Значение 1";
 Rows[1].Value2 := "Значение 2";
 Rows[1].Value3 := 3;}

 AssignFile(F, "./rows.my");
 Rewrite(F);

 try
   for i:= 1 to 16 do
   Write(F, Rows[i]);
 finally
   CloseFile(F);
 end;


var
 Row: TRow;
 F: file of TRow;
begin
 AssignFile(F, "./rows.my");
 Reset(F);
 try
   while not Eof(F) do
     begin
       Read (F, Row);
       // Получаем значения.
       {Row.Value1...}
     end;
 finally
   CloseFile(F);
 end;
end;


Идея рассматривалась на http://forum.sources.ru


 
Palladin ©   (2008-06-17 11:53) [19]


> Идея рассматривалась на http://forum.sources.ru

однако растут :) какие великие идеи рассматривать начали


 
EgorovAlex ©   (2008-06-17 12:47) [20]

Для такой записи всё просто, она же фиксированной длины, да к тому же и не юникодная


 
Sapersky   (2008-06-17 13:15) [21]

Для записи с WideString могу предложить хакерский метод, позволяющий писать/читать запись одной командой. Но вам, как начинающему, возможно, лучше о нём не знать :)


 
EgorovAlex ©   (2008-06-17 13:38) [22]

Все мы когда-то в чём-то начинающие, не томи, показывай :)


 
Sapersky   (2008-06-17 13:55) [23]

На всякий случай повторю: запись должна быть с WideString, не WideChar. Собственно, с чем оно будет работать, с чем нет - расписано в комментарии в начале модуля TypInfoEx.
http://sapersky.narod.ru/files/TypInfoEx.rar


 
EgorovAlex ©   (2008-06-19 12:46) [24]

Опять вопрос:
Сейчас записываю в стрим так:

type
 PMyRec = ^TMyRec;
 TMyRec = record
   S: PWideChar;
 end;
var
 Size: Cardinal;
 MS: TMemoryStream;
 Rec: PMyRec;

MS.WriteBuffer(Rec^, SizeOf(TMyRec));
if Assigned(Rec.S) then
 Size := WStrLen(Rec.S)
else
 Size := 0;
MS.WriteBuffer(Size, SizeOf(Size));
MS.WriteBuffer(Rec.S^, Size*SizeOf(WideChar));


а читаю так:

var
 Buf: WideString;

MS.ReadBuffer(Rec^, SizeOf(TMyRec));
MS.ReadBuffer(Size, SizeOf(Size));
if (Size > 0) then
begin
 SetLength(Buf, Size);
 MS.ReadBuffer(PWideChar(Buf)^, Size*SizeOf(WideChar));
 Rec.S := WStrNew(PWideChar(Buf));
end;


и всё работает нормально, но если я пытаюсь избавиться от промежуточного буфера и читать так:

MS.ReadBuffer(Rec^, SizeOf(TMyRec));
MS.ReadBuffer(Size, SizeOf(Size));
if (Size > 0) then
begin
 Rec.S := WStrAlloc(Size);
 MS.ReadBuffer(Rec.S^, Size*SizeOf(WideChar));
end;


то в конце строки Rec.S появляется какой-то мусор. Почему?


 
Sapersky   (2008-06-19 15:51) [25]

Насколько я понял, WStrLen (из TntWideStrUtils), даёт длину без завершающего #0, а в WStrAlloc её нужно указывать с учётом нуля, во всяком случае, WStrNew берёт Size := WStrLen(Str) + 1.

И вот это зачем:
MS.WriteBuffer(Rec^, SizeOf(TMyRec));
MS.ReadBuffer(Rec^, SizeOf(TMyRec));


 
EgorovAlex ©   (2008-06-19 16:14) [26]

Это здесь не нужно, просто по инерции на упрощённыи пример перекинул, а в D2007 WStrLen уже в WideStrUtils есть.
Да, с прибавлением единицы перед записью проблема решилась



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

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

Наверх




Память: 0.53 MB
Время: 0.013 c
15-1212754520
Рваный Башмак
2008-06-06 16:15
2008.07.20
Чтение буфера обмена


15-1212557889
андр.
2008-06-04 09:38
2008.07.20
Float=Real


2-1213869168
NeiL
2008-06-19 13:52
2008.07.20
Компонент


2-1213614223
Рустам1
2008-06-16 15:03
2008.07.20
delete from


15-1212366526
Пробегал2....
2008-06-02 04:28
2008.07.20
Невероятная работа потока