UTL_FILE 包的使用详解

UTL_FILE包可以用来读写操作系统上的文本文件,UTL_FILE提供了在客户端(FORM等等)和服务器端的文件访问功能。
创建测试目录:
    新建一个command window;
    创建目录:(以system用户登录数据库)

SQL> create or replace directory utl_dir as '/home/oracle';
Directory created.
$ cat abc.log
the begining of file
Hello World!
Thank you!
Bye!

SQL> grant read, write on directory cux_log_dir to public; 
    Grant succeeded
检查目录是否成功创建
select * FROM all_directories dir WHERE dir.DIRECTORY_NAME = 'CUX_LOG_DIR';
Ps:视图all_directories存放着我们能否访问的目录对象。如果要删除目录,也需用system用户登录数据库,执行如下命令:Drop directory cux_log_dir;
过程和函数
FOPEN
描述:打开一个文件,基本上在我们对文件进行读写动作之前都需要先执行这个function来打开文件先。
语法:
UTL_FILE.FOPEN (  location IN VARCHAR2,
filename IN VARCHAR2,
open_mode IN VARCHAR2,
max_linesize IN BINARY_INTEGER DEFAULT 1024)  RETURN FILE_TYPE;
参数:location   略。
            Filename  略。
            open_mode  指明文件打开的模式。有如下几种

  • r –只读(文本)
  • w – 只写(本文)
  • a – 追加(文本)
  • rb – 只读(字节)
  • wb – 只写(字节)
  • ab – 追加(字节)

(注:当使用模式:a或者ab的时候,如果文件不存在,则会以write模式创建此文件)

max_linesize   指定文件文本每一行存放的最大字符数。
返回值:FOPEN返回一个接下来我们的程序将要使用到的文件的指针
FCLOSE
功能:关闭一个打开的文件。
语法:UTL_FILE.FCLOSE (file IN OUT FILE_TYPE);
参数:1. file->调用FOPEN或者FOPEN_NVCHAR返回的活动中的文件指针。
注意事项:当FCLOSE执行的时候,如果还有缓冲数据没有及时写入到文件中,那么程序就会raise一个异常:WRITE_ERROR。可以在PUT_LINE的时候加上参数autoflush => TRUE;或者在每次PUT之后执行:FFLUSH。
FCLOSE_ALL
功能:此procedure将会关闭本次session所有打开的文件。它用来紧急情况的清理功能,例如当PL/SQL程序在EXCEPTION部分退出时。
语法:UTL_FILE.FCLOSE_ALL;
注意事项:FCLOSE_ALL不会修改所打开的文件的状态,也就是说执行了FCLOSE_ALL后,再用IS_OPEN去检测文件,结果还是打开状态,但是之后,这些文件任然是不能去read或者write的。而FCLOSE执行后,相关的文件则完全关闭了,测试:

declare
  l_loc  VARCHAR2(100) :='UTL_DIR';
  l_file utl_file.file_type;
  l_buffer  varchar2(1024);
begin
  l_file := utl_file.fopen(location    => l_loc,
                           filename    => 'abc.log',
                           open_mode   => 'R');
  utl_file.fclose(file     => l_file);
--  utl_file.fclose_all;
  if utl_file.is_open(file => l_file) THEN
     dbms_output.put_line('OPEN');
  ELSE
     dbms_output.put_line('CLOSE');
  END IF;
   utl_file.get_line(file => l_file, buffer=> l_buffer);
exception
  when others then
   dbms_output.put_line(SQLERRM);
end;
/
ClOSE
ORA-29282: invalid file ID

 

declare
  l_loc  VARCHAR2(100) :='UTL_DIR';
  l_file utl_file.file_type;
  l_buffer  varchar2(1024);
begin
  l_file := utl_file.fopen(location    => l_loc,
                           filename    => 'abc.log',
                           open_mode   => 'R');
--   utl_file.fclose(file     => l_file);
     utl_file.fclose_all;
  if utl_file.is_open(file => l_file) THEN
     dbms_output.put_line('OPEN');
  ELSE
     dbms_output.put_line('CLOSE');
  END IF;
   utl_file.get_line(file => l_file, buffer=> l_buffer);
exception
  when others then
   dbms_output.put_line(SQLERRM);
end;
/
OPEN
ORA-29282: invalid file ID

FCOPY
功能:此procedure复制一个文件的连续部分内容或者全部内容到一个新创建的文件。如果参数start_line和end_line省略的话,默认地会复制整个文件。此操作会将源文件以read模式打开,将目标文件以write模式打开。
语法:
UTL_FILE.FCOPY ( src_location    IN VARCHAR2,
src_filename  IN VARCHAR2,
dest_location  IN VARCHAR2,
dest_filename IN VARCHAR2,
start_line         IN BINARY_INTEGER DEFAULT 1,
end_line          IN BINARY_INTEGER DEFAULT NULL);
参数:src_location来源文件的目录名。取值来源是视图ALL_DIRECTORIES的DIRECTORY_NAME;
             src_filename  将要被复制的来源文件
             dest_location 被创建的目标文件存放的目录名。
    dest_filename 从来源文件创建的目标文件。
    start_line  要复制的内容起始行号,默认为1,表示从第一行开始复制。
    end_line 要复制的内容的终止行号,默认NULL,表示文件的末尾。
