ABAP Operaciones de archivo: OPEN DATASET, READ, TRANSFER

Kategorie
ABAP-Statements
Veröffentlicht
Autor
Johannes

Las operaciones de archivo permiten leer y escribir archivos en el servidor de aplicaciones SAP. Los comandos OPEN DATASET, READ DATASET, TRANSFER y CLOSE DATASET forman la base para el procesamiento de archivos en ABAP.

Comandos basicos

ComandoDescripcion
OPEN DATASETAbrir archivo
READ DATASETLeer datos de archivo
TRANSFEREscribir datos en archivo
CLOSE DATASETCerrar archivo
DELETE DATASETEliminar archivo

Sintaxis

Abrir archivo

OPEN DATASET <nombrearchivo>
FOR { INPUT | OUTPUT | APPENDING | UPDATE }
IN { TEXT MODE | BINARY MODE | LEGACY TEXT MODE }
[ ENCODING { DEFAULT | UTF-8 | NON-UNICODE } ]
[ WITH { SMART | NATIVE | UNIX | WINDOWS } LINEFEED ]
[ MESSAGE <mensaje> ].

Leer/Escribir archivo

READ DATASET <nombrearchivo> INTO <datos> [ LENGTH <longitud> ].
TRANSFER <datos> TO <nombrearchivo> [ LENGTH <longitud> ].

Cerrar/Eliminar archivo

CLOSE DATASET <nombrearchivo>.
DELETE DATASET <nombrearchivo>.

Ejemplos

1. Escribir archivo de texto

DATA: lv_file TYPE string VALUE '/tmp/output.txt',
lv_message TYPE string.
" Abrir archivo para escritura
OPEN DATASET lv_file FOR OUTPUT IN TEXT MODE
ENCODING UTF-8
MESSAGE lv_message.
IF sy-subrc = 0.
" Escribir lineas
TRANSFER 'Linea 1: Hola Mundo' TO lv_file.
TRANSFER 'Linea 2: ABAP es genial' TO lv_file.
TRANSFER 'Linea 3: Fin del archivo' TO lv_file.
CLOSE DATASET lv_file.
WRITE: / 'Archivo escrito exitosamente'.
ELSE.
WRITE: / 'Error:', lv_message.
ENDIF.

2. Leer archivo de texto

DATA: lv_file TYPE string VALUE '/tmp/input.txt',
lv_line TYPE string.
OPEN DATASET lv_file FOR INPUT IN TEXT MODE
ENCODING UTF-8.
IF sy-subrc = 0.
" Leer linea por linea
DO.
READ DATASET lv_file INTO lv_line.
IF sy-subrc <> 0.
EXIT. " Fin del archivo
ENDIF.
WRITE: / lv_line.
ENDDO.
CLOSE DATASET lv_file.
ELSE.
WRITE: / 'No se pudo abrir el archivo'.
ENDIF.

3. Leer archivo en tabla

DATA: lv_file TYPE string VALUE '/tmp/data.txt',
lv_line TYPE string,
lt_lines TYPE TABLE OF string.
OPEN DATASET lv_file FOR INPUT IN TEXT MODE ENCODING UTF-8.
IF sy-subrc = 0.
DO.
READ DATASET lv_file INTO lv_line.
IF sy-subrc <> 0.
EXIT.
ENDIF.
APPEND lv_line TO lt_lines.
ENDDO.
CLOSE DATASET lv_file.
" Procesamiento
WRITE: / 'Lineas leidas:', lines( lt_lines ).
ENDIF.

4. Escribir tabla en archivo

DATA: lv_file TYPE string VALUE '/tmp/export.txt',
lt_lines TYPE TABLE OF string.
lt_lines = VALUE #(
( `Nombre;Edad;Ciudad` )
( `Juan;30;Madrid` )
( `Ana;25;Barcelona` )
( `Pedro;35;Valencia` )
).
OPEN DATASET lv_file FOR OUTPUT IN TEXT MODE ENCODING UTF-8.
IF sy-subrc = 0.
LOOP AT lt_lines INTO DATA(lv_line).
TRANSFER lv_line TO lv_file.
ENDLOOP.
CLOSE DATASET lv_file.
WRITE: / 'Exportadas:', lines( lt_lines ), 'lineas'.
ENDIF.

5. Procesar archivo CSV

TYPES: BEGIN OF ty_customer,
name TYPE string,
age TYPE i,
city TYPE string,
END OF ty_customer.
DATA: lv_file TYPE string VALUE '/tmp/customers.csv',
lv_line TYPE string,
lt_customers TYPE TABLE OF ty_customer,
lt_fields TYPE TABLE OF string.
OPEN DATASET lv_file FOR INPUT IN TEXT MODE ENCODING UTF-8.
IF sy-subrc = 0.
" Saltar linea de cabecera
READ DATASET lv_file INTO lv_line.
" Leer lineas de datos
DO.
READ DATASET lv_file INTO lv_line.
IF sy-subrc <> 0.
EXIT.
ENDIF.
" Dividir linea
SPLIT lv_line AT ';' INTO TABLE lt_fields.
IF lines( lt_fields ) >= 3.
APPEND VALUE ty_customer(
name = lt_fields[ 1 ]
age = CONV #( lt_fields[ 2 ] )
city = lt_fields[ 3 ]
) TO lt_customers.
ENDIF.
ENDDO.
CLOSE DATASET lv_file.
ENDIF.
" Mostrar resultados
LOOP AT lt_customers INTO DATA(ls_cust).
WRITE: / ls_cust-name, ls_cust-age, ls_cust-city.
ENDLOOP.

6. Crear exportacion CSV

DATA: lv_file TYPE string VALUE '/tmp/export.csv',
lv_line TYPE string.
DATA: lt_orders TYPE TABLE OF ty_order.
" Datos de prueba
lt_orders = VALUE #(
( id = 1 customer = 'Garcia' amount = '100.50' )
( id = 2 customer = 'Lopez' amount = '250.00' )
( id = 3 customer = 'Martinez' amount = '75.25' )
).
OPEN DATASET lv_file FOR OUTPUT IN TEXT MODE ENCODING UTF-8.
IF sy-subrc = 0.
" Escribir cabecera
TRANSFER 'ID;Cliente;Monto' TO lv_file.
" Lineas de datos
LOOP AT lt_orders INTO DATA(ls_order).
lv_line = |{ ls_order-id };{ ls_order-customer };{ ls_order-amount }|.
TRANSFER lv_line TO lv_file.
ENDLOOP.
CLOSE DATASET lv_file.
ENDIF.

7. Leer archivo binario

DATA: lv_file TYPE string VALUE '/tmp/image.png',
lv_data TYPE xstring,
lv_buffer TYPE x LENGTH 1024,
lv_length TYPE i.
OPEN DATASET lv_file FOR INPUT IN BINARY MODE.
IF sy-subrc = 0.
DO.
READ DATASET lv_file INTO lv_buffer LENGTH lv_length.
IF sy-subrc <> 0.
EXIT.
ENDIF.
" Concatenar datos
CONCATENATE lv_data lv_buffer(lv_length) INTO lv_data IN BYTE MODE.
ENDDO.
CLOSE DATASET lv_file.
WRITE: / 'Leidos:', xstrlen( lv_data ), 'bytes'.
ENDIF.

8. Escribir archivo binario

DATA: lv_file TYPE string VALUE '/tmp/output.bin',
lv_data TYPE xstring.
" Datos binarios (por ej. de BD o procesamiento)
lv_data = 'A1B2C3D4E5F6'.
OPEN DATASET lv_file FOR OUTPUT IN BINARY MODE.
IF sy-subrc = 0.
TRANSFER lv_data TO lv_file.
CLOSE DATASET lv_file.
ENDIF.

9. Agregar a archivo (APPENDING)

DATA: lv_file TYPE string VALUE '/tmp/log.txt',
lv_line TYPE string.
" Agregar fecha/hora al log
lv_line = |{ sy-datum DATE = ISO } { sy-uzeit TIME = ISO }: Nueva entrada|.
OPEN DATASET lv_file FOR APPENDING IN TEXT MODE ENCODING UTF-8.
IF sy-subrc = 0.
TRANSFER lv_line TO lv_file.
CLOSE DATASET lv_file.
ENDIF.

10. Verificar y eliminar archivo

DATA: lv_file TYPE string VALUE '/tmp/temp.txt'.
" Verificar si el archivo existe (abriendo)
OPEN DATASET lv_file FOR INPUT IN TEXT MODE ENCODING DEFAULT.
IF sy-subrc = 0.
CLOSE DATASET lv_file.
WRITE: / 'Archivo existe'.
" Eliminar archivo
DELETE DATASET lv_file.
IF sy-subrc = 0.
WRITE: / 'Archivo eliminado'.
ENDIF.
ELSE.
WRITE: / 'Archivo no existe'.
ENDIF.

11. Leer directorio

DATA: lv_dir TYPE string VALUE '/tmp/',
lt_files TYPE TABLE OF string,
lv_filename TYPE string.
" Abrir directorio
CALL FUNCTION 'EPS_GET_DIRECTORY_LISTING'
EXPORTING
dir_name = CONV eps2path( lv_dir )
TABLES
dir_list = lt_files
EXCEPTIONS
invalid_eps_subdir = 1
sapgparam_failed = 2
build_directory_failed = 3
no_authorization = 4
read_directory_failed = 5
too_many_read_errors = 6
empty_directory_list = 7
OTHERS = 8.
IF sy-subrc = 0.
LOOP AT lt_files INTO lv_filename.
WRITE: / lv_filename.
ENDLOOP.
ENDIF.

12. Archivo con mensaje de error

DATA: lv_file TYPE string VALUE '/nonexistent/path/file.txt',
lv_message TYPE string.
OPEN DATASET lv_file FOR INPUT IN TEXT MODE
ENCODING UTF-8
MESSAGE lv_message.
IF sy-subrc <> 0.
WRITE: / 'Error al abrir:'.
WRITE: / lv_message.
WRITE: / 'Codigo de retorno:', sy-subrc.
ENDIF.

13. Modos de salto de linea

" Salto de linea Unix (LF)
OPEN DATASET lv_file FOR OUTPUT IN TEXT MODE
ENCODING UTF-8
WITH UNIX LINEFEED.
" Salto de linea Windows (CRLF)
OPEN DATASET lv_file FOR OUTPUT IN TEXT MODE
ENCODING UTF-8
WITH WINDOWS LINEFEED.
" Automatico (dependiente del servidor)
OPEN DATASET lv_file FOR OUTPUT IN TEXT MODE
ENCODING UTF-8
WITH NATIVE LINEFEED.
" Smart: Escribe como Native, Lectura detecta automaticamente
OPEN DATASET lv_file FOR INPUT IN TEXT MODE
ENCODING UTF-8
WITH SMART LINEFEED.

14. Posicionamiento en archivo

DATA: lv_file TYPE string VALUE '/tmp/data.bin',
lv_data TYPE x LENGTH 100,
lv_pos TYPE i.
OPEN DATASET lv_file FOR UPDATE IN BINARY MODE.
IF sy-subrc = 0.
" Obtener posicion
GET DATASET lv_file POSITION lv_pos.
WRITE: / 'Posicion actual:', lv_pos.
" Saltar a posicion
SET DATASET lv_file POSITION 100.
" Leer desde posicion 100
READ DATASET lv_file INTO lv_data.
CLOSE DATASET lv_file.
ENDIF.

15. Procesar archivos grandes eficientemente

CONSTANTS: c_buffer_size TYPE i VALUE 8192.
DATA: lv_file TYPE string VALUE '/tmp/large_file.txt',
lv_buffer TYPE string,
lv_count TYPE i.
OPEN DATASET lv_file FOR INPUT IN TEXT MODE ENCODING UTF-8.
IF sy-subrc = 0.
DO.
READ DATASET lv_file INTO lv_buffer.
IF sy-subrc <> 0.
EXIT.
ENDIF.
lv_count = lv_count + 1.
" Procesamiento sin guardar todas las lineas
" process_line( lv_buffer ).
" Mostrar progreso (cada 10000 lineas)
IF lv_count MOD 10000 = 0.
WRITE: / 'Procesadas:', lv_count, 'lineas'.
ENDIF.
ENDDO.
CLOSE DATASET lv_file.
WRITE: / 'Total:', lv_count, 'lineas'.
ENDIF.

16. Crear archivo temporal

DATA: lv_temp_file TYPE string,
lv_guid TYPE sysuuid_c32.
" Generar nombre de archivo unico
lv_guid = cl_system_uuid=>create_uuid_c32_static( ).
lv_temp_file = |/tmp/temp_{ lv_guid }.txt|.
" Usar archivo temporal
OPEN DATASET lv_temp_file FOR OUTPUT IN TEXT MODE ENCODING UTF-8.
TRANSFER 'Datos temporales' TO lv_temp_file.
CLOSE DATASET lv_temp_file.
" ... Procesamiento ...
" Limpiar
DELETE DATASET lv_temp_file.

Opciones de Encoding

EncodingDescripcion
DEFAULTEstandar del sistema
UTF-8Unicode (recomendado)
NON-UNICODELegacy, no-Unicode

Valores de sy-subrc

ValorSignificado
0Exitoso
4Fin de archivo (READ)
8Error (archivo no encontrado, sin permiso)

Alternativa ABAP Cloud

" En ABAP Cloud: Interfaz FILE no disponible
" En su lugar: CL_ABAP_FILE_UTILITIES o XCO
" Ejemplo con XCO (Cloud)
DATA(lo_file) = xco_cp=>file( '/tmp/test.txt' ).
" Verificar si existe
IF lo_file->exists( ).
" Leer
DATA(lv_content) = lo_file->read( )->as_string( ).
ENDIF.

Notas importantes / Mejores practicas

  • CLOSE DATASET siempre llamar - incluso en caso de error (TRY-FINALLY).
  • UTF-8 como encoding para archivos modernos.
  • Agregar MESSAGE para mensajes de error descriptivos.
  • sy-subrc = 4 en READ significa fin de archivo (EOF).
  • APPENDING para agregar a archivos existentes.
  • Procesar archivos grandes linea por linea en lugar de cargar completos.
  • Verificar autorizaciones (S_DATASET) para acceso a archivos.
  • Especificar rutas siempre de forma absoluta (no relativa).
  • En ABAP Cloud las operaciones de archivo estan restringidas - usar XCO.
  • Archivos binarios para contenido no textual (imagenes, PDFs).