Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Чтение и запись строки в Stream


Страницы:   1 2

vidiv ©   (2006-04-12 09:25:00) 

Можно ли так производить запись и чтение строки из Stream-а:

procedure SaveStringToStream(Str:string; Stream:TStream);
var L:integer;
begin
   L := length(Str);
   Stream.WriteBuffer(L, SizeOf(L));
   Stream.WriteBuffer( Str[1], L);
end;

function LoadStringFromStream(Stream:TStream):string;
var L:integer;
begin
   Stream.ReadBuffer(L, SizeOf(L));
   SetLength(Result, L);
   Stream.ReadBuffer( Result[1], L);
end;


Больше всего интересует выделенный фрагмент


Сергей М.   (2006-04-12 13:48:00) [21]


> Lamer@fools.ua ©   (12.04.06 13:29) [16]


> ещё лучше (в плане скорости) Pointer(Str)^.


Соблаговоли привести аргументы в пользу такого утверждения...


Lamer@fools.ua   (2006-04-12 13:29:00) [22]

>> MBo ©   (12.04.06 09:31) [2]

> Лучше использовать вместо Str[1]  -  PChar(Str)^

А ещё лучше (в плане скорости) Pointer(Str)^.


jack128   (2006-04-12 13:02:00) [23]

MBo ©   (12.04.06 12:47) [14]
Что-то ты много лишнего накрутил и не то смотришь - конечно, при SetLength адрес меняется.

ну кстати - это для меня это совсем не очевидно было. Мне казалось, что при SetLength(s, Length(S)); адрес не изменится.  А реальность оказалось несколько сложнее.

Но дело в другом.  Если SetLength - копирует строку, то счетчик ссылок этой строки - становится равным 1.  Так? Так.  А раз так, то и UniqueString не будет копировать строку(зачем её копировать, если строка итак уникальная). Поэтому и различие в прозводительности между S[1] и PChar(S)^  минимальна.

То есть вот в таком коде

function ReadString(Stream: TStream): string;
var
L: Integer;
OldP, NewP: Pointer;
begin
Stream.ReadBuffer(L, SizeOf(L));
SetLength(Result, L);
if L > 0 then
begin
  OldP := Pointer(Result);
  Stream.ReadBuffer(Result[1], L);
  NewP := Pointer(Result);
  Assert(OldP = NewP);
end
else
  Result := '';
end;


assert никогда не сработает!!


MBo   (2006-04-12 12:47:00) [24]

>jack128 ©   (12.04.06 11:40) [12]
Что-то ты много лишнего накрутил и не то смотришь - конечно, при SetLength адрес меняется.
Я говорил о том, что при использовании S[1] происходит вызов UniqueString, что в данном случае лишнее.


begin...end   (2006-04-12 12:18:00) [25]

> Anatoly Podgoretsky ©   (12.04.06 09:31) [1]
> Anatoly Podgoretsky ©   (12.04.06 09:48) [3]

Чушь. Никакого AV не будет и при L = 0.


jack128   (2006-04-12 11:40:00) [26]

MBo ©   (12.04.06 9:56) [6]
C PChar не вызывается UniqueString, что накладно при существенной длине строки.


копирование строки в любом случае будет:

function ReadString(Stream: TStream): string;
var
 L: Integer;
 OldP, NewP: Pointer;
begin
 Stream.ReadBuffer(L, SizeOf(L));
 OldP := Pointer(Result);
 Assert(Length(Result) = L);
 SetLength(Result, L);
 NewP := Pointer(Result);
 ShowMessage(Format('OldP = %8x, NewP = %8x', [Integer(OldP), Integer(NewP)])); // произошло копирование строки
 if L > 0 then
   Stream.ReadBuffer(PChar(Result)^, L)
 else
   Result := '';
end;

procedure TForm2.FormCreate(Sender: TObject);
var
 Stream: TStream;
 S1, S2, S3: string;
 L: Integer;
begin
 Stream := TMemoryStream.Create;
 try
   L := 100;
   S1 := StringOfChar('A', L);
   S2 := S1;
   S3 := StringOfChar('B', L);
   Stream.WriteBuffer(L, SizeOf(L));
   Stream.WriteBuffer(S3[1], L);
   Stream.Position := 0;
   S1 := ReadString(Stream);
   ShowMessage(S1);
   ShowMessage(S2);
 finally
   Stream.Free;
 end;
end;


с другой стороны - если бы при SetLength - копирования строки не происходило, то S2 тоже изменилось бы при вызове ReadString/ А это выглядило бы несколько странно, согласись ;-)


Anatoly Podgoretsky   (2006-04-12 10:53:00) [27]

vidiv ©   (12.04.06 09:49) [4]
Т.е. учитывая все, вот так будет правильно:

  SetLength(Result, L);
  if L > 0 then
      Stream.ReadBuffer(PChar(Result)^, L)
  else
      Result := '';

Почти, если убрать лишнии действия, то так

  SetLength(Result, L);
  if L > 0 then
      Stream.ReadBuffer(PChar(Result)^, L)


Leonid Troyanovsky   (2006-04-12 10:46:00) [28]


> vidiv ©   (12.04.06 09:57) [7]

> А как тогда правильно?


TStringStream.Create & etc

--
Regards, LVT.


vidiv   (2006-04-12 10:26:00) [29]

Спасибо :)


MBo   (2006-04-12 10:10:00) [30]

>А как тогда правильно?
Да правильно у тебя, кроме описки с Result в SaveString


vidiv   (2006-04-12 09:57:00) [31]

А как тогда правильно?


MBo   (2006-04-12 09:56:00) [32]

C PChar не вызывается UniqueString, что накладно при существенной длине строки.


vidiv   (2006-04-12 09:51:00) [33]

Функция точнее такая

function LoadStringFromStream(Stream:TStream):string;
var L:integer;
begin
  Stream.ReadBuffer(L, SizeOf(L));
  if L > 0 then begin
      SetLength(Result, L);
      Stream.ReadBuffer(PChar(Result)^, L)
  end else
      Result := '';
end;


vidiv   (2006-04-12 09:49:00) [34]

Т.е. учитывая все, вот так будет правильно:

procedure SaveStringToStream(Str:string; Stream:TStream);
var L:integer;
begin
   L := length(Str);
   Stream.WriteBuffer(L, SizeOf(L));
   if L > 0 then
       Stream.WriteBuffer(PChar(Result)^, L);
end;

function LoadStringFromStream(Stream:TStream):string;
var L:integer;
begin
   Stream.ReadBuffer(L, SizeOf(L));
   SetLength(Result, L);
   if L > 0 then
       Stream.ReadBuffer(PChar(Result)^, L)
   else
       Result := '';
end;


Anatoly Podgoretsky   (2006-04-12 09:48:00) [35]

Результат одинаков AV


Anatoly Podgoretsky   (2006-04-12 09:31:00) [36]

Можно, если L>0


MBo   (2006-04-12 09:31:00) [37]

Лучше использовать вместо Str[1]  -  PChar(Str)^


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо