简体   繁体   English

如何关闭文件读取

[英]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. 如果由于文件结尾而未读取任何文本,则会引发NO_DATA_FOUND异常。

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: 如果您要赶上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);
...

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. 就Oracle而言,文件为空不是错误条件,因此您不会因此而获得异常。 But if the file is empty then my_arr.COUNT will still be zero after the loop, so you can test for that: 但是,如果文件为空,则循环后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
...

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. 如果计数在抛出时大于零,则文件不为空。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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