Странности с LoadFromStream

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Странности с LoadFromStream

Сообщение Troublemaker » 11.05.2008 19:04:32

Это у меня одного так:

(TempStream и INISTream - оба TMemoryStream, оба уже .create на момент работы следующего кода)

MyIni:=TStringList.Create;
IniName:=ExtractFilePath(Application.ExeName)+'formtest.pp';
if FileExists(IniName) then begin
TempStream.LoadFromFile(IniName); //читает весь файл, как и должно (* 1)

//следующие две строки вставлены для отладки вместо настоящей обработки
//которая должна переварить TempStream и переложить его в INISTream
INISTream.CopyFrom(TempStream,TempStream.Size); //копируется всё, что надо
INISTream.SaveToFile(IniName+'.new'); //сохраненный файл - точная копия из (* 1)

//следующая строка не работает. Даже в раскомментированном виде :shock:
// MyIni.LoadFromStream(INISTream); //НЕ РАБОТАЕТ! после нее MyIni.count=0

MyIni.LoadFromfile(IniName); //а вот это работает и .count точно равен числу строк в файле

Это я что-то делаю не так, или опять глюк в RTL?
Аватара пользователя
Troublemaker
постоялец
 
Сообщения: 292
Зарегистрирован: 16.04.2008 13:00:44
Откуда: Биробиджан, Дальний Восток

Re: Странности с LoadFromStream

Сообщение Deepthroat » 11.05.2008 19:38:07

Перед чтением (а равно копированием) из потока, установи внутренний курсор в начало потока. По-моему, метод TFileStream.Seek(), но точно не скажу, см. мануал.
Аватара пользователя
Deepthroat
постоялец
 
Сообщения: 144
Зарегистрирован: 06.09.2007 00:21:34
Откуда: Outer Heaven

Re: Странности с LoadFromStream

Сообщение Troublemaker » 11.05.2008 19:56:39

Э-э... обязательно проверю, хотя по логике LFS сама должна это делать. Ща...

Добавлено спустя 2 минуты 19 секунд:
Гм... действительно помогло. Большое спасибо. Видать, с разработчиком LFS у нас несколько разные системы логики.
Аватара пользователя
Troublemaker
постоялец
 
Сообщения: 292
Зарегистрирован: 16.04.2008 13:00:44
Откуда: Биробиджан, Дальний Восток

Re: Странности с LoadFromStream

Сообщение shade » 11.05.2008 20:15:48

"В один поток нельзя войти дважды"

В случае с TStream иногда (пожалуй в типичных случаях) можно и дважды. У потока как и у файла есть (*) внутрений указатель, который перемещается по мере чтения/записи и методом Seek() и изменением свойтва Position. В TFileStream, TMemoryStream, TStringStream - метод Seek должен работать.

Т.е. в первом приближении поток можно рассматривать как тот же файл. Соответствено у вас получилось следующее
1. TempStream.LoadFromFile(IniName); // прочитали файл в TempStream, указатель TempStream на нуле
2. INISTream.CopyFrom(TempStream,TempStream.Size); // закопировали, но теперь TempStream.Position = INISTream.Position = TempStream.Size, т.е. оба указателя в конце потока
3. INISTream.SaveToFile(IniName+'.new'); // сохраняете, судя по иходникам, сохраняется все, а указатель остается на прежнем месте, т.е. в конце (см. 2)
4. MyIni.LoadFromStream(INISTream); // пытаетесь загрузить из потока, но указатель INISTream находиться в конце!, т.е. MyIni пытается читать из конца потока, а не из начала. Потому добавьте перед этим INIStream.Position := 0;

(*) точнее может быть, но не у всех, например у TSocketStream его быть просто не может.
Аватара пользователя
shade
энтузиаст
 
Сообщения: 879
Зарегистрирован: 21.02.2006 20:15:48
Откуда: http://shamangrad.net/

Re: Странности с LoadFromStream

Сообщение Troublemaker » 11.05.2008 20:22:53

shade писал(а):MyIni.LoadFromStream(INISTream); // пытаетесь загрузить из потока, но указатель INISTream находиться в конце!, т.е. MyIni пытается читать из конца потока, а не из начала.

Я уже это понял, почему и написал, что помогло.
Просто сначала я исходил вот из какой логики: раз tstrings.LFS полностью заменяет содержимое TStrings, то и читать оно должно с начала потока, самостоятельно переставляя position:=0.
На этом и споткнулся, причем настолько, что уже написал "слабое подобие левой руки", то бишь аналог readln но для tstream (readAnsiString не катит из-за формата этой строки) и так построчно перекачал stream в stringlist.
Аватара пользователя
Troublemaker
постоялец
 
Сообщения: 292
Зарегистрирован: 16.04.2008 13:00:44
Откуда: Биробиджан, Дальний Восток

Re: Странности с LoadFromStream

Сообщение Vadim » 12.05.2008 05:19:52

Вот что нам рассказывают исходники... :)
"Давным давно, в одной далёкой, далёкой галактике..." :)
Код: Выделить всё
Procedure TStrings.LoadFromStream(Stream: TStream);
{
   Borlands method is no good, since a pipe for
   instance doesn't have a size.
   So we must do it the hard way.
}
...
    Repeat
      BufDelta:=BufSize*I;
      SetLength(Buffer,BufLen+BufDelta);
      BytesRead:=Stream.Read(Buffer[BufLen+1],BufDelta);
...

Код, который не имеет отношения к вопросу обсуждения, я пропустил.
Как видно, чтение в буфер из заданного потока начинается с текущей позиции этого потока, а не сначала, как хотелось бы ожидать при загрузке потока целиком. Перед чтением нигде нет установки позиции в потоке на начало потока.
Я тоже считаю это недоработкой, но, увы, пока что на это никто не обратил внимания разработчиков...
Vadim
долгожитель
 
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: Странности с LoadFromStream

Сообщение Sergei I. Gorelkin » 12.05.2008 07:51:52

Какая такая недоработка?

Если сбрасывать в ноль позицию во входном потоке, то:
1) Станет невозможным чтение из потоков, не допускающих изменение позиции (а это подавляющее большинство потоков, реализующих сжатие, шифрование; стандартный ввод-вывод, сокеты - грубо говоря, всё кроме TFileStream и TMemoryStream).
2) Станет невозможным чтение данных, расположенных не с начала потока.
3) Придется переотлаживать весь уже написанный на Дельфи код, потому что он станет работать по-другому.

Шире надо мыслить, товарищи...
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1406
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Re: Странности с LoadFromStream

Сообщение Timid » 17.05.2008 07:36:28

Я тоже считаю это недоработкой, но, увы, пока что на это никто не обратил внимания разработчиков...

2 Vadim
Видимо вы недавно в Win(Linux) программировании и не поняли смысл использования потоков, а используете их просто как заменители файлов.
Это в корне неверно идеологически. Просто нативный инструментарий разработки с использованием потоков слишком сложен, поэтому были придуманы заглушки, вроде LoadFromStream с автопозиционированием на начало.
В идеале, поток - это просто "отверстие", в которое вы будете загружать данные (или извлекать), как ввод с клавиатуры или вывод на экран.
Для "полноценного" использования потоков вам необходимо создавать его потомка, который бы производил необходимые преобразования прямо при загрузке. Например, как в объекте TTextStream, при загрузке которого автоматически создается коллекция строк.
Timid
постоялец
 
Сообщения: 290
Зарегистрирован: 21.11.2007 21:33:15


Вернуться в Free Pascal Compiler

Кто сейчас на конференции

Сейчас этот форум просматривают: Google [Bot] и гости: 3

Рейтинг@Mail.ru