Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

СУБД Oracle для разработчиков. Forms and Reports 6i-10g


Файловый Ввод/Вывод в Oracle Forms

Сергеенко С.В.

                Пакет TEXT_IO в Oracle Forms - самая последняя новинка, обеспечивающая доступ к файлам операционной системы. Стивен использует ее для построения другого "Свежего Инструмента", который необходим каждому разработчику Oracle.

Пакет TEXT_IO позволяет приложению, разработанному на Oracle Forms (и любой другой базирующейся на OD2K системе) как читать из файлов операционной системы, так и писать в них. Эти восклицательные знаки выражают радость, которую, несомненно, почувствуют все разработчики, работавшие в течение последних семи лет с различными инструментами корпорации Oracle для генерации экранов (UFI, SQL*Forms 2.3, SQL*Forms 3, и, наконец, Oracle Forms 4.0), и безнадежно мечтавшие все это время о такой возможности.

Наконец-то Вы получили возможность работы с файлами операционной системы - по меньшей мере с файлами операционной системы со стороны клиента. Пакет TEXT_IO - это инструментальное средство клиентской стороны, и с его помощью невозможно получить доступ к файлам со стороны сервера (если эти файлы недоступны через сетевую операционную систему).

Для записи в файл (в большинстве случаев) Вы должны выполнить следующие шаги:

1.    Объявить переменную управления файлом (file handle), которая будет служить указателем на файл для последующих обращений к процедуре TEXT_IO, чтобы манипулировать содержимым файла.

2.    Открыть файл, вызвав FOPEN. Файл можно открыть для замены или для добавления текста.

3.    Записать данные в файл, используя для этого процедуры PUT, PUTF или PUT_LINE.

4.    Закрыть файл, вызвав FCLOSE.

Для чтения данных из файла (в большинстве случаев) следуйте следующим указаниям:

1.    Объявить переменную управления файлом (file handle), которая будет служить указателем на файл для последующих обращений к процедуре TEXT_IO, чтобы манипулировать содержимым файла.

2.    Объявить строковый буфер типа VARCHAR2 для приема строки данных из файла.

3.    Открыть файл в режиме чтения ("read"), используя FOPEN.

4.    Использовать процедуру GET_LINE для чтения данных из файла в буфер. Чтобы прочитать все строки из файла, нужно выполнить GET_LINE в цикле.

5.    Закрыть файл, вызвав FCLOSE.

Пакет TEXT_IO содержит все необходимые модули и специальный тип данных для объявления переменной управления файлом (FILE_TYPE). Обращаясь к любому модулю пакета, начинайте его имя с "TEXT_IO."

Функция поиска строки

Здесь приведен пример, в котором используется TEXT_IO. Строковая функция INSTR (возвращающая позицию первого символа тестового фрагмента в строке - прим.переводчика) настолько полезна, что я изобразил операцию того же сорта, которая обеспечит удобство работы с файлами операционной системы. Функция line_with_text, текст которой приведен в Листинге 1, возвращает номер строки в файле, содержащей определенный текст. Простейшая версия этой функции будет иметь спецификацию такого типа:

FUNCTION line_with_text

   (file_in IN VARCHAR2, text_in IN VARCHAR2)

 

RETURN INTEGER

Другими словами, передав имя файла и фрагмент текста, Вы находите первую строку в файле, содержащую этот фрагмент. Вы можете вызывать эту функцию, как показано в следующем примере:

IF line_with_text('names.vp','Хануби') > 0

 

THEN

 

   MESSAGE ('Джозефина Хануби - вице-президент');

 

END IF;

Проблема с этой версией line_with_text заключается в совершенно недостаточной ее гибкости. Что, если я захочу найти второе вхождение текста в файле? Что, если я захочу начать поиск с 10-й строки? Что, если я захочу выполнить нечувствительный к строчным или прописным буквам поиск? Никакие из этих вариаций не поддерживаются.

Я рекомендую Вам подумать о различных вариантах реализации утилиты, подобной line_with_text прежде, чем Вы построите ее. Нельзя строить в расчете только на требования сегодняшнего дня - нужно предвидеть, что Вам понадобится завтра, на следующей неделе и в более отдаленном будущем.

Широкие возможности этой функции диктуют следующие требования к спецификации:

FUNCTION line_with_text

 

   (file_in        IN VARCHAR2,

 

    text_in        IN VARCHAR2,

 

    occurence_in   IN INTEGER := 1,

 

    start_line     IN INTEGER := 1,

 

    end_line       IN INTEGER := 0,

 

    ignore_case_in IN VARCHAR2 := 'IGNORE_CASE')

 

RETURN INTEGER

 

Здорово! Здесь много больше пересылаемых параметров. Благодаря дополнительным аргументам наша функция станет более гибкой. Описание каждого параметра Вы найдете в Листинге 1.

