使用UTL_FILE读取错误

时间:2015-05-20 09:23:17

标签: oracle10g utl-file

我有以下脚本来创建3个文件:

set serveroutput on
declare
  nombreArchivo             varchar2(30);
  f_out                     UTL_FILE.FILE_TYPE;
begin
  nombreArchivo :='fich_fseek.txt';
  dbms_output.put_line('Abrir el fichero '||nombrearchivo||' en modo escritura.');
  f_out:=UTL_FILE.FOPEN('TEMPORAL',nombreArchivo,'w');
  UTL_FILE.PUT_LINE(f_out,'Hola, me llamo Álvaro.');
  UTL_FILE.PUT_LINE(f_out,'Esto es una prueba para ver cómo funcionan las funciones FSEEK y FGETPOS.');  
  UTL_FILE.PUT_LINE(f_out,'Espero que te diviertas.');
  UTL_FILE.NEW_LINE(f_out,1);
  UTL_FILE.PUT_LINE(f_out,'Atentamente,');
  UTL_FILE.PUT_LINE(f_out,'el que esto escribe'); 
  UTL_FILE.FCLOSE(f_out);

  nombreArchivo :='caracter.txt';
  dbms_output.put_line('Abrir el fichero '||nombrearchivo||' en modo escritura.');
  f_out:=UTL_FILE.FOPEN('TEMPORAL',nombreArchivo,'w');
  UTL_FILE.PUT(f_out,'a');
  UTL_FILE.FCLOSE(f_out);

  nombreArchivo :='vacio.txt';
  dbms_output.put_line('Abrir el fichero '||nombrearchivo||' en modo escritura.');
  f_out:=UTL_FILE.FOPEN('TEMPORAL',nombreArchivo,'w');
  UTL_FILE.FCLOSE(f_out);
exception
  when others then -- así me aseguro que cualquier flujo abierto será cerrado
    dbms_output.put_line('Se ha producido un error: '||SQLERRM);
    UTL_FILE.FCLOSE_ALL;
end;
/

当我创建另一个脚本来读取文件而不使用异常子句时出现了问题:

set serveroutput on

declare
  nombreArchivo             varchar2(30):='fich_fseek.txt';
  --nombreArchivo             varchar2(30):='caracter.txt';
  --nombreArchivo             varchar2(30):='vacio.txt';
  f_out                     UTL_FILE.FILE_TYPE;
  texto                     varchar2(100);
  posición                  pls_integer := 0;

  existe                    boolean;
  tamaño_archivo            number;
  tamaño_bloque             number; 
begin
  UTL_FILE.FGETATTR('TEMPORAL', nombreArchivo, existe, tamaño_archivo, tamaño_bloque);
  if existe then
    if tamaño_archivo > 0 then
      dbms_output.put_line('Abrir el fichero '||nombrearchivo||' en modo lectura, que tiene un tamaño de '||tamaño_archivo||' bytes.');
      f_out:=UTL_FILE.FOPEN('TEMPORAL',nombreArchivo,'r');

      posición := UTL_FILE.FGETPOS(f_out);
      while posición < tamaño_archivo loop
        UTL_FILE.GET_LINE(f_out, texto);
        dbms_output.put_line('pre  Posición '||posición);
        dbms_output.put_line(texto);
        posición := UTL_FILE.FGETPOS(f_out);
        dbms_output.put_line('post Posición '||posición);
      end loop;

      UTL_FILE.FCLOSE(f_out);
    else
      dbms_output.put_line('El fichero '||nombrearchivo||' está vacío (0 bytes).');
    end if;
  else
    dbms_output.put_line('El archivo '||nombrearchivo||' no existe');
  end if;
end;
/

然后ORA-01403“找不到数据”,但只能使用'fich_fseek.txt'文件。

1 个答案:

答案 0 :(得分:0)

感谢Alex Poole的评论。实际上,如果在Windows中以错误的方式计算新行字符,那么在readed_bytes小于file_size之前,我将使用correction_size:循环直到readed_bytes小于correction_size,而不是读取。校正非常简单,在起始点corre_size等于file_size,但每次读取新行时,correct_size将减少一个单位(字节):

set serveroutput on

