Форум: "Основная";
Текущий архив: 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.013 c