![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Чтение и запись строки в Stream
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)^