declare
  nombreArchivo             varchar2(30):='fich_fseek.txt';
  --nombreArchivo             varchar2(30):='caracter.txt';
  --nombreArchivo             varchar2(30):='vacio.txt';
  f_out                     UTL_FILE.FILE_TYPE;
  texto                     varchar2(100);
  posición                  pls_integer := 0;

  existe                    boolean;
  tamaño_archivo            number;
  tamaño_bloque             number;
  tamaño_corregido          number;
begin
  UTL_FILE.FGETATTR('TEMPORAL', nombreArchivo, existe, tamaño_archivo, tamaño_bloque);
  if existe then
    if tamaño_archivo > 0 then
      dbms_output.put_line('Abrir el fichero '||nombrearchivo||' en modo lectura, que tiene un tamaño de '||tamaño_archivo||' bytes.');
      f_out:=UTL_FILE.FOPEN('TEMPORAL',nombreArchivo,'r');

      posición := UTL_FILE.FGETPOS(f_out);
      tamaño_corregido := tamaño_archivo;
      while posición < tamaño_corregido loop -- hay que poner el -6  para evitar un error no_data_found
        UTL_FILE.GET_LINE(f_out, texto);
        --dbms_output.put_line('pre  Posición '||posición);
        dbms_output.put_line(texto);
        posición := UTL_FILE.FGETPOS(f_out);
        --dbms_output.put_line('post Posición '||posición);
        tamaño_corregido := tamaño_corregido-1;
      end loop;

      UTL_FILE.FCLOSE(f_out);
    else
      dbms_output.put_line('El fichero '||nombrearchivo||' está vacío (0 bytes).');
    end if;
  else
    dbms_output.put_line('El archivo '||nombrearchivo||' no existe');
  end if;
end;
/

使用逐字节读取的替代版本:

set serveroutput on

declare
  nombreArchivo             varchar2(30):='fich_fseek.txt';
  --nombreArchivo             varchar2(30):='caracter.txt';
  --nombreArchivo             varchar2(30):='vacio.txt';
  f_out                     UTL_FILE.FILE_TYPE;
  texto                     varchar2(100) := '';
  posición                  pls_integer := 0;

  existe                    boolean;
  tamaño_archivo            number;
  tamaño_bloque             number;

  flag_acento               boolean := false;
  tamaño_corregido          number;
begin
  UTL_FILE.FGETATTR('TEMPORAL', nombreArchivo, existe, tamaño_archivo, tamaño_bloque);
  if existe then
    if tamaño_archivo > 0 then
      dbms_output.put_line('Abrir el fichero '||nombrearchivo||' en modo lectura, que tiene un tamaño de '||tamaño_archivo||' bytes.');
      f_out:=UTL_FILE.FOPEN('TEMPORAL',nombreArchivo,'r');

      posición := UTL_FILE.FGETPOS(f_out);
      tamaño_corregido := tamaño_archivo;
      while posición < tamaño_corregido  loop 
        UTL_FILE.GET_RAW(f_out, texto, 1);
        if texto = 'C3' then
          --dbms_output.put_line('Encontrado');
          flag_acento := true; --TODO
          goto CONTINUE;
        end if;
        if flag_acento then
          dbms_output.put_line('Posición '||rpad(posición,3)||' '||texto||': '||utl_raw.cast_to_varchar2('C3'||texto));
          flag_acento := false;
        else
          dbms_output.put_line('Posición '||rpad(posición,3)||' '||texto||': '||CHR(TO_NUMBER(texto,'xx')));
        end if;

        if texto = '0A' then -- caracter de sálto de línea
          --exit;
          tamaño_corregido := tamaño_corregido-1;
        end if;

        <<CONTINUE>> posición := UTL_FILE.FGETPOS(f_out);
      end loop;
      --dbms_output.put_line('ASDF '||CHR(TO_NUMBER('C3','xx'))||CHR(TO_NUMBER('81','xx')));
      /*unión := utl_raw.cast_to_varchar2('C381');
      dbms_output.put_line('ASDF '||unión );*/
      UTL_FILE.FCLOSE(f_out);
    else
      dbms_output.put_line('El fichero '||nombrearchivo||' está vacío (0 bytes).');
    end if;
  else
    dbms_output.put_line('El archivo '||nombrearchivo||' no existe');
  end if;
end;
/
相关问题