如何关闭文件读取

时间:2019-02-28 21:56:41

标签: oracle stored-procedures plsql exception-handling

尽管可以正确读取文件,但会引发异常,但我知道只有在发现异常之前,文件才会关闭。我该如何更改?

CREATE OR REPLACE PROCEDURE APPS.toks_hcm_estructures (
    p_errbuf         OUT VARCHAR2,
    p_linea          OUT CLOB,
    p_file_name   IN     VARCHAR2,
    p_retcode        OUT NUMBER)
AS
    l_file      UTL_FILE.FILE_TYPE;
    v_line      VARCHAR2 (32000);
    my_arr      v_arr1 := v_arr1 ();
    v_path      VARCHAR2 (100) := 'TOKS_HR_DIR_HDL';
    ls_linea2   VARCHAR2 (32000);
BEGIN
    l_file :=
        UTL_FILE.FOPEN (v_path,
                        p_file_name,
                        'R',
                        32767);

    BEGIN
        LOOP
            UTL_FILE.GET_LINE (l_file, v_line);
            my_arr.EXTEND;
            my_arr (my_arr.COUNT) := v_line;
        END LOOP;
    EXCEPTION
        WHEN NO_DATA_FOUND
        THEN
            p_errbuf := 'Error al generar archivo. No se Encontraron Datos.';
            p_retcode := 1;
            UTL_FILE.fclose (l_file);
        WHEN UTL_FILE.INVALID_FILENAME
        THEN
            p_errbuf := 'Error. El archivo no existe.';
            p_retcode := 1;
            UTL_FILE.fclose (l_file);
        WHEN UTL_FILE.read_error
        THEN
            p_errbuf := 'Error al generar archivo. Error de Lectura.';
            p_retcode := 1;
            UTL_FILE.fclose (l_file);
        WHEN OTHERS
        THEN
            p_errbuf := 'Error paquete: ' || SQLERRM;
            p_retcode := 1;
            UTL_FILE.fclose (l_file);
    END;

    FOR i IN 1 .. my_arr.COUNT
    LOOP
        p_linea := p_linea || CHR (10) || my_arr (i);
    END LOOP;
EXCEPTION
    WHEN OTHERS
    THEN
        p_errbuf := 'Error paquete: ' || SQLERRM;
        p_retcode := 1;
        UTL_FILE.fclose (l_file);
END toks_hcm_estructures;
/

我认为目前尚不清楚我要做什么,因为通过异常我可以验证两件事:

  1. 该文件存在

  2. 该文件不为空

1 个答案:

答案 0 :(得分:0)

引发了when you read past the end of the file异常:

  

如果由于文件结尾而未读取任何文本,则会引发NO_DATA_FOUND异常。

所以您根本就不想将其视为错误。您目前正在忽略其他任何错误。如果您要赶上OTHERS,则应该在关闭后重新抛出:

...
BEGIN
  l_file := UTL_FILE.FOPEN(v_path, p_file_name, 'R',32767);
  BEGIN
    LOOP
      UTL_FILE.GET_LINE (v_file, v_line);
      my_arr.EXTEND;
      my_arr (my_arr.COUNT) := v_line;
     END LOOP;
  EXCEPTION
    WHEN no_data_found THEN
      --p_errbuf := 'Error de lectura. No se Encontraron Datos.';
      --p_retcode := 1;
      UTL_FILE.FCLOSE (v_file);
    WHEN OTHERS THEN                              
      UTL_FILE.FCLOSE (v_file);
      RAISE; -- re-throw exception so it is reported
  END;
  UTL_FILE.FCLOSE (v_file);
...

或(在您编辑之后),如果每个异常处理程序都设置了一条消息但没有提早返回-也许他们应该这样做? -您只需要在该子块结束之后进行一次单笔关闭。我补充说是因为您的原始代码会在出错时关闭文件,但不会在成功时关闭文件。

就Oracle而言,文件为空不是错误情况,因此您不会因此而获得异常。但是,如果文件为空,则my_arr.COUNT在循环后仍为零,因此您可以对此进行测试:

...
  END;

  IF my_arr.COUNT = 0 THEN
    p_errbuf := 'Error al generar archivo. No se Encontraron Datos.';
    p_retcode := 1;
  END IF;

  FOR i IN 1..my_arr.COUNT LOOP
...
循环之后的

(或者,实际上;在这种情况下,第二个循环什么也不做)。该文件目前已经关闭。

或者,如果愿意,保留原始代码,但在看到异常时检查计数:

...
BEGIN
  l_file := UTL_FILE.FOPEN(v_path, p_file_name, 'R',32767);
  BEGIN
    LOOP
      UTL_FILE.GET_LINE(l_file, v_line);
      my_arr.EXTEND;
      my_arr(my_arr.COUNT) := v_line;
    END LOOP;
  EXCEPTION
    WHEN no_data_found THEN
      IF arr.COUNT = 0 THEN
        p_errbuf := 'Error al generar archivo. No se Encontraron Datos.';
        p_retcode := 1;
      END IF;
      UTL_FILE.FCLOSE (v_file);
    WHEN UTL_FILE.INVALID_FILENAME THEN
...

如果计数在抛出时大于零,则文件不为空。