-
record s1, s2: PWideChar; end;
Как мне её записать в файл и потом прочитать из файла?
пробовал так: MS: TMemoryStream;
MS.Write(Rec^, SizeOf(Rec)); MS.Position := 0; MS.WriteToFile...
но потом при чтении из файла (тоже через мемористрим) не читаются s1 и s2.
Что я не так делаю?
-
все так. что записал то и считал.
-
Поразмышляй вот над этим: showmrssage(inttostr(SizeOf(rec)))
-
Я над этим уже поразмышлял :) только как применить пока не понимаю, я понял, что я пишу 2 байта указателей, а не содержимое полей записи, а вот как записать всё?
-
> как записать всё?
также. Write() каждое поле отдельно
-
плюс еще записать туда же обе длины чтобы знать сколько читать в последствии
-
т.е. писать так?
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...
-
записать длину первого поля. записать само первое поле. записать длину второго поля записать само второе поле.
-
Вроде всё так и написано в приведённом коде, но считать почему-то не получается, читаю так:
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;
-
try ms := T....Stream.create(...); except on E:Exception do ShowMessage('Ой, мама!'#13#10 + E.Message) end
-
ну еще бы читалось.
-
так нет никаких исключений, но и не читается :(
to TForumHelp
а как читать-то :)
-
Эт я не в ту ветку запостил
-
ридбуфер требует параметром адрес, а не указатель
-
С этим разобрался, спасибо, теперь для уточнения моих познаний :) (т.к. старался всегда использовать только записи с фиксированными полями, а не указателями)
Если у меня есть запись 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));
-
1. New(Rec2) красивше чем гетмем в этом случае. 2. Память под строки распределять надо и надо копировать сами строки если хочешь именно дубликат записи, а не две записи с указателями на один и тот же буфер. 3. Со строками тоже лучше работать через строковые функции а не через гетмем и копимемори
-
Что за функции работы со строками? Какие преимущества они дадут?
-
тебе перепечатать сюда штатную справку?
-
> Запись в файл и чтение из файла записи: есть запись: > > 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
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);
end;
finally
CloseFile(F);
end;
end; Идея рассматривалась на http://forum.sources.ru
-
-
Для такой записи всё просто, она же фиксированной длины, да к тому же и не юникодная
-
Для записи с WideString могу предложить хакерский метод, позволяющий писать/читать запись одной командой. Но вам, как начинающему, возможно, лучше о нём не знать :)
-
Все мы когда-то в чём-то начинающие, не томи, показывай :)
-
-
Опять вопрос: Сейчас записываю в стрим так: 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 появляется какой-то мусор. Почему?
-
Насколько я понял, WStrLen (из TntWideStrUtils), даёт длину без завершающего #0, а в WStrAlloc её нужно указывать с учётом нуля, во всяком случае, WStrNew берёт Size := WStrLen(Str) + 1.
И вот это зачем: MS.WriteBuffer(Rec^, SizeOf(TMyRec)); MS.ReadBuffer(Rec^, SizeOf(TMyRec));
-
Это здесь не нужно, просто по инерции на упрощённыи пример перекинул, а в D2007 WStrLen уже в WideStrUtils есть. Да, с прибавлением единицы перед записью проблема решилась
|