StreamReader шаг назад
От: vladpol Украина http://vlad-mislitel.livejournal.com/
Дата: 08.12.15 17:15
Оценка:
Что за ерунда?
Пытаюсь сдвинуть позицию чтения на шаг назад
StreamReader _reader;
 Stream stream = new MemoryStream((new UTF32Encoding().GetBytes(text)), false);
            _reader = new StreamReader(stream, new UTF32Encoding());
//...
_reader.BaseStream.Seek(-1, SeekOrigin.Current);


Но оказывается, что _reader.BaseStream.Position в этот момент равно _reader.BaseStream.Capacity

И сдвигаюсь я не на шаг назад, а на шаг назад от конца.

Как-то с этой [censored] можно бороться?

Спасибо
С уважением, Владислав Полищук
Re: StreamReader шаг назад
От: Nikolay_Ch Россия  
Дата: 08.12.15 18:05
Оценка: +1
V>_reader.BaseStream.Seek(-1, SeekOrigin.Current);
А зачем Вы дергаете BaseStream? Что Вам мешает дергать Seek у ридера?
Re: StreamReader шаг назад
От: Sinix  
Дата: 08.12.15 18:24
Оценка: 1 (1)
Здравствуйте, vladpol, Вы писали:

V>Что за ерунда?

V>Пытаюсь сдвинуть позицию чтения на шаг назад
V>
V>StreamReader _reader;
V> Stream stream = new MemoryStream((new UTF32Encoding().GetBytes(text)), false);
V>            _reader = new StreamReader(stream, new UTF32Encoding());
V>//...
V>_reader.BaseStream.Seek(-1, SeekOrigin.Current);
V>


V>Но оказывается, что _reader.BaseStream.Position в этот момент равно _reader.BaseStream.Capacity

Ну так вы прочитали что-то ридером, иначе с чего position поменялось-то?
Проверяйте отладчиком и расставляйте ассерты.

V>И сдвигаюсь я не на шаг назад, а на шаг назад от конца.

Нет, сдвигаетесь вы на шаг назад от текущей позиции. А вот как вы там оказались — это не к ридеру вопрос.

V>Как-то с этой [censored] можно бороться?

Как всегда, изучением матчасти. Сам по себе поток никогда позицию не меняет. StreamReader считывает контент порциями, размер буфера по умолчанию зависит от фреймворка, или 1 кб, или 4. Ставьте точку остановки на MemoryStream.Read (выключить just my code debugging) и смотрите, что там у вас лезет в поток.

P.S. Для смешанного контента вам нужен unbuffered stream reader, что-то типа такого.
Отредактировано 08.12.2015 18:30 Sinix . Предыдущая версия .
Re[2]: StreamReader шаг назад
От: Sinix  
Дата: 08.12.15 18:27
Оценка: 3 (1)
Здравствуйте, Nikolay_Ch, Вы писали:

N_C>А зачем Вы дергаете BaseStream? Что Вам мешает дергать Seek у ридера?

А нет его у ридера. System.IO, наследие первого фреймворка, все дела.
Re[2]: StreamReader шаг назад
От: vladpol Украина http://vlad-mislitel.livejournal.com/
Дата: 08.12.15 19:55
Оценка:
Здравствуйте, Sinix, Вы писали:

V>>И сдвигаюсь я не на шаг назад, а на шаг назад от конца.

S>Нет, сдвигаетесь вы на шаг назад от текущей позиции. А вот как вы там оказались — это не к ридеру вопрос.
Что вы имеете ввиду? Я читаю один символ , а Position = 200
С уважением, Владислав Полищук
Re[3]: StreamReader шаг назад
От: Sinix  
Дата: 08.12.15 20:23
Оценка:
Здравствуйте, vladpol, Вы писали:

V>Что вы имеете ввиду? Я читаю один символ , а Position = 200


Ну вот с этого и надо было начинать А то "оно само сместилось" и прочая мистика — попробуй угадай, в чём на самом деле проблема.


StreamReader считывает контент порциями. Позиция = min(остаток, размер буфера).

Как всегда, для ответа на "и что с этим делать?" нужно знать, какую задачу вы пытаетесь решить и чем вас не устраивает текущее поведение.
Re[3]: StreamReader шаг назад
От: hardcase Пират http://nemerle.org
Дата: 08.12.15 20:23
Оценка: 2 (1) +2
Здравствуйте, vladpol, Вы писали:

V>Что вы имеете ввиду? Я читаю один символ , а Position = 200


Только вот смещение на один байт назад != смещение на один символ назад. Твои 200 байт прокачал внутрь себя StreamReader чтобы декодировать юникод.
/* иЗвиНите зА неРовнЫй поЧерК */
Re[4]: StreamReader шаг назад
От: vladpol Украина http://vlad-mislitel.livejournal.com/
Дата: 08.12.15 21:08
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Как всегда, для ответа на "и что с этим делать?" нужно знать, какую задачу вы пытаетесь решить и чем вас не устраивает текущее поведение.