Заметьте, что все новые параметры: occurence_in, start_line, end_line, ignore_case_in имеют параметры по умолчанию, так что Вы можете вызывать эту функцию точно тем же способом и с таким же результатом, что и первую, ограниченную версию:

IF line_with_text('names.vp','Хануби') > 0

 

THEN

 

   MESSAGE ('Джозефина Хануби - вице-президент');

 

END IF;

 

 

Теперь, однако, Вы можете делать много больше:

 

 

1. Подтвердить, что этому пользователю назначена роль

 

   SUPERVISOR:

 

 

line_with_text('config.usr','ROLE=SUPERVISOR')

 

 

2. Найти второе вхождение строки DELETE, начиная с пятой строки:

 

 

line_with_text('commands.dat','delete',2,5)

 

 

3. Проверить третью строку на содержание спецификации терминала:

 

 

line_with_text('setup.cfg','termtype=',1,3,3)

 

У меня нет места для демонстрации каждого модуля пакета TEXT_IO, но функция line_with_text в достаточной степени продемонстрирует его ценность. Я уверен, что еще больше об этих ценных инструментальных средствах Вы прочитаете в будущих выпусках Oracle Developer.

Листинг 1. Функция line_with_text

 

 

FUNCTION line_with_text

 

   (file_in        IN VARCHAR2,

 

    text_in        IN VARCHAR2,

 

    occurence_in   IN INTEGER := 1,

 

    start_line     IN INTEGER := 1,

 

    end_line       IN INTEGER := 0,

 

    ignore_case_in IN VARCHAR2 := 'IGNORE_CASE')

 

RETURN INTEGER

/*

|| Функция INSTR для файлов операционной системы.

 

|| Возвращает номер строки файла, в которой найден

 

|| заданный текстовый фрагмент.

 

*/

IS

   /*

   || Переменная управления файлом. Открыть,

 

   || если аргументы допустимы.

 

   */

   file_handle TEXT_IO.FILE_TYPE;

   /*

   || Использовать локальную переменную для

 

   || этой информации

 

   */

 

   ignore_case BOOLEAN := UPPER(ignore_case_in) = 'IGNORE_CASE';

 

    /* Переменная-буфер для строки текста из файла */

 

    line_of_text VARCHAR2(1000);

 

 

    text_loc INTEGER;

 

    found_count INTEGER := 0;

    /*

    || Логическая переменная для определения,

 

    || есть ли еще что-то для чтения

 

    */

 

    no_more_lines BOOLEAN := FALSE;

 

    /* Возвращаемое функцией значение */

 

    return_value INTEGER := 0;

BEGIN

   /*

   || Утвердить правильные аргументы.

 

   || Если их недостает, вернуть NULL.

   */

 

   IF file_in IS NULL   OR

 

      text_in IS NULL   OR

 

      occurence_in <=0  OR

 

      start_line_in < 1 OR

 

      end_line_in   < 0

 

   THEN

 

      return_value := NULL;

 

   ELSE

 

      /*

 

      || Все аргументы в порядке.

 

      || Открыть и прочитать файл.

 

      */

 

      file_handle := TEXT_IO.FOPEN(file_in,'R');

 

      LOOP

         /*

 

         || Прочитать следующую строку и выйти,

 

         || если обнаружен конец файла.

 

         */

 

         get_nextline (file_handle, line_of_text, no_more_lines);

 

         EXIT WHEN no_more_lines;

 

 

         /* Получена очередная строка из файла */

 

         return_value := return_value + 1;

 

 

         /*

 

         || Если эта строка находится в пределах

 

         || области поиска ...

 

         */

 

         IF (return_value BETWEEN

 

             start_line_in AND end_line_in) OR

 

            (return_value >= start_line_in and

 

             END_LINE_IN = 0)

 

         THEN

 

            /*

 

            || Используем INSTR для определения,

 

            || не входит ли фрагмент в строку

 

            */

 

            IF ignore_case

 

            THEN

 

               text_loc := INSTR(line_of_text, text_in);

 

            ELSE

 

               text_loc := INSTR(UPPER(line_of_text),

 

                      UPPER(text_in));

 

            END IF;

 

            /*

            || Если местоположение фрагмента больше 0,

 

            || проводим сравнение.

 

            */

 

            IF text_loc > 0

 

            THEN

 

               /*

 

               || Увеличение счетчика строк.

 

               || Выйти, если подстрока найдена.

 

               */

 

               found_count := found_count + 1;

 

               EXIT WHEN found_count = occurence_in;

 

            END IF;

 

         END IF;

 

      END LOOP;

 

      TEXT_IO.FCLOSE(file_handle);

 

   END IF;

 

   IF no_more_lines

 

   THEN

      /* Прочитан весь файл. Фрагмент не найден. */

 

      return_value := NULL;

 

   END IF;

 

   RETURN return_value;

 

END;

Все вопросы и комментарии прошу присылать по адресу sqaimes@mail.ru

 


В избранное