Форум: "Начинающим";
Текущий архив: 2008.07.20;
Скачать: [xml.tar.bz2];
ВнизЗапись в файл и чтение из файла записи: есть запись: Найти похожие ветки
← →
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;
Скачать: [xml.tar.bz2];
Память: 0.51 MB
Время: 0.039 c