¿ Quieres imprimir esta página ? Volver a la página principal de Recursos iSeries AS400 ¿ Necesitas ayuda ? En pruebas
System i5 iSeries AS400 Recursos. Compartiendo generamos conocimiento
Novedades en Recursos iSeries AS400
Noticias tecnológicas

Documentos
Generar ficheros en la QDLS desde RPG IV

Normalmente los programadores que queremos generar un fichero a las carpetas compartidas (QDLS), lo que hacemos es generar un fichero (o miembro) en el AS/400 y copiarlo después utilizando el mandato CPYTOPCD para dejarlo en la carpeta compartida, y borrando el miembro o fichero creado en el AS. Con una sencilla utilización de algunas API's conseguiremos el mismo resultado, pero sin utilizar recursos de máquina para crear/copiar/borrar objetos. En resumen, conseguiremos crear documentos de PC desde un RPG.

Las API's que utilizaremos para esta finalidad son las siguientes:

QHFOPNSF - Abre un fichero en la IFS con sistema HFS.
QHFWRTSF - Graba a un fichero en la IFS con sistema HFS.
QHFCLOSF - Cierra un fichero en la IFS con sistema HFS.
documentadas en el manual: QB3AMK01 OS/400 Hyerarchial File System V4R2.

Para que la utilización de estas API's no signifiquen una carga extra en la programación y podamos seguir el hilo conductor de los programas que las utilicen, crearemos 3 prototipos o procedimientos para cada una de las acciones a realizar:

@ObreIFS - Abre un fichero IFS

Parámetros que le pasamos por valor:

obreIFS_Path de 1024a - Carpeta y nombre de fichero a abrir.

obreIFS_Info de 10a - Son los parámetros con los que abriremos el fichero.

Parámetro que retorna:

globalIFSHDL 16a - Es el identificador con el que la máquina reconoce el fichero abierto.

@GravaIFS - Grabamos al fichero IFS

Parámetros que le pasamos por valor:

gravaIFS_txt 255a - Es el texto que grabamos al fichero.

gravaIFS_HDL 16a - Identificador de fichero.

Parámetro que retorna:

Indicador de resultado de la operación

@TancaIFS - Cerramos el fichero IFS

Parámetros que le pasamos por valor:

tancaIFS_HDL 16a - Identificador de fichero.

Parámetro que retorna:

Indicador de resultado de la operación

De esta manera, la hoja D de definición de los prototipos, y de la variable que utilizaremos como identificador de archivo, quedará así:

d*                                                   
d GlobalIFSHDL1   s             16a                  
d GlobalIFSHDL2   s             16a                  
d*                                                   
d @ObreIFS        PR            16a                  
d  obreIFS_Path               1024a   Value          
d  obreIFS_Info                 10a   Value          
d*                                                   
d @GravaIFS       PR              n                  
d  gravaIFS_Txt                255a   Value          
d  gravaIFS_HDL                 16a   Value          
d*                                                   
d  @TancaIFS      PR              n                  
d  tancaIFS_HDL                 16a   Value          
d*
Para abrir un fichero, lo haremos de la siguiente manera:
c                   Eval      GlobalIFSHDL = @ObreIFS(           
c                              '/QDLS/PROVES/PROVES.TXT' :       
c                              '211 211   ')                     

Siendo el primer parámetro el nombre del fichero con la via IFS a donde se generará el fichero, y el segundo el resultado de aplicar las siguientes directrices:

Byte 1 Acción a tomar si el fichero existe:

0 No abre el fichero y vuelve un error.

1 Abre el fichero.

2 Reemplaza el fichero existente.

2 Acción a tomar si el fichero no existe:

0 Retorna un error

1 Crea el fichero

3 Tipo de grabación

0 Grabación asíncrona. Retorna el control al programa inmediatamente.

1 Grabación síncrona. Retorna el control al programa cuando ha efectuado la operación.

4 Reservado, ha de estar a blancos.

5 Modalidad de bloqueo.

1 No bloqueamos

2 Bloqueamos la escritura

3 Bloqueamos la lectura

4 Bloqueamos la lectura i la escritura.

6 Modalidad de acceso

0 Sólo lectura

1 Sólo escritura

2 Lectura/escritura

7 Tipo de operaciones de obertura para optimización

0 Normal

1 El fichero se cerrará con la API QHFCLOSF. ENDRQS y RCLRSC no cierran el fichero.

8-10 Reservados, han de estar a blancos

Así pues abrimos nuestro fichero PROVES.TXT en la carpeta PROVES de la QDLS diciendo que: si existe, que lo reemplace, si no existe, que lo cree, que retorne el control al programa cuando realice la grabación física, que bloquee la escritura a otros trabajos, que accederemos únicamente para escritura, y que cerraremos el fichero por programa con la API. La carpeta que indiquemos tendrá que estar montada con el sistema de archivos HFS, la QDLS lo está por omisión.

Para grabar en el fichero PROVES.TXT haremos lo siguiente:

c                   Eval      *In99 = @GravaIFS(             
c                              'Hola Mundo!' : GlobalIFSHDL)   

Siendo el primer parámetro el texto a grabar, que puede ser una combinación de texto y valores de campo, y el segundo el identificador de fichero retornado anteriormente. Si gestionamos más de un fichero al mismo tiempo, tendremos una variables de tipo identificador para cada fichero.

Para cerrar el fichero procederemos de la siguiente manera:

c                   Eval      *In99 = @TancaIFS(GlobalIFSHDL)

La codificación de los diferentes prototipos la pondremos al final del RPG o en un programa de servicio.

p*---------------------------------------------------            
p* Abrimos un fichero en la IFS                                 
p*---------------------------------------------------           
p @ObreIFS        B                                             
d @ObreIFS        PI            16a                             
d  obreIFS_Path               1024a   Value                     
d  obreIFS_Info                 10a   Value                     
d*                                                              
d  o_PathLn       s              9b 0                           
d  o_Info         ds                                            
d    o_NumInf                    9b 0                           
d    o_ParInf                  400a                             
d  o_InfoLn       s              9b 0                           
d  o_Accio        s              1a                             
d  o_Error        s           1024a                             
c*                                                              
c* Llamamos a la API que abre el fichero
c                   Eval      o_PathLn = %len(%trim(obreIFS_Path)) 
c*                                                                   
c                   Call      'QHFOPNSF'                            
c                   Parm                    o_Hdl                   
c                   Parm                    obreIFS_Path            
c                   Parm                    o_PathLn                
c                   Parm                    obreIFS_Info            
c                   Parm                    o_Info                  
c                   Parm                    o_InfoLn                
c                   Parm                    o_Accio                 
c                   Parm                    o_Error                 
c*                                                                  
c                   Return    o_Hdl                                 
c*                                                                  
p                 E                                                 



p*---------------------------------------------------
p* Insertamos líneas en el fichero
p*---------------------------------------------------      
p @GravaIFS       B                                        
d @GravaIFS       PI              n                        
d  gravaIFS_Txt                255a   Value                
d  gravaIFS_HDL                 16a   Value                
d*                                                         
d i_Buffer        s           1024a                        
d i_BufferLen     s              9b 0                      
d i_BufferWri     s              9b 0                      
d i_Error         s           1024a                        
d i_NL            c                   Const(X'0D')         
d i_Text          s            256a                        
c*                                                         
c* Grabamos al fichero
c                   Eval      i_BufferLen = %len(%trim(i_Buffer)) 
c                   Call      'QHFWRTSF'                          
c                   Parm                    gravaIFS_HDL          
c                   Parm                    i_Buffer              
c                   Parm                    i_BufferLen           
c                   Parm                    i_BufferWri           
c                   Parm                    i_Error               
c*                                                                
c                   Return    *Off                                
c*                                                                
p                 E                                               



p*---------------------------------------------------       
p* Cierra un fichero en la IFS                               
p*---------------------------------------------------       
p @TancaIFS       B                                         
d @TancaIFS       PI              n                         
d  tancaIFS_HDL                 16a   Value                 
d*                                                          
d  o_Error        s           1024a                         
c*                                                          
c* Llamamos a la API que cierra el fichero
c                   Call      'QHFCLOSF'  
c                   Parm                    tancaIFS_HDL    
c                   Parm                    o_Error         
c*                                                          
c                   Return    *Off                          
c*                                                          
p                 E
Estos prototipos no gestionan los errores.

Cierto, los prototipos tal y como están codificados, no controlan los errores posibles, y siempre retornan *Off. Se ha omitido este apartado para así poder ir aprendiendo de los errores. Si se quiere gestionar estos errores, controlaremos si las variables de error contienen algún valor, y crearemos en cada prototipo una subrutina *PSSR que los controle, o que sencillamente retorne el valor *On. En el caso de la apertura del fichero, como que el valor retornado no es un indicador sino el identificador de fichero, podemos retornar la palabra *ERROR para controlarlo. Pero esto lo dejo a vuestro libre albedrío.

El fichero generado no se entiende.

Esto se debe a que se genera en formato EBCDIC. Para que se guarde en formato ANSI, en el prototipo @GravaIFS añadiremos el siguiente código antes de la primera instrucción de cálculo:

d*                                                        
d c_CvtLenI       s              5p 0                     
d c_Taula         s             10a   Inz('Q284A05A5U')   
d c_Lib           s             10a   Inz('QUSRSYS')      
c*                                                        
c* Convertimos el texto de EBCDIC a ANSI
c                   Eval      i_Text = %trim(gravaIFS_Txt) + i_NL 
c                   Eval      c_CvtLenI = %len(%trim(i_Text))     
c                   Call      'QDCXLATE'                          
c                   Parm                    c_CvtLenI             
c                   Parm      i_Text        i_Buffer              
c                   Parm                    c_Taula               
c                   Parm                    c_Lib

Me gustaría que el fichero tuviera un nombre largo.

Estas API's sólo funcionan con carpetas IFS montadas con sistema de archivos HFS. Por cuestiones de tiempo no he entrado en el tema de montar HFS en otra carpeta diferente de la QDLS de manera que permita nombres largos como en OS/2, que según el manual se puede hacer.

Así que para conseguir este objetivo, ejecutaremos el mandato CL CPY de la siguiente manera:

CPY OBJ('/qdls/proves/proves.txt')                   
    TOOBJ('/home/pruebas/fichero de pruebas.txt')

La carpeta /home del sistema está montada con el sistema de archivos root, que si permite nombres largos.

Hasta el momento no he encontrado la manera de gestionar ficheros en carpetas con FS root desde RPG. Desde C se puede hacer, pero al no disponer de compilador C, no he podido diseccionar las API's necesarias y aplicarlas a RPG... todo llegará ;-)

Puedo controlar la seguridad de estos ficheros?

Si. Se puede controlar a nivel de grupo de usuarios o de usuario de igual manera que tratamos los objetos del AS/400... claro, es que es un objeto del AS.

Para no extenderme más, recomiendo hacer GO FSSEC y ver las posibilidades de seguridad de los diferentes sistemas de archivos.

Àlex Corretge

Comentarios de usuarios

Nombre:
Mail:
Comentario:
 
Subir a la parte superior de la web

 

NUESTRA COMUNIDAD EN
ÚNETE Y.... ¡¡ PARTICIPA !!
Dossiers técnicos iSeries y AS400
- Seguridad
- Alta disponibilidad.
Nuestros links favoritos
- Tendencias tecnologías de la información
Expertos en tecnologías de la información, nos dan su punto de vista sobre las tendencias actuales y futuras
- Los últimos anuncios sobre hardware-software para iSeries AS400 realizados por IBM
- Freeware y shareware para el iSeries AS400
- Utilidades para el iSeries AS400 realizadas por profesionales
- Documentos. Trucos e ideas para resolver tus problemas
- Los manuales y links más interesantes del iSeries AS400

  Links patrocinados
  •  
  •  

[ Soy nuevo |   Profesionales |   AS qué |   Empresas |    Foros |   Recomiéndanos |    Productos ]
 
Recursos iSeries AS400. Es una web de: PUBLICACIONES HELP400, S.L. CIF:B-60-202827 Gran Vía de les Corts Catalanes, núm. 715, Entresuelo – 3ª - Barcelona - Tel.+34.932.310.049