Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.05.28;
Скачать: CL | DM;

Вниз

Чтение и запись строки в Stream   Найти похожие ветки 

 
vidiv ©   (2006-04-12 09:25) [0]

Можно ли так производить запись и чтение строки из 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;


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


 
Anatoly Podgoretsky ©   (2006-04-12 09:31) [1]

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


 
MBo ©   (2006-04-12 09:31) [2]

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


 
Anatoly Podgoretsky ©   (2006-04-12 09:48) [3]

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


 
vidiv ©   (2006-04-12 09:49) [4]

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

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;


 
vidiv ©   (2006-04-12 09:51) [5]

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

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;


 
MBo ©   (2006-04-12 09:56) [6]

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


 
vidiv ©   (2006-04-12 09:57) [7]

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


 
MBo ©   (2006-04-12 10:10) [8]

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


 
vidiv ©   (2006-04-12 10:26) [9]

Спасибо :)


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


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

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


TStringStream.Create & etc

--
Regards, LVT.


 
Anatoly Podgoretsky ©   (2006-04-12 10:53) [11]

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)


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

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/ А это выглядило бы несколько странно, согласись ;-)


 
begin...end ©   (2006-04-12 12:18) [13]

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

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


 
MBo ©   (2006-04-12 12:47) [14]

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


 
jack128 ©   (2006-04-12 13:02) [15]

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 никогда не сработает!!


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

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

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

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


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


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


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


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


 
jack128 ©   (2006-04-12 13:51) [18]

Сергей М. ©   (12.04.06 13:48) [17]
Соблаговоли привести аргументы в пользу такого утверждения...

потому что преобразование строки к PChar приводит к вызову функции, преобразование к Pointer - вообще не добавляет ни одной инструкции в код. Вобщем то все это можно увидеть в окне CPU


 
MBo ©   (2006-04-12 13:56) [19]

>jack128
При чтении в строку - да, uniquestring быстро сработает. А вот при записи  - по-разному может быть, поскольку может сложиться, что счетчик ссылок не единичный.


 
MBo ©   (2006-04-12 13:59) [20]

>потому что преобразование строки к PChar приводит к вызову функци
В принципе - да, но фактически это всего несколько тактов.


 
Сергей М. ©   (2006-04-12 14:05) [21]


> jack128 ©   (12.04.06 13:51) [18]


см. [20]

Практически это ловля блох.


 
TStream   (2006-04-18 04:04) [22]

> MBo
> может сложиться, что счетчик ссылок не единичный.
А где показывается колличество ссылок? Как посмотерть этот счётчик?

И есть ли разница между Write и WriteBuffer?


 
Lamer@fools.ua ©   (2006-04-18 09:43) [23]

>>MBo ©   (12.04.06 13:59) [20]

В цикле, чьё тело выполняется много раз, и несколько тактов бывают важны. Но это уже, вероятно, к сабджу не относится.


 
Apavl   (2006-04-18 15:12) [24]

Я подгядел код и делаю так
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;

procedure TForm1.Button5Click(Sender: TObject);
var
 Stream: TStream;
begin
 Stream := TStream.Create;
 SaveStringToStream("22 33 44", Stream);

end;


 
Slym ©   (2006-04-18 15:15) [25]

TStream - абстрактный класс...
и ошибка скорее всего "абстрактная" :)


 
Apavl   (2006-04-18 15:17) [26]

Да, ошибка абстрактная. Так как ее исправить?


 
Slym ©   (2006-04-18 15:26) [27]

Apavl   (18.04.06 15:17) [26]
Да, ошибка абстрактная. Так как ее исправить?

не исправлять надо, а избегать:
не создавать абстрактных классов коим является TStream,
пользуй TMemoryStream, TStringStream, всякие TFileStream


 
Apavl   (2006-04-18 15:30) [28]

Стал использовать TStringStream. Ошибка исчезла, но появилась другая.

При вызове
function LoadStringFromStream(Stream:TStream):string;
var L:integer;
begin
  Stream.ReadBuffer(L, SizeOf(L)); --здесь ошибка stream read error.
  SetLength(Result, L);
  if L > 0 then
      Stream.ReadBuffer(PChar(Result)^, L)
  else
      Result := "";
end;


 
Slym ©   (2006-04-18 15:33) [29]

а ты чтонибудь положил в "коробочку", чтобы чтонибудь взять?


 
Apavl   (2006-04-18 15:34) [30]

да
SaveStringToStream("dsgf dsf g", Stream);
ShowMessage(LoadStringFromStream(Stream));


 
Slym ©   (2006-04-18 15:35) [31]

SaveStringToStream("dsgf dsf g", Stream);
Stream.Position:=0;
ShowMessage(LoadStringFromStream(Stream));


 
Apavl   (2006-04-18 15:39) [32]

супер, спасибо!


 
TStream   (2006-04-19 07:30) [33]

> MBo
> может сложиться, что счетчик ссылок не единичный.
А где показывается колличество ссылок? Как посмотерть этот счётчик?

И есть ли разница между Write и WriteBuffer?


 
TStream   (2006-04-20 03:34) [34]

Короче никто не знает где счётчик ссылок? Если не знаете, то какие же вы мастера после этого?


 
Джо ©   (2006-04-20 03:53) [35]

> [34] TStream   (20.04.06 03:34)
> Короче никто не знает где счётчик ссылок? Если не знаете,
> то какие же вы мастера после этого?

Тебе не кажется, что это уже хамством попахивает?
Счетчик ссылок на строку хранится по отрицательному смещению -8 от начала области памяти, где размещена строка. Занимает 4 байта (Integer).


 
Германн ©   (2006-04-20 04:07) [36]


> Джо ©   (20.04.06 03:53) [35]


А что, вчера тоже был повод?
Ну так купиться на "подколку" некоего TStream"a!


 
Anatoly Podgoretsky ©   (2006-04-20 08:42) [37]

TStream   (20.04.06 03:34) [34]
Песочница в соседнем квартале.



Страницы: 1 вся ветка

Текущий архив: 2006.05.28;
Скачать: CL | DM;

Наверх




Память: 0.56 MB
Время: 0.05 c
15-1146384583
Rule
2006-04-30 12:09
2006.05.28
Нет ли желания сделать мастак пати ???


4-1141487716
Volf_555
2006-03-04 18:55
2006.05.28
Как сделать копию экрана когда играет видео?


2-1147166724
seleman
2006-05-09 13:25
2006.05.28
xpmanifest


15-1146718299
syte_ser78
2006-05-04 08:51
2006.05.28
вот это спам так спам.


15-1146812786
REA
2006-05-05 11:06
2006.05.28
BDS 2006 - скорость загрузки