简体   繁体   中英

How to close the reading of a file

The exceptions are thrown although the file is read correctly, I understand that only the file is closed until it finds an exception. How can I change this?

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;
/

I think it was not clear what I try to do is that through the exceptions I can validate two things:

  1. That the file exists

  2. That the file is not empty

The exception is thrown when you read past the end of the file :

If no text was read due to end of file, the NO_DATA_FOUND exception is raised.

so you don't really want to treat that as an error at all. You are currently ignoring any other error though. If you're going to catch OTHERS you should really re-throw after closing:

...
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);
...

or (after your edit) if every exception handler sets a message but doesn't return early - perhaps they should? - you only need the single close after the end of that sub-block. I added that because your original code closes the file on error, but not on success.

The file being empty is not an error condition as far as Oracle is concerned, so you won't get an exception just for that. But if the file is empty then my_arr.COUNT will still be zero after the loop, so you can test for that:

...
  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
...

after the loop (either, really; the second loop does nothing in that scenario anyway). The file is already closed by now.

Or if you prefer, keep your original code but check the count when you see the exception:

...
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
...

If the count is greater than zero when it's thrown then the file was not empty.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM