Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2006.05.28;
Скачать: [xml.tar.bz2];

Вниз

Чтение и запись строки в 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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.54 MB
Время: 0.011 c
2-1147339727
Hitkliff
2006-05-11 13:28
2006.05.28
ВебБраузер??


2-1147511357
Vitalik__
2006-05-13 13:09
2006.05.28
Кто нибудь работал с SynEdit?


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


3-1144058948
barakuda
2006-04-03 14:09
2006.05.28
Отчет руками


2-1147446716
Silica
2006-05-12 19:11
2006.05.28
Числа





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