Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 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
15-1212582496
TStas
2008-06-04 16:28
2008.07.20
Что значит: Группы Google: Ваш адрес был добавлен в группу MPST?


2-1213686010
webpauk
2008-06-17 11:00
2008.07.20
Найти MDI


2-1213898401
ProofNA
2008-06-19 22:00
2008.07.20
Работа с принтером


15-1212666482
ЧуВАГ
2008-06-05 15:48
2008.07.20
Delphi uses


2-1214198328
ganda
2008-06-23 09:18
2008.07.20
Class + Memory





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский