Chapter 24. UTL_FILE Built-in Package

The UTL_FILE package, available in PL/SQL Version 2.3 and later, allows PL/SQL programs to read and write operating-system files. For example, you can use PL/SQL to create text-based reports that you can send as an email or view over the Web. This chapter tests your ability to establish file and directory privileges and use UTL_FILE to read and write operating-system files.

Beginner

24-1.

Before using UTL_FILE in your PL/SQL programs, what changes do you have to make to your instance parameter initialization file (your INIT.ORA file)? Can you read and/or write files in any directory on your database server?

24-2.

Suppose you want to enable read/write access on these three directories:

/tmp
/app/datafiles
/app/datafiles/q1

Which of the following sets of entries in the initialization file will successfully enable those directories?

  1. utl_file_dir = /tmp;/app/datafiles;/app/datafiles/q1

  2. utl_file_dir = /tmp
    utl_file_dir = /app/datafiles/*
  3. utl_file_dir = /tmp
    utl_file_dir = /app/datafiles
    utl_file_dir = /app/datafiles/q1
  4. utl_file_dir = '/tmp'
    utl_file_dir = '/app/datafiles'
    utl_file_dir = '/app/datafiles/q1'
  5. utl_file_dir = /tmp/
    utl_file_dir = /app/datafiles/
    utl_file_dir = /app/datafiles/q1/

24-3.

How can you specify that you want to read/write in any directory on the server? Under what circumstances would you use this setting?

24-4.

How can you specify that you want to read/write in the current directory for your session, regardless of that particularly location?

24-5.

Can you read and write files on your client-side computer with UTL_FILE?

24-6.

What is the maximum-sized line you can read/write using UTL_FILE?

24-7.

Which of the following exceptions are defined in UTL_FILE or raised by UTL_FILE, and which are not?

  1. UTL_FILE.INVALID_PATH

  2. NO_DATA_FOUND

  3. TOO_MANY_ROWS

  4. UTL_FILE.FILE_ALREADY_OPEN

  5. UTL_FILE.INVALID_OPERATION

24-8.

To open a file, you call UTL_FILE.FOPEN. Which of the following uses of this program are valid, and which are invalid?

  1. BEGIN
       UTL_FILE.FOPEN (
          'c:	emplotsa_data.txt', 'READ'),
  2. DECLARE
       myfile INTEGER;
    BEGIN
       myfile := UTL_FILE.FOPEN (
          'c:	emplotsa_data.txt', 'READWRITE'),
  3. DECLARE
       myfile UTL_FILE.FILE_TYPE;
    BEGIN
       myfile := UTL_FILE.FOPEN (
          'c:	emp', 'lotsa_data.txt', 'R'),
  4. DECLARE
       fname VARCHAR2(100) := 'lotsa_data.txt';
       myfile UTL_FILE.FILE_TYPE := UTL_FILE.FOPEN (
          'c:	emp', fname, 'R'),
    BEGIN

24-9.

Write a procedure that opens a file to read it (specified by location and name) and returns (through IN/OUT parameters) the handle to the file and a status flag indicating whether the file was opened successfully.

24-10.

How can you close all files that are open in your session? Why might you want to do this?

24-11.

What are the differences between UTL_FILE.PUT, UTL_FILE.PUTF, UTL_FILE.PUT_LINE, and UTL_FILE.NEW_LINE?

24-12.

What program do you call to read the next line in a file?

Intermediate

24-13.

Which of the following actions are not possible with UTL_FILE?

  1. Read sequentially the contents of a server-side file.

  2. Append text to the end of an existing file.

  3. Read from a “random” location in a file.

  4. Delete a file.

  5. Create a new file and write text to it.

  6. Copy a file.

  7. Move a file to a different location.

  8. Change the access privileges on a file.

  9. Obtain the number of bytes in a file without reading the entire file.

24-14.

What is displayed in your SQL*Plus session when the following program is run (assume that UTL_FILE has the necessary privileges to read the file)?

DECLARE
   fid UTL_FILE.FILE_TYPE :=
      UTL_FILE.FOPEN ('/tmp', 'twolines.txt', 'R'),
   line VARCHAR2(2000);
BEGIN
   LOOP
      UTL_FILE.GET_LINE (fid, line);
      DBMS_OUTPUT.PUT_LINE (line);
   END LOOP;
END;

Here are the contents of the data file that is read:

I am not a very large file, really I consist
of nothing more than two lines.

24-15.

Write a procedure to display the contents of the specified file to standard output (usually your screen). Make sure you don’t leave a file open if an error occurs.

24-16.

What is wrong with the following code?

CREATE TYPE string_list_t IS TABLE OF VARCHAR2(255);
/

  1 CREATE OR REPLACE PROGRAM nest2file (file IN VARCHAR2,
  2    list IN string_list_t%TYPE)
  3 /* Move contents of nested table to file. */
  4 IS
  5    fid UTL_FILE.FILE_TYPE := UTL_FILE.FOPEN (file, 'R'),
  6    line VARCHAR2(100);
  7    linenum INTEGER;
  8 BEGIN
  9    FOR linenum IN list.LAST .. list.FIRST
 10    LOOP
 11       line := list(linenum);
 12       UTL_FILE.WRITE_LINE (line);
 13       EXIT WHEN linenum = list.FIRST;
 14    END LOOP;
 15 END;
 16 /