У меня простенький лексический анализатор. Посимвольно читаю из потока. В одном хитром случае нужно, грубо говоря, вернуть символ обратно в поток.
Понятно, что можно написать обертку или работать с массивом и т.д. и т.п. Но думал есть более простой способ
С уважением, Владислав Полищук
Re[5]: StreamReader шаг назад
От: hardcase Пират http://nemerle.org
Дата: 08.12.15 21:24
Оценка: +1
Здравствуйте, vladpol, Вы писали:

V>У меня простенький лексический анализатор. Посимвольно читаю из потока.


Если простенький, то зачем машинерия со Stream/TextReader, почему бы не использовать String?
/* иЗвиНите зА неРовнЫй поЧерК */
Re[5]: StreamReader шаг назад
От: Sinix  
Дата: 09.12.15 06:23
Оценка: 2 (1)
Здравствуйте, vladpol, Вы писали:

V>У меня простенький лексический анализатор. Посимвольно читаю из потока. В одном хитром случае нужно, грубо говоря, вернуть символ обратно в поток.

V>Понятно, что можно написать обертку или работать с массивом и т.д. и т.п. Но думал есть более простой способ
А, тогда стандартный streamreader вам не совсем подходит. Но ничего не мешает сделать простенькую обёртку, которая будет запоминать, затем откатывать позицию потока и вызывать reader.DiscardBufferedData. Для посимвольного чтения вообще Read() + Peek() достаточно.

P.S. Seek на -1 неправильно в принципе. 1 символ может занимать от 1 до 4 байт, в зависимости от кодировки.
Re: StreamReader шаг назад
От: Sinatr Германия  
Дата: 09.12.15 07:55
Оценка:
Здравствуйте, vladpol, Вы писали:

V>Как-то с этой [censored] можно бороться?


А почему не используете StringReader? Впрочем у него тоже нет Seek.

Кстате, похожий вопрос задавали на SO. Может найдете что-то полезное.
---
ПроГLамеры объединяйтесь..
Re[2]: StreamReader шаг назад
От: Sinix  
Дата: 09.12.15 07:58
Оценка:
Здравствуйте, Sinatr, Вы писали:

S>А почему не используете StringReader?

Так он требует держать в памяти всю строку. Для больших объёмов не подходит.
Re: StreamReader шаг назад
От: LWhisper  
Дата: 09.12.15 16:23
Оценка: 38 (1) +1
Здравствуйте, vladpol, Вы писали:
V>Как-то с этой [censored] можно бороться?
По-простому не получится. У меня была схожая задача — на лету поменять кодировку StreamReader'а.
Но по человечески это сделать нельзя, так как даже если ты вытащишь всю необходимую информацию при помощи отражения из StreamReader'а, останется Decoder, который лежит в нём и может содержать в себе половинки символов. То бишь из потока ты считываешь один байт, а декодер считает, что это управляющая последовательность и просит у тебя ещё 4. И вот эти куски из декодера не выдрать (вроде бы, для этого служит Convert, но он работает обратно здравому смыслу).

В итоге я просто написал собственный StreamReader, чего и тебе желаю. Если тебе не нужна полноценная имплементация TextReader'а, автоматический детект кодировки по преамбуле и прочая хрень, это сделать очень просто. Точно также проинициализируй свой класс кодировкой, получи из неё декодер, заведи внутренний буфер, и читай кусками, вручную контролируя позицию перед каждой операцией.

А если никакого расширения в последствии не будет, то и читай просто по байтам, явно приводя их к Char'ам — нехорошо, но если нужно быстро и топорно, то почему бы и нет. Не придётся возиться с половинчатыми символами и прочей пакостью.

P.S. А вообще стоит описать свою задачу. В повторной обработке одного и того же текста нет ничего хорошего. Возможно, от неё легко можно избавиться?
Re[2]: StreamReader шаг назад
От: vladpol Украина http://vlad-mislitel.livejournal.com/
Дата: 09.12.15 21:08
Оценка:
Здравствуйте, LWhisper, Вы писали:

LW>В итоге я просто написал собственный StreamReader, чего и тебе желаю. Если тебе не нужна полноценная имплементация TextReader'а, автоматический детект кодировки по преамбуле и прочая хрень, это сделать очень просто. Точно также проинициализируй свой класс кодировкой, получи из неё декодер, заведи внутренний буфер, и читай кусками, вручную контролируя позицию перед каждой операцией.


LW>А если никакого расширения в последствии не будет, то и читай просто по байтам, явно приводя их к Char'ам — нехорошо, но если нужно быстро и топорно, то почему бы и нет. Не придётся возиться с половинчатыми символами и прочей пакостью.


Спасибо за совет. Я уже написал свою обертку над StreamReader'ом. Получилось пока может не сильно изящно, но надежно. Модуль, по сути, вспомогательный и хочется сосредоточиться на главной задаче. Если она взлетит — перепишу анализатор
С уважением, Владислав Полищук
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.