![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Запись в файл и чтение из файла записи: есть запись:
EgorovAlex © (2008-06-16 14:54:00)record
s1,
s2: PWideChar;
end;
Как мне её записать в файл и потом прочитать из файла?
пробовал так: MS: TMemoryStream;
MS.Write(Rec^, SizeOf(Rec));
MS.Position := 0;
MS.WriteToFile...
но потом при чтении из файла (тоже через мемористрим) не читаются s1 и s2.
Что я не так делаю?
EgorovAlex (2008-06-19 16:14:00) [1]Это здесь не нужно, просто по инерции на упрощённыи пример перекинул, а в D2007 WStrLen уже в WideStrUtils есть.
Да, с прибавлением единицы перед записью проблема решилась
Sapersky (2008-06-19 15:51:00) [2]Насколько я понял, WStrLen (из TntWideStrUtils), даёт длину без завершающего #0, а в WStrAlloc её нужно указывать с учётом нуля, во всяком случае, WStrNew берёт Size := WStrLen(Str) + 1.
И вот это зачем:
MS.WriteBuffer(Rec^, SizeOf(TMyRec));
MS.ReadBuffer(Rec^, SizeOf(TMyRec));
EgorovAlex (2008-06-19 12:46:00) [3]Опять вопрос:
Сейчас записываю в стрим так:
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-17 13:55:00) [4]На всякий случай повторю: запись должна быть с WideString, не WideChar. Собственно, с чем оно будет работать, с чем нет - расписано в комментарии в начале модуля TypInfoEx.
http://sapersky.narod.ru/files/TypInfoEx.rar
EgorovAlex (2008-06-17 13:38:00) [5]Все мы когда-то в чём-то начинающие, не томи, показывай :)
Sapersky (2008-06-17 13:15:00) [6]Для записи с WideString могу предложить хакерский метод, позволяющий писать/читать запись одной командой. Но вам, как начинающему, возможно, лучше о нём не знать :)
EgorovAlex (2008-06-17 12:47:00) [7]Для такой записи всё просто, она же фиксированной длины, да к тому же и не юникодная
Palladin (2008-06-17 11:53:00) [8]
> Идея рассматривалась на http://forum.sources.ru
однако растут :) какие великие идеи рассматривать начали
Василий Жогарев (2008-06-17 11:30:00) [9]
> Запись в файл и чтение из файла записи: есть запись:
>
> 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
Поросенок Винни-Пух (2008-06-17 11:05:00) [10]тебе перепечатать сюда штатную справку?
EgorovAlex (2008-06-17 10:57:00) [11]Что за функции работы со строками? Какие преимущества они дадут?
Поросенок Винни-Пух (2008-06-17 10:41:00) [12]1. New(Rec2) красивше чем гетмем в этом случае.
2. Память под строки распределять надо и надо копировать сами строки если хочешь именно дубликат записи, а не две записи с указателями на один и тот же буфер.
3. Со строками тоже лучше работать через строковые функции а не через гетмем и копимемори
EgorovAlex (2008-06-17 09:50:00) [13]С этим разобрался, спасибо, теперь для уточнения моих познаний :)
(т.к. старался всегда использовать только записи с фиксированными полями, а не указателями)
Если у меня есть запись 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-16 17:10:00) [14]ридбуфер требует параметром адрес, а не указатель
Поросенок Винни-Пух (2008-06-16 17:09:00) [15]Эт я не в ту ветку запостил
EgorovAlex (2008-06-16 17:05:00) [16]так нет никаких исключений, но и не читается :(
to TForumHelp
а как читать-то :)
TForumHelp (2008-06-16 17:02:00) [17]ну еще бы читалось.
Поросенок Винни-Пух (2008-06-16 17:01:00) [18]try
ms := T....Stream.create(...);
except
on E:Exception do ShowMessage('Ой, мама!'#13#10 + E.Message)
end
EgorovAlex (2008-06-16 16:54:00) [19]Вроде всё так и написано в приведённом коде, но считать почему-то не получается, читаю так:
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 16:50:00) [20]записать длину первого поля.
записать само первое поле.
записать длину второго поля
записать само второе поле.