24-17.

Rewrite the awfully written program in 24-16 to get rid of its problems.

24-18.

Write a procedure to transfer the last_name, hire_date, and salary for each row of the employee table to the specified file, using commas to delimit each column’s data.

24-19.

When you write a file using UTL_FILE, is that file owned by your user process or by the Oracle process?

24-20.

Write a procedure that uses a single call to a UTL_FILE “put” procedure to write the following text to a file:

"Freedom's just another word
for working on your ***"
-- Dave Lippman

where *** is a string that is provided through the parameter list of the procedure, whose header is:

PROCEDURE what_is_freedom (
   fid IN UTL_FILE.FILE_TYPE,
   it_is IN VARCHAR2);

24-21.

How can you determine whether a file is already open?

24-22.

What is the maximum number of files you can have open in a single Oracle session?

24-23.

How many different ways can you use UTL_FILE programs to insert into a file the string “I LUV ORACLE” followed by a newline character?

24-24.

Write a procedure that returns the next line of an already-opened file and also returns a Boolean flag indicating whether you have reached the end-of-file. Is there any advantage to using this procedure rather than the built-in UTL_FILE.GET_LINE?

24-25.

If you try to append to a file with a call to FOPEN as follows:

   fid := UTL_FILE.FOPEN (mydir, myfile, 'A'),

and the file does not exist, what happens?

24-26.

Write a substitute for (or encapsulation of) FOPEN that allows developers to not have to worry about whether they are appending to an existing file or a new file.

24-27.

What happens if you try to close a file that has already been closed?

24-28.

There are times when a developer might like to create a file to use as a flag indicating that a certain action is taking place—or not taking place. Write a program that creates a file with the specified location and name, but that does not require the user to declare a FILE_TYPE record and perform each of the necessary steps himself.

Expert

24-29.

What information is displayed on the screen when you run this code (assume that you have UTL_FILE privileges on the c: emp directory):

DECLARE
   fid UTL_FILE.FILE_TYPE :=
      UTL_FILE.FOPEN ('c:	emp', 'new.txt', 'W'),
   line VARCHAR2(2000);
BEGIN
   fid.id := NULL;
   IF UTL_FILE.IS_OPEN (fid)
   THEN
      DBMS_OUTPUT.PUT_LINE ('Seems open to me...'),
   ELSE
      DBMS_OUTPUT.PUT_LINE ('Who closed my file?'),
   END IF;
END;
/

24-30.

Create a procedure that allows you to write lines of arbitrary length (even exceeding the maximum allowed in UTL_FILE) to a file.

24-31.

Write an INSTR-like function for UTL_FILE. It should implement the following header:

CREATE OR REPLACE FUNCTION infile
   (loc_in IN VARCHAR2,
    file_in IN VARCHAR2,
    text_in IN VARCHAR2,
    occurrence_in IN INTEGER := 1,
    start_line_in IN INTEGER := 1,
    end_line_in IN INTEGER := 0,
    ignore_case_in IN BOOLEAN := TRUE)
RETURN INTEGER;

In other words, find the nth occurrence of the string text_in between lines start_line_in and end_line_in, either matching or ignoring case. Assume that the following rules are obeyed to simplify your solution:

  • The file always contains text.

  • The number of occurrences is positive.

  • The starting line is not negative.

  • The ending line is greater than the starting line.

24-32.

Let’s take a look at error handling with the UTL_FILE package. I created this procedure (as well as fileplay2.sp) to play around with files:


/* Filename on web page: fileplay.sp */
CREATE OR REPLACE PROCEDURE play_with_files
   (loc_in IN VARCHAR2,
    file_in IN VARCHAR2,
    mode_in IN VARCHAR2,
    mixed_up IN BOOLEAN := FALSE)
IS
   fID UTL_FILE.FILE_TYPE;
   line VARCHAR2(32767) := 'fun stuff!';
