2011-02-02 33 views
5

Actualmente estoy en la tarea de escribir una aplicación C#, que se ubica entre dos aplicaciones existentes. Todo lo que sé sobre la segunda aplicación es que procesa los archivos generados por la primera. La primera aplicación está escrita en Cobol.Leyendo un archivo generado por Cobol

Pasos: 1) Aplicación Cobol, escribe algunos archivos y copias en un directorio. 2) La segunda aplicación recoge estos archivos y los procesa.

Mi aplicación C# se ubicaría entre 1) un 2). Tendría que recoger el archivo generado por 1), leerlo, modificarlo y guardarlo, para que la aplicación 2) no supiera que estuve allí.

Tengo algunos problemas.

  • En primer lugar, si abro un archivo generado por 1) en el bloc de notas, la mayor parte es ilegible, mientras que otras partes sí lo son.
  • Si leo el archivo, lo modifico y lo guardo, debo guardar el archivo con la misma notación utilizada por la aplicación cobol, para que la aplicación 2), no sepa que he estado allí.

He tratado de leer el archivo de esta manera, pero Está siendo ilegibles:

Código:

 string ss = @"filename"; 

     using (FileStream fs = new FileStream(ss, FileMode.Open)) 
     { 
      StreamReader sr = new StreamReader(fs); 
      string gg = sr.ReadToEnd(); 
     } 

también si encuentro una manera de hacer que sea legible (utilizando algún tipo de la técnica de codificación), me temo que cuando guarde el archivo de nuevo, puedo cambiar su formato original.

¿Alguna idea? Sugerencias?

+3

Necesita averiguar el proveedor del COBOL, luego descubra cuál es el formato del archivo. No hay un solo formato "COBOL". –

+0

Sería interesante saber qué formato * supone * ser, ¿es un CSV? ¿Puedes hablar con el tipo que genera el archivo para preguntarle qué debe contener el archivo? –

+0

COBOL es anterior a CSV. –

Respuesta

26

Para leer el archivo COBOL-genned, necesitará saber:

En primer lugar, usted necesitará el registro diseño (cuaderno) para el archivo. Un diseño de registro COBOL se verá algo como esto:

01 PATIENT-TREATMENTS. 
    05 PATIENT-NAME    PIC X(30). 
    05 PATIENT-SS-NUMBER   PIC 9(9). 
    05 NUMBER-OF-TREATMENTS  PIC 99 COMP-3. 
    05 TREATMENT-HISTORY OCCURS 0 TO 50 TIMES 
      DEPENDING ON NUMBER-OF-TREATMENTS 
      INDEXED BY TREATMENT-POINTER. 
     10 TREATMENT-DATE. 
      15 TREATMENT-DAY  PIC 99. 
      15 TREATMENT-MONTH  PIC 99. 
      15 TREATMENT-YEAR  PIC 9(4). 
     10 TREATING-PHYSICIAN  PIC X(30). 
     10 TREATMENT-CODE   PIC 99. 

También necesitará una copia de IBM Principios de funcionamiento (S/360, S370, z/OS, en realidad no importa para nuestros propósitos) Última está disponible en IBM en

los capítulos 8 (Instrucciones decimales) y 9 (Floating Point general e instrucciones de apoyo) son los bits interesantes para nuestros propósitos.

Sin eso, que está bastante perdido.

Luego, debe comprender los tipos de datos COBOL. Por ejemplo:

  • PIC define un campo con formato alfanumérico (PIC 9 (4), por ejemplo, 4 dígitos decimales, que podría rellenarse con caracteres de espacio si falta). La imagen 999V99 tiene 5 dígitos decimales, con un punto decimal implícito. Continuamente y así forthe.
  • BINARY es [normalmente] un entero binario con punto fijo firmado. Los tamaños habituales son halfword (2 octets) y fullword (4 octets).
  • COMP-1 es punto flotante de precisión simple.
  • COMP-2 es punto flotante de doble precisión.

Si el origen de datos es un mainframe de IBM, COMP-1 y COMP-2 probablemente no será punto flotante EEI: será de IBM base-16 excess 64 floating point format. Necesitará algo como S/370 Principios de operación para ayudarlo a comprenderlo.

  • COMP-3 es 'packed decimal', de longitudes variables. El decimal empaquetado es una forma compacta de representar un número decimal. La declaración tendrá el siguiente aspecto: PIC S9999V99 COMP-3. Esto dice que está firmado, consta de 6 dígitos decimales con un punto decimal implícito. El decimal empaquetado representa cada dígito decimal como un mordisco de un octeto (valores hexadecimales 0-9). El dígito de orden superior es el nibble superior del octeto más a la izquierda. El nibble bajo del octeto más a la derecha es un valor hexadecimal A-F que representa el signo. Por lo tanto, la cláusula PIC anterior requerirá ceil((6+1)/2) o 4 octetos. el valor -345.67, como se representa por la cláusula PIC anterior se verá como 0x0034567D. El valor del signo real puede variar (el valor predeterminado es C/positivo, D/negativo, pero A, C, E y F se tratan como positivos, mientras que solo B y D se tratan como negativos). Nuevamente, vea S \ 370 Principles of Operation para detalles sobre la representación.

Relacionado con COMP-3 es zonado decimal. Esto podría declararse como `PIC S9999V99 '(firmado, 5 dígitos decimales, con un punto decimal implícito). Los dígitos decimales, en EBCDIC, son los valores hexadecimales 0xFO - 0xF9. 'Unpack' (instrucción de máquina de mainframe) toma un campo decimal empaquetado y lo convierte en un campo de caracteres. El proceso es:

  • comienzan con el octeto del extremo derecho. Inviértalo, para que el signo de mordisco esté en la parte superior y colóquelo en el octeto más a la derecha del campo de destino.
  • Trabajando de derecha a izquierda (fuente y destino ambos), quite cada mordisco restante del campo decimal empaquetado y colóquelo en el nibble bajo del siguiente octeto disponible en el destino. Llene el nibble alto con un hex. F.

  • La operación finaliza cuando se agota el campo de origen o de destino.

  • Si el campo de destino no está agotado, si se rellenó con ceros rellenando los octetos restantes con el decimal '0' (oxF0).

Así que nuestro valor ejemplo, -345,67, si se almacena con el valor del signo por defecto (hex D), obtendría desembalado como 0xF0F0F0F3F4F5F6D7 ('0003456P', en EBDIC).

[Aquí tienes. Hay un cuestionario más adelante]

  1. Si la aplicación COBOL vive en un mainframe de IBM, ¿se ha convertido el archivo de su EBCDIC original a ASCII? De lo contrario, tendrá que hacer el mapeo usted mismo (Sugerencia: no es necesariamente tan sencillo como podría parecer, ya que esto podría ser un proceso selectivo, solo los campos de caracteres se convierten (COMP-1, COMP-2, COMP) -3 y BINARY quedan excluidos ya que son una secuencia de octetos binarios).Peor aún, hay múltiples sabores de representaciones EBCDIC, debido a las variadas implementaciones nacionales y las diferentes cadenas de impresión en uso en diferentes impresoras.

Oh ... una última cosa. El hardware del mainframe tiende a gustar diferentes elementos alineados en los límites de media palabra, palabra o palabra doble, por lo que el diseño del registro puede no corresponderse directamente con los octetos del archivo, ya que puede haber octetos de relleno insertados entre campos para mantener la alineación de palabras necesaria.

Buena suerte.

+0

Volveré mañana y voto favorable - se han agotado para hoy. Excelente respuesta ¡Parece una tarea bastante formidable! :) –

+0

Por lo general, no es tan malo como parece. La mayoría de las aplicaciones COBOL escriben registros de formato de carácter directo. Raras veces se ve el punto flotante en la naturaleza, pero es posible que vea el punto decimal empacado o el punto fijo binario. El binario de punto fijo es un mapeo directo 1: 1 a 'short' o' int' (fuera de los problemas big-/little-endian). El decimal empaquetado es un poco complicado, pero no es tan malo escribir una rutina de conversión para convertirlo a 'decimal'. –

+0

-1 por no incluir un relleno en el diseño de registro :) –

2
  • Sería útil saber qué Cobol dialecto que se trata de porque no hay un único formato Cobol. Algunos compiladores de Cobol (Micro Focus) ponen una "Descripción del archivo" en la parte frontal de los archivos (para Micro Focus VB/indexados).

  • Eche un vistazo al RecordEditor (http://record-editor.sourceforge.net/). Tiene un File Wizard que puede ser muy útil para usted.

    • En el Asistente de archivos, establezca el archivo como Archivo de ancho fijo (más común en Cobol). El programa te permite probar diferentes longitudes de registro. Cuando obtiene la longitud correcta de registro, los campos de texto deben alinearse.
    • Más adelante en el Asistente hay una búsqueda de campo que puede buscar Binary, Comp-3, Text Fields.
    • Hay algunas notas sobre el uso Asistente del RecordEditor con un archivo desconocido aquí http://record-editor.sourceforge.net/Unkown.htm
  • menos que el archivo proviene de una unidad central/AS400 es poco probable que utilice EBCDIC (cp037 - página con código 37 es de US EBCDIC), cualquier texto es más probable en Ascii.

  • El archivo probablemente contenga datos de Packed-Decimal (Comp3) y Binary-Integer. La mayoría de los Cobols usan Big-Endian (para enteros Comp) incluso en Intel (hardware little endian).

  • Una cosa para recordar con Cobol PIC s9 (6) V99 comp se almacena como un entero binario con x'0001 'que representa 0.01. A menos que tenga la definición Cobol no se puede decir wether un 1 binario es 1 0,1, 0,01, etc

2

que veo de los comentarios adjuntos a su pregunta que se trata de la estructura de archivos por lotes COBOL “clásico”: Registro de encabezado, registros de detalle y registro de tráiler.

¡Esta es probablemente una mala noticia si usted es responsable de crear el registro del tráiler! El registro típico de "avance" se utiliza para identificar el final del archivo y proporciona información de control, como el número de registros que lo preceden y varias sumas de cheques y/o totales generales para los registros de "detalles". En otras palabras, puede que necesite leer y resumir todo el archivo para crear el avance. Agregue a esto la posibilidad de que gran parte de los datos en el archivo estén en Decimal empaquetado, Decimal por zonas u otros tipos de datos numéricos de COBOLish, podría estar en un momento difícil.

Es posible que desee preguntar por qué está agregando registros de tráiler a estos archivos. Normalmente, el "avance" es producido por el mismo programa o aplicación que creó los registros de "detalles". Se supone que el avance actúa como una verificación de que la aplicación o el programa emisor escribió todos los datos que se suponía que debía. Los totales de resumen, los recuentos, etc. son utilizados por la aplicación receptora para verificar que los registros de detalles coincidan con los detalles anteriores.Se supone que esto sirve como otra verificación de que la aplicación de envío no impidió los datos o que no se corrompió en la ruta (eso no era una broma, pero tal vez debería ser). Cuando un "hombre en el medio" crea los trailers, como que derrota todo el propósito del ejercicio (sin importar qué tan defectuoso haya sido comenzar).

+0

+1 para recordarme cómo se hicieron las cosas cuando los campos Total se desbordaron en el trailer :) –