суббота, 25 апреля 2009 г.

Перехват потока вывода в Ruby

Ну вот таки добрался до писанины, и вы читаете эти страдания полуношника (чёрт! быква "ш" опять с трудом набирается...).

Я вот недавно писал, что так и не смог разобраться с тем, как перенаправить данные из основного потока вывода в некоторый буфер, чтобы потом их в сооветствии с некоторой логикой обработать. Сейчас вот мы и попытаемся найти приемлемый для этого метод.

Итак, буффер стандартного потока вывода в Ruby определяется глобальной переменной $std_out. Она используется ядром для основного процесса вывода. По природе своей она значением содержит экземпляр объекта StringIO ( константа - STDOUT), который и поставляет разнообразнейшие методы для реализации буфера хранения потоковых данных и их выброса куда вам необходимо. Его декларация содержится в файле stringio.

Описанная же в начале проблема решается довольно просто, как, вероятно, многие из читателей уже смогли понять - назначением $std_out пользовательского объекта типа StringIO, в который и будет отвечать за буфферизацию всего, что будет выброшено в поток до того момента, пока не будет вновь назначен в качестве основного стандартный поток (STDOUT).

Вот что у меня получилось:
# output_handling.rb
# Подключаем файл поставляющий класс StringIO
require "stringio"
# Создаём промежуточный буффер
temp_output = StringIO.new();
# Указываем созданный нами буффер в качестве основного
$std_output = temp_output;
# Выводим некоторые данные в поток
puts "I hate you! I hate you! I hate you!!!!!!!";

# Вновь указывает стандартный поток вывода в качестве основного
$std_output = STDOUT;

# Переводим указатель смещения на начало
temp_output.rewind();
# Выводим содержимое временного буффера
puts tmp_output.read();


Вообще, наверное не стоит рассказывать о всей пользе подобной возможности. Однако спорный момент "хорошести" подобного подхода. Так, при переопределении потока вывода вы это делаете для области всей программы, что не хорошо в контексте многопоточности. Эта проблема довольно хорошо решается в том же PHP, где перехват данных потока осуществляется с помощью возможностей платформы (ob_start() и ob_end()).

Комментариев нет:

Отправить комментарий