BEGIN
   IF mixed_up AND mode_in = 'R'
   THEN
      fID := UTL_FILE.FOPEN (loc_in, file_in, 'W'),
   ELSIF mixed_up
   THEN
      fID := NULL;
   ELSE
      fID := UTL_FILE.FOPEN (loc_in, file_in, mode_in);
   END IF;

   IF mode_in = 'R'
   THEN
      UTL_FILE.GET_LINE (fid, line);
      DBMS_OUTPUT.PUT_LINE (
         'Read from ' || file_in || ' in ' || loc_in);
   ELSE
      UTL_FILE.PUT_LINE (fid, line);
      DBMS_OUTPUT.PUT_LINE (
         'Wrote to ' || file_in || ' in ' || loc_in);
   END IF;

   UTL_FILE.FCLOSE (fid);
END;
/

As you can see, it lets me either write to a file or read from a file. If I specify that I want things “mixed up,” the program tries to write to a read-only file or sets the file handle to NULL. Then I set up the following script to exercise my play_with_files procedure:


/* Filename on web page: fileplay.tst */
SET FEEDBACK OFF
EXEC fcreate ('c:	emp', 'newfile.txt'),
EXEC play_with_files ('c:	emp', 'newfile.txt', 'R'),
EXEC play_with_files ('c:
osuchdir', 'new.txt', 'R'),
EXEC play_with_files ('c:
osuchdir', 'new.txt', 'X'),
EXEC play_with_files ('c:	emp', 'nosuchfile.txt', 'R'),
EXEC play_with_files ('c:	emp', 'nosuchfile.txt', 'A'),
EXEC play_with_files (
   'c:	emp', 'nosuchfile.txt', 'R', mixed_up => TRUE);
EXEC play_with_files (
   'c:	emp', 'nosuchfile.txt', 'W', mixed_up => TRUE);
EXEC UTL_FILE.FCLOSE_ALL;
HOST DEL c:	emp
osuchfile.txt
HOST DEL c:	emp
ew.txt

The fcreate procedure creates a new file (see the fcreate.sp file on the book’s web page). There is no directory named nosuchdir and no file named nosuchfile.txt. Here is the somewhat abbreviated output from running this script:

SQL> @fileplay.tst
ORA-01403: no data found
ORA-06510: PL/SQL: unhandled user-defined exception
ORA-06510: PL/SQL: unhandled user-defined exception
ORA-06510: PL/SQL: unhandled user-defined exception
Wrote to nosuchfile.txt in c:	emp
ORA-06510: PL/SQL: unhandled user-defined exception
ORA-06510: PL/SQL: unhandled user-defined exception

Not too informative, is it? If I try to read past the end of a file (in this case, read the first line of an empty file), UTL_FILE raises NO_DATA_FOUND. I also find that in Oracle 8.1, if I append to a nonexistent file, I no longer get an error; the script wrote to nosuchfile.txt successfully. But once I get past those conclusions, I can determine little else from the output.

Why do I keep seeing the same error message, even though it seems as if I am encountering different errors?

24-33.

How can you obtain more meaningful error information from UTL_FILE-dependent programs? Specifically, how could I change the play_with_files procedure to see precisely which error was raised by my “foolin’ around”?

24-34.

Implement the concept of a path for UTL_FILE by creating the package body for this specification:


/* Filename on web page: filepath.pkg */
CREATE OR REPLACE PACKAGE fileIO
IS
   c_delim CHAR(1) := ';';

   PROCEDURE setpath (str IN VARCHAR2);
   FUNCTION path RETURN VARCHAR2;

   FUNCTION open (file IN VARCHAR2) RETURN UTL_FILE.FILE_TYPE;
END;
/

where the c_delim constant “publicizes” the delimiter to be used in parsing the path string, setpath sets the path to a list of delimited directories, path returns the current path, and open opens.

24-35.

You can use UTL_FILE is to write error information to a file; with files, you don’t have to worry about ROLLBACKs erasing your log entries. Write a package that allows a developer to:

  • Specify the location and name of the error log file, which are maintained as global values in the package and for the session.

  • Write the error code, error message, and program name to the file (with the current date, time, and user supplied by the logging program).

  • The components of the line written to the file are separated by a vertical bar, defined as a constant in the package specification.

  • See each line after it is written to the log, even though the file is not yet closed.

  • Close the log at user request.

Here is the specification for the package; you write the body:


/* Filename on web page: flog.pkg */
CREATE OR REPLACE PACKAGE flog /* File LOG */
IS

   delim CONSTANT CHAR(1) := '|';
   PROCEDURE setfile (loc IN VARCHAR2, file IN VARCHAR2);
   PROCEDURE put_line (
      prog IN VARCHAR2, code IN INTEGER, msg IN VARCHAR2);
   PROCEDURE close;
END flog;
/

Don’t forget to open for append and catch the error if the file does not yet exist. And when and how often should you open and close the file?

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.219.95.244