1

此代码在压缩小文件 (4M) 时工作​​正常,但在尝试压缩大文件 (1.3G) 时出现数字或值错误。知道我在这里缺少什么吗?管道函数 ListDir 工作正常,所以这不是问题。

DECLARE
   dir_name VARCHAR2(50) ;
   dir_path VARCHAR2(1024);
   ns VARCHAR2(1024)       ;
   f    utl_file.file_type ;
   compressed    blob ;
   data_b        bfile ;
   compress_rate integer := 9 ;
BEGIN
   BEGIN
      select directory_name,directory_path
      into dir_name,dir_path
      from all_directories where directory_name = 'PURGE_ARCH_DIR' ;          
  EXCEPTION
      WHEN no_data_found
      THEN
          RAISE ;       
   END ;

   FOR each_file IN (SELECT column_value FROM TABLE(ListDir(dir_path)) ) 
   LOOP
      IF ( each_file.column_value = '07-22-2015_ccr_records_arc_purged.csv' )
      THEN
           DBMS_OUTPUT.PUT_LINE(each_file.column_value);
           f := UTL_FILE.fopen (dir_name, each_file.column_value || '.gz', 'wb');
           data_b := BFILENAME (dir_name,each_file.column_value);
           DBMS_LOB.FILEOPEN (data_b, DBMS_LOB.LOB_READONLY);
           DBMS_LOB.createtemporary (compressed, false);
           compressed := UTL_COMPRESS.lz_compress (data_b,compress_rate);
           UTL_FILE.put_raw(f, compressed, true);
           UTL_FILE.fclose (f);
           DBMS_LOB.FILECLOSE (data_b);
           DBMS_LOB.freetemporary (compressed);               
      END IF ;          
   END LOOP;       
EXCEPTION
     WHEN  others THEN
         RAISE ;
END;
/

错误是:

07-22-2015_ccr_records_arc_purged.csv
ERROR at line 1:
ORA-20001: Error_Stack...
ORA-06502: PL/SQL: numeric or value error
ORA-06512: at line 36
4

1 回答 1

2

我解决了这个问题。问题是你不能一次压缩一个大文件,在 1.3G 的情况下。我不得不遍历 Blob 并将其分块写出。

这是工作代码:

DECLARE
   dir_name VARCHAR2(1024) ;
   dir_path VARCHAR2(50)   ;
   ns VARCHAR2(1024)       ;
   v_process_name varchar2(61) := 'test_compress';
   src_file   BFILE;
   v_content  BLOB;
   v_blob_len INTEGER;
   v_file     utl_file.file_type;
   v_buffer   RAW(32767);
   v_amount   BINARY_INTEGER := 32767;
   v_pos      INTEGER := 1;
   v_compress_rate INTEGER := 9 ;
BEGIN
   BEGIN
      select directory_name,directory_path
      into dir_name,dir_path
      from all_directories where directory_name = 'PURGE_ARCH_DIR' ;

      EXCEPTION
         WHEN no_data_found
         THEN
              RAISE ;   
   END ;

   FOR each_file IN (SELECT column_value FROM TABLE(ListDir(dir_path)) ) 
   LOOP
      -- test large file (1.3G)
      IF ( each_file.column_value = '07-22-2015_imr_aces.aces_records_arc_purged.csv' )
      THEN
           DBMS_OUTPUT.PUT_LINE(each_file.column_value);

           src_file := bfilename(dir_name, each_file.column_value);
           dbms_lob.fileopen(src_file, dbms_lob.file_readonly);
           v_content  := utl_compress.lz_compress(src_file, v_compress_rate);
           v_blob_len := dbms_lob.getlength(v_content);
           v_file     := utl_file.fopen(dir_name,
                            each_file.column_value || '.gz','wb');

           WHILE v_pos < v_blob_len 
           LOOP
                dbms_lob.READ(v_content, v_amount, v_pos, v_buffer);
                utl_file.put_raw(v_file, v_buffer, TRUE);
                v_pos := v_pos + v_amount;
           END LOOP;

           utl_file.fclose(v_file);

      END IF ;

   END LOOP;

   EXCEPTION
      WHEN  others THEN
         IF utl_file.is_open(v_file) 
         THEN
               utl_file.fclose(v_file);
         END IF;
         RAISE ;

END;
/
于 2015-07-23T21:01:32.213 回答