测试程序之前:

$ cat abc.log
the begining of file
Hello World!
Thank you!
Bye!
测试代码:

declare
  l_loc   all_directories.directory_name%type := 'UTL_DIR';
BEGIN
  utl_file.fcopy(src_location   => l_loc,
                src_filename    => 'abc.log',
                dest_location   => l_loc,
                dest_filename   => 'efg.log',
                start_line        => 1,
                end_line        => 2);
exception
  WHEN OTHERS THEN
    dbms_output.put_line(SQLERRM);
end;
/

测试程序之后:

[oracle@dbserver ~]$ cat efg.log
the begining of file
Hello World!
并且efg.log文件中的内容只有两行:
FFLUSH
描述:FFLUSH强制将缓冲的数据写入文件。因为通常待写入文件的数据都是都在缓冲存储位置。当有必要去read一个任然处于打开状态的文件时,FFLUSH就起作用了,例如在调试程序中,可以将调试的消息及时冲到文件中,已便于我们马上就能read这些内容。
语法:
UTL_FILE.FFLUSH (file IN FILE_TYPE);
FGETATTR
描述:FGETATTR读取磁盘上的文件并返回文件的属性。
语法:UTL_FILE.FGETATTR( location IN VARCHAR2,
filename IN VARCHAR2,
fexists OUT BOOLEAN,
file_length OUT NUMBER,
block_size OUT BINARY_INTEGER);
参数:location 此处略去X个字。
      filename此处略去X个字。
      fexists 返回的属性1:文件是否存在
      file_length 返回的属性2:文件字节长度,如果文件不存在,则返回NULL。
      block_size  文件系统块的字节大小。
测试:

DECLARE
      l_loc         all_directories.directory_name%TYPE := 'CUX_LOG_DIR'; 
      l_file        utl_file.file_type; 
      l_file_exsits BOOLEAN; 
      l_file_length NUMBER; 
      l_block_size  BINARY_INTEGER; 
      l_buffer      VARCHAR2(1024); 
    BEGIN
      utl_file.fgetattr(location    => l_loc, 
                        filename    => 'l001.log', 
                        fexists     => l_file_exsits, 
                        file_length => l_file_length, 
                        block_size  => l_block_size); 
        IF l_file_exsits THEN
      l_file := utl_file.fopen(location  => l_loc, 
                               filename  => 'l001.log', 
                               open_mode => 'R'); 
      dbms_output.put_line('file exsits'); 
      dbms_output.put_line('file length:' || l_file_length); 
      dbms_output.put_line('block sieze :' || l_block_size); 
    END IF; 
    utl_file.fclose_all; 
    END;
输出结果:
 file exsits
file length:39802
block sieze :4096
FGETPOS
描述:此函数返回一个文件中当前的偏移位置。
语法:
UTL_FILE.FGETPOS (file IN FILE_TYPE) RETURN PLS_INTEGER;
   注意事项:如果file没有打开,则会抛出异常。
测试:

 declare
  l_loc  varchar2(100)  := 'UTL_DIR';
  l_file utl_file.file_type;
  l_buffer  VARCHAR2(1000);
begin
  l_file := utl_file.fopen(location => l_loc,
                           filename => 'abc.log',
                           open_mode => 'R');
  dbms_output.put_line('before get_line: current position is ' || utl_file.fgetpos(file => l_file));
  utl_file.get_line(file => l_file, buffer => l_buffer);
  dbms_output.put_line('after get_line: current position is ' || utl_file.fgetpos(file => l_file));
end;
/
before get_line: current position is 0
after get_line: current position is 21
PL/SQL procedure successfully completed.

FREMOVE
描述:此procedure在你有充足的权限之下,删除一个磁盘上的文件。
语法:
UTL_FILE.FREMOVE ( location IN VARCHAR2,
      filename IN VARCHAR2);
FRENAME
描述:此procedure将一个存在的文件重命名,类似unix命令:mv
语法:
UTL_FILE.FRENAME ( src_location   IN VARCHAR2,
     src_filename  IN VARCHAR2,
     dest_location  IN VARCHAR2,
     dest_filename IN VARCHAR2,
     overwrite        IN BOOLEAN DEFAULT FALSE);
参数:介绍略。
GET_LINE
描述:此procedure从一个打开的文件中读取一行文本,直到遇到换行符。
语法:
UTL_FILE.GET_LINE ( file     IN FILE_TYPE,
     buffer OUT VARCHAR2,
     len      IN PLS_INTEGER DEFAULT NULL);
   参数:len 从文本中读取一次的长度,默认是null,oracle就取FOPEN时的max_linesieze。
IS_OPEN
描述:顾名思义。
语法:UTL_FILE.IS_OPEN (file IN FILE_TYPE)  RETURN BOOLEAN;

PUT
描述:PUT写入内容到文件中。(每写一次,不带换行符)
语法:UTL_FILE.PUT (file IN FILE_TYPE, buffer IN VARCHAR2);
PUT_LINE
描述:PUT_LINE写入内容到文件中。(每写一次,末尾都加一个换行符)
语法:
UTL_FILE.PUT_LINE ( file          IN FILE_TYPE,
                                  buffer      IN VARCHAR2,
                                  autoflush  IN BOOLEAN DEFAULT FALSE);

测试

declare
  l_loc    varchar2(100) := 'UTL_DIR';
  l_file   utl_file.file_type;
  l_buffer varchar2(1000);
begin
  l_file   := utl_file.fopen(location => l_loc,
                             filename => 'abc.log',
                             open_mode => 'r');
  utl_file.get_line(file => l_file,
                    buffer => l_buffer);
  dbms_output.put_line( l_buffer);
  utl_file.fclose(file   => l_file);
  l_file   := utl_file.fopen(location => l_loc,
                             filename => 'abc.log',
                             open_mode => 'A');
  l_buffer := 'Add one more line!!!';
  utl_file.put_line(file     => l_file,
                    buffer   => l_buffer);
  utl_file.fclose(file   => l_file);
end;   
/
the begining of file

PL/SQL procedure successfully completed.
$ cat abc.log
the begining of file
Hello World!
Thank you!
Bye!
Add one more line!!!
PUTF
描述:    写入格式化的内容到文件中。好比C语言的printf()
语法:
UTL_FILE.PUTF ( file IN FILE_TYPE,
     format IN VARCHAR2,
     [arg1 IN VARCHAR2 DEFAULT NULL,
      . . .
     arg5 IN VARCHAR2 DEFAULT NULL]);
参数:format 包含格式化字符[\n,%s]的内容。
   \n:代表一个换行符。
   %s:用arg1~5的值去代替。
完整例子程序:
DECLARE
    l_loc         all_directories.directory_name%TYPE := 'CUX_LOG_DIR'; 
    l_file        utl_file.file_type; 
    l_file_exsits BOOLEAN; 
    l_file_length NUMBER; 
    l_block_size  BINARY_INTEGER; 
    l_buffer      VARCHAR2(32767); 
    --data 
    CURSOR c_hander IS
      SELECT fu.user_name, fu.description 
        FROM fnd_user fu 
       WHERE 1 = 1 
         AND fu.user_name LIKE 'XXX%'
       ORDER BY fu.user_name; 
BEGIN
    utl_file.fgetattr(location    => l_loc, 
                      filename    => 'test.log', 
                      fexists     => l_file_exsits, 
                      file_length => l_file_length, 
                      block_size  => l_block_size); 
    --put 
    IF l_file_exsits THEN
      l_file   := utl_file.fopen(location  => l_loc, 
                                 filename  => 'test.log', 
                                 open_mode => 'w'); 
    l_buffer := 'begining of file....'; 
    utl_file.put_line(file   => l_file, 
                      buffer => l_buffer); 
    FOR l IN c_hander LOOP 
      l_buffer := l.user_name || chr(9) || nvl(l.description, 
                                               'no description'); 
      utl_file.put_line(file   => l_file, 
                        buffer => l_buffer); 
    END LOOP; 
    l_buffer := 'end of file....'; 
    utl_file.put_line(file   => l_file, 
                      buffer => l_buffer); 
    --flush 
    utl_file.fflush(file => l_file); 
    --get 
    l_file := utl_file.fopen(location  => l_loc, 
                             filename  => 'test.log', 
                             open_mode => 'r'); 
    utl_file.fgetattr(location    => l_loc, 
                      filename    => 'test.log', 
                      fexists     => l_file_exsits, 
                      file_length => l_file_length, 
                      block_size  => l_block_size); 
    LOOP 
      utl_file.get_line(file   => l_file, 
                        buffer => l_buffer, 
                        len    => 32767); 
      dbms_output.put_line(a => l_buffer); 
      EXIT WHEN utl_file.fgetpos(file => l_file) = l_file_length; 
    END LOOP; 
  END IF; 
  utl_file.fclose_all; 
END; 

参考至:http://blog.chinaunix.net/uid-7374279-id-3839512.html
http://www.cnblogs.com/advocate/archive/2011/02/18/1957540.html
http://docs.oracle.com/cd/B19306_01/appdev.102/b14258/u_file.htm?bcsi_scan_7B0C6D5865CF5974=0&bcsi_scan_filename=u_file.htm#i1003796

如有错误,欢迎指正

邮箱:[email protected]

你可能感兴趣的:(File)