You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Oracle/PLSQL读取dat文件时能否识别换行符CHR(10)或CHR(13)?

在Oracle中校验dat文件行尾换行符的实现方案

需求与问题

需要校验dat文件的每行格式:

  • 每行必须以CHR(10)(换行符LF)结尾,不能是CHR(13)(回车符CR)或其他字符
  • 每行的第160位必须是CHR(10),不符合则抛出错误

但使用UTL_FILE.GETLINE读取文件时,该函数会自动截断行尾的换行符(CR/LF/CRLF组合都会被剔除),导致无法直接获取并校验这些字符,因此需要确认Oracle中是否能实现该校验逻辑。

实现方案

可以实现。UTL_FILE.GETLINE的特性就是自动移除行尾换行符,所以要获取原始文件字节(包括换行符),需要改用二进制读取模式,通过UTL_FILE.GET_RAW逐块读取原始字节数据,再对字节进行校验。

示例代码

SET SERVEROUTPUT ON;
DECLARE
    v_file      UTL_FILE.FILE_TYPE;
    v_raw_data  RAW(4000);
    v_byte      NUMBER;
    v_line_pos  NUMBER := 0;
    v_line_len  CONSTANT NUMBER := 160; -- 每行固定160字节
BEGIN
    -- 以二进制只读模式打开文件,避免字符集转换干扰原始字节
    v_file := UTL_FILE.FOPEN('DIR_IN_IMP_ACT_VENTE', 'temp.dat', 'RB');
    
    LOOP
        BEGIN
            -- 每次读取160字节(对应一行的要求长度)
            UTL_FILE.GET_RAW(v_file, v_raw_data, v_line_len);
            v_line_pos := v_line_pos + 1;
            
            -- 检查第160位字节是否为CHR(10)(ASCII值为10)
            v_byte := UTL_RAW.SUBSTR(v_raw_data, v_line_len, 1);
            IF v_byte != 10 THEN
                RAISE_APPLICATION_ERROR(-20001, 
                    '第' || v_line_pos || '行不符合要求:第160位不是CHR(10)');
            END IF;
            
            -- 检查整行是否包含CHR(13)(ASCII值为13)
            IF UTL_RAW.INSTR(v_raw_data, UTL_RAW.CAST_FROM_NUMBER(13)) > 0 THEN
                RAISE_APPLICATION_ERROR(-20002, 
                    '第' || v_line_pos || '行不符合要求:包含CHR(13)');
            END IF;
            
            DBMS_OUTPUT.PUT_LINE('第' || v_line_pos || '行校验通过');
            
        EXCEPTION
            WHEN NO_DATA_FOUND THEN
                -- 校验最后一行长度是否符合要求
                IF v_line_pos = 0 OR UTL_RAW.LENGTH(v_raw_data) != v_line_len THEN
                    RAISE_APPLICATION_ERROR(-20003, '最后一行长度不符合要求(需160字节)');
                END IF;
                EXIT;
        END;
    END LOOP;
    
    UTL_FILE.FCLOSE(v_file);
EXCEPTION
    WHEN OTHERS THEN
        IF UTL_FILE.IS_OPEN(v_file) THEN
            UTL_FILE.FCLOSE(v_file);
        END IF;
        RAISE;
END;
/

代码关键点说明

  • 'RB'模式打开文件:二进制只读模式,确保读取的是文件原始字节,不会被Oracle字符集转换处理
  • UTL_FILE.GET_RAW:直接读取原始字节数据,完整保留所有字符(包括CR/LF)
  • UTL_RAW.SUBSTR/UTL_RAW.INSTR:专门用于操作RAW类型的字节数据,精准校验目标字节位置和内容
  • 自定义异常:不符合条件时抛出明确错误信息,便于定位问题

原测试代码的问题

你原代码中使用的UTL_FILE.GETLINE会自动截断行尾的CHR(10)、CHR(13)或CHR(13)||CHR(10)组合,导致V1变量中不会包含这些换行符,因此无法通过SUBSTR(V1, -1)获取到行尾的换行符,这是无法完成校验的核心原因。

内容的提问来源于stack exchange,提问作者Ayushi Ramsurn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 13:42:43