1. Tipos de organização de arquivo

No mainframe, a organização do arquivo define como os registros são armazenados e acessados:

OrganizaçãoCOBOLAcessoUso típico
SequencialSEQUENTIALRegistro a registro, do início ao fimArquivos de movimento, relatórios, extrato
Indexado (VSAM KSDS)INDEXEDPor chave ou sequencialmenteCadastros, tabelas de referência, posição
RelativoRELATIVEPor número de registroTabelas de acesso direto (menos comum)

🦕 Analogia — organização de arquivo é como uma gaveta

Sequencial é como uma fila de fichas: para achar a décima, você passa pelas nove anteriores. Indexado é como um fichário com abas: você vai direto na aba "C" e encontra o registro pelo CPF sem precisar passar por todos os outros. Para processar tudo de uma vez, o sequencial é imbatível em velocidade — para buscar um registro específico, o indexado é essencial.

2. Declarando arquivos: SELECT e FD

Um arquivo precisa ser declarado em dois lugares: no ENVIRONMENT DIVISION (associando o nome COBOL ao dataset físico) e no DATA DIVISION (descrevendo o layout do registro).

Arquivo sequencial

COBOL Declaração — arquivo sequencial
       ENVIRONMENT DIVISION.
       INPUT-OUTPUT SECTION.
       FILE-CONTROL.
           SELECT ARQ-MOVIMENTO
               ASSIGN TO        DDMOVTO
               ORGANIZATION IS  SEQUENTIAL
               ACCESS MODE IS   SEQUENTIAL
               FILE STATUS IS   WS-FS-MOVIMENTO.

       DATA DIVISION.
       FILE SECTION.
       FD  ARQ-MOVIMENTO
           RECORDING MODE IS F
           BLOCK CONTAINS 0 RECORDS
           RECORD CONTAINS 150 CHARACTERS.
       01  REG-MOVIMENTO.
           05  MV-AGENCIA       PIC 9(04).
           05  MV-CONTA         PIC 9(08).
           05  MV-TIPO          PIC X(03).
           05  MV-VALOR         PIC 9(13)V99.
           05  MV-DATA          PIC 9(08).
           05  MV-FILLER        PIC X(120).

       WORKING-STORAGE SECTION.
       01  WS-FS-MOVIMENTO  PIC X(02).

Arquivo indexado (VSAM KSDS)

COBOL Declaração — arquivo indexado
       FILE-CONTROL.
           SELECT ARQ-CLIENTE
               ASSIGN TO        DDCLIEN
               ORGANIZATION IS  INDEXED
               ACCESS MODE IS   DYNAMIC
               RECORD KEY IS    CLI-CPF
               FILE STATUS IS   WS-FS-CLIENTE.

       FD  ARQ-CLIENTE.
       01  REG-CLIENTE.
           05  CLI-CPF          PIC X(11).   *chave primária
           05  CLI-NOME         PIC X(40).
           05  CLI-SALDO        PIC S9(13)V99.
           05  CLI-STATUS       PIC X(01).
               88  CLI-ATIVO     VALUE 'A'.
               88  CLI-INATIVO   VALUE 'I'.

💗 Para iniciantes — ACCESS MODE

  • SEQUENTIAL — lê/grava sempre do começo ao fim, em ordem
  • RANDOM — acessa diretamente por chave, sem passar pelos outros
  • DYNAMIC — permite os dois modos no mesmo programa (o mais flexível para arquivos indexados)

3. OPEN — abrindo o arquivo

Todo arquivo precisa ser aberto antes de usar. O modo de abertura define o que você pode fazer com ele:

COBOL Modos de OPEN
             * INPUT: leitura — não pode gravar
       OPEN INPUT  ARQ-MOVIMENTO

             * OUTPUT: gravação — cria ou recria o arquivo (apaga o existente!)
       OPEN OUTPUT ARQ-SAIDA

             * I-O: leitura e atualização — para REWRITE e DELETE
       OPEN I-O    ARQ-CLIENTE

             * EXTEND: grava no final de um arquivo já existente
       OPEN EXTEND ARQ-LOG

             * Vários arquivos de uma vez
       OPEN INPUT  ARQ-MOVIMENTO
                   ARQ-CLIENTE
            OUTPUT ARQ-SAIDA
                   ARQ-REJEITOS
ModoREADWRITEREWRITEDELETE
INPUT
OUTPUT
I-O✅*
EXTEND

* WRITE em modo I-O só funciona em arquivos indexados (para inserir novo registro).

4. READ — lendo registros

Leitura sequencial

COBOL READ sequencial
             * Forma básica: lê para a área do FD (REG-MOVIMENTO)
       READ ARQ-MOVIMENTO
           AT END
               SET FIM-ARQUIVO TO TRUE
           NOT AT END
               PERFORM 2000-PROCESSA-REGISTRO
       END-READ

             * Forma com INTO: copia para área de trabalho
       READ ARQ-MOVIMENTO INTO WS-MOVIMENTO
           AT END SET FIM-ARQUIVO TO TRUE
       END-READ

             * Verificando FILE STATUS após leitura
       READ ARQ-MOVIMENTO
           AT END CONTINUE
       END-READ
       EVALUATE WS-FS-MOVIMENTO
           WHEN '00'  CONTINUE               *leitura ok
           WHEN '10'  SET FIM-ARQUIVO TO TRUE *fim de arquivo
           WHEN OTHER PERFORM 9000-ERRO-LEITURA
       END-EVALUATE

Leitura por chave (arquivo indexado)

COBOL READ por chave
             * Busca direto pelo CPF — ACCESS MODE RANDOM ou DYNAMIC
       MOVE '12345678901' TO CLI-CPF
       READ ARQ-CLIENTE
           INVALID KEY
               MOVE 'CLIENTE NAO ENCONTRADO' TO WS-MSG
               PERFORM 9100-TRATA-NAO-ENCONTRADO
           NOT INVALID KEY
               PERFORM 2000-PROCESSA-CLIENTE
       END-READ

             * START: posiciona no arquivo indexado para leitura sequencial
             * depois do START, usa READ NEXT para avançar
       MOVE '123' TO CLI-CPF
       START ARQ-CLIENTE KEY >= CLI-CPF
           INVALID KEY PERFORM 9200-ERRO-POSICIONA
       END-START

       PERFORM UNTIL FIM-ARQUIVO
           READ ARQ-CLIENTE NEXT
               AT END SET FIM-ARQUIVO TO TRUE
           END-READ
           IF NOT FIM-ARQUIVO
               PERFORM 2000-PROCESSA-CLIENTE
           END-IF
       END-PERFORM

5. WRITE — gravando registros

COBOL WRITE sequencial e indexado
             * WRITE sequencial: grava o conteúdo da área do FD
       MOVE WS-DADOS-SAIDA TO REG-SAIDA
       WRITE REG-SAIDA       *atenção: é o registro (01 do FD), não o arquivo!

             * FROM: monta e grava em um único passo
       WRITE REG-SAIDA FROM WS-DADOS-SAIDA

             * Arquivo de impressão: AFTER ADVANCING controla o espaçamento
       WRITE REG-RELATORIO FROM WS-LINHA-DETALHE
           AFTER ADVANCING 1 LINE
       WRITE REG-RELATORIO FROM WS-CABECALHO
           AFTER ADVANCING PAGE  *salta para nova página

             * WRITE indexado: insere novo registro
       MOVE WS-NOVO-CLIENTE TO REG-CLIENTE
       WRITE REG-CLIENTE
           INVALID KEY
               MOVE 'CHAVE DUPLICADA' TO WS-ERRO
               PERFORM 9000-TRATA-ERRO
       END-WRITE

⚠️ WRITE usa o nome do registro, não do arquivo

Um erro clássico de quem está aprendendo: escrever WRITE ARQ-SAIDA em vez de WRITE REG-SAIDA. O verbo WRITE recebe o nome do registro (o 01 declarado sob o FD), não o nome do arquivo. O READ usa o nome do arquivo; o WRITE usa o nome do registro.

6. REWRITE — atualizando registros

O REWRITE substitui o registro que foi lido por último (sequencial) ou identificado pela chave (indexado). O arquivo precisa estar aberto em modo I-O:

COBOL REWRITE
             * REWRITE indexado — primeiro lê, depois altera, depois reescreve
       MOVE '12345678901' TO CLI-CPF
       READ ARQ-CLIENTE
           INVALID KEY PERFORM 9100-NAO-ENCONTRADO
       END-READ

       IF WS-FS-CLIENTE = '00'
           ADD WS-VALOR-DEPOSITO TO CLI-SALDO
           REWRITE REG-CLIENTE
               INVALID KEY
                   PERFORM 9200-ERRO-REWRITE
           END-REWRITE
       END-IF

7. DELETE — excluindo registros

O DELETE funciona apenas em arquivos indexados (VSAM). Em sequencial não existe exclusão lógica nativa — a convenção é marcar um campo de status como inativo:

COBOL DELETE em arquivo indexado
             * Exclui o registro com a chave atual
       MOVE '12345678901' TO CLI-CPF
       DELETE ARQ-CLIENTE
           INVALID KEY
               MOVE 'REGISTRO NAO ENCONTRADO' TO WS-MSG
               PERFORM 9300-ERRO-DELETE
       END-DELETE

             * Alternativa para sequencial: exclusão lógica com flag
       MOVE 'I' TO CLI-STATUS      *marca como inativo
       REWRITE REG-CLIENTE          *grava de volta com status 'I'
       END-REWRITE

8. CLOSE — fechando o arquivo

Sempre feche os arquivos antes de terminar o programa. O CLOSE garante que todos os buffers sejam gravados e os recursos liberados:

COBOL CLOSE
             * Fechar individualmente
       CLOSE ARQ-MOVIMENTO

             * Fechar vários de uma vez
       CLOSE ARQ-MOVIMENTO
             ARQ-CLIENTE
             ARQ-SAIDA

✅ Feche os arquivos mesmo em caso de erro

Sempre feche os arquivos no parágrafo de finalização, inclusive nos caminhos de erro. Se o programa terminar sem fechar um arquivo de saída, os dados podem não ser gravados — os buffers ficam em memória e são perdidos. No parágrafo 9000-TRATA-ERRO, chame PERFORM 3100-FECHA-ARQUIVOS antes do STOP RUN.

9. FILE STATUS — tratando erros

O FILE STATUS é um campo de dois caracteres que o COBOL preenche após cada operação de arquivo. É a forma mais confiável de tratar erros de I/O:

CódigoSignificadoSituação
00SucessoOperação concluída sem erros
10Fim de arquivoREAD chegou ao último registro
22Chave duplicadaWRITE com chave que já existe
23Não encontradoREAD/DELETE/REWRITE por chave inexistente
35Arquivo não existeOPEN de arquivo que não foi alocado no JCL
37Modo inválidoOPEN com modo incompatível com o tipo de arquivo
47READ em arquivo não aberto para INPUT/I-OSequência errada de operações
48WRITE em arquivo não aberto para OUTPUT/I-O/EXTENDSequência errada
91Arquivo VSAM não disponívelProblema de alocação ou enfileiramento
COBOL Usando FILE STATUS
       WORKING-STORAGE SECTION.
       01  WS-FS-CLIENTE    PIC X(02).
           88  FS-OK            VALUE '00'.
           88  FS-FIM-ARQ       VALUE '10'.
           88  FS-DUPLICADO     VALUE '22'.
           88  FS-NAO-ENCONTRADO VALUE '23'.
           88  FS-ARQ-INEXISTE  VALUE '35'.

       PROCEDURE DIVISION.
       1100-ABRE-ARQUIVOS.
           OPEN INPUT ARQ-CLIENTE
           EVALUATE TRUE
               WHEN FS-OK
                   CONTINUE
               WHEN FS-ARQ-INEXISTE
                   MOVE 'ARQUIVO CLIENTE NAO ALOCADO' TO WS-MSG
                   PERFORM 9000-TRATA-ERRO
               WHEN OTHER
                   MOVE 'ERRO AO ABRIR CLIENTE: ' TO WS-MSG
                   STRING WS-MSG WS-FS-CLIENTE
                       DELIMITED SIZE INTO WS-MSG-COMPLETA
                   PERFORM 9000-TRATA-ERRO
           END-EVALUATE.

10. Exemplo completo

Um programa batch completo que lê um arquivo de movimentos sequencial e atualiza saldos em um cadastro de clientes indexado:

COBOL Programa completo — atualiza saldo
       IDENTIFICATION DIVISION.
       PROGRAM-ID. ATUASALD.

       ENVIRONMENT DIVISION.
       INPUT-OUTPUT SECTION.
       FILE-CONTROL.
           SELECT ARQ-MOVIMENTO ASSIGN TO DDMOVTO
               ORGANIZATION IS SEQUENTIAL
               FILE STATUS IS WS-FS-MOV.
           SELECT ARQ-CLIENTE ASSIGN TO DDCLIEN
               ORGANIZATION IS INDEXED
               ACCESS MODE IS DYNAMIC
               RECORD KEY IS CLI-CPF
               FILE STATUS IS WS-FS-CLI.

       DATA DIVISION.
       FILE SECTION.
       FD ARQ-MOVIMENTO.
       01 REG-MOVIMENTO.
           05 MV-CPF    PIC X(11).
           05 MV-TIPO   PIC X(01).
               88 MV-CREDITO VALUE 'C'.
               88 MV-DEBITO  VALUE 'D'.
           05 MV-VALOR  PIC 9(11)V99.

       FD ARQ-CLIENTE.
       01 REG-CLIENTE.
           05 CLI-CPF    PIC X(11).
           05 CLI-NOME   PIC X(40).
           05 CLI-SALDO  PIC S9(11)V99.

       WORKING-STORAGE SECTION.
       01 WS-FS-MOV         PIC X(02).
       01 WS-FS-CLI         PIC X(02).
       01 WS-FIM-ARQ        PIC X(01).
           88 FIM-ARQUIVO   VALUE 'S'.
       01 WS-TOTAL-PROC    PIC 9(08) VALUE ZEROS.
       01 WS-TOTAL-ERRO    PIC 9(08) VALUE ZEROS.

       PROCEDURE DIVISION.
       0000-INICIO.
           PERFORM 1000-INICIALIZA
           PERFORM 2000-PROCESSA
           PERFORM 3000-FINALIZA
           STOP RUN.

       1000-INICIALIZA.
           OPEN INPUT  ARQ-MOVIMENTO
           OPEN I-O    ARQ-CLIENTE
           MOVE 'N' TO WS-FIM-ARQ.

       2000-PROCESSA.
           READ ARQ-MOVIMENTO
               AT END SET FIM-ARQUIVO TO TRUE
           END-READ
           PERFORM UNTIL FIM-ARQUIVO
               PERFORM 2100-ATUALIZA-SALDO
               READ ARQ-MOVIMENTO
                   AT END SET FIM-ARQUIVO TO TRUE
               END-READ
           END-PERFORM.

       2100-ATUALIZA-SALDO.
           MOVE MV-CPF TO CLI-CPF
           READ ARQ-CLIENTE
               INVALID KEY
                   ADD 1 TO WS-TOTAL-ERRO
               NOT INVALID KEY
                   IF MV-CREDITO
                       ADD MV-VALOR TO CLI-SALDO
                   ELSE
                       SUBTRACT MV-VALOR FROM CLI-SALDO
                   END-IF
                   REWRITE REG-CLIENTE
                   END-REWRITE
                   ADD 1 TO WS-TOTAL-PROC
           END-READ.

       3000-FINALIZA.
           CLOSE ARQ-MOVIMENTO
                 ARQ-CLIENTE
           DISPLAY 'REGISTROS PROCESSADOS: ' WS-TOTAL-PROC
           DISPLAY 'ERROS (NAO ENCONTRADO): ' WS-TOTAL-ERRO.

11. Erros comuns

1. Abrir arquivo com modo errado

COBOL Modo de abertura errado
             * Tentando REWRITE em arquivo aberto como INPUT → FS=47
       OPEN INPUT ARQ-CLIENTE
       REWRITE REG-CLIENTE   *ERRO: precisa de I-O para atualizar

             * Correto para atualização:
       OPEN I-O ARQ-CLIENTE

2. Não verificar FILE STATUS após OPEN

COBOL Verificar FILE STATUS no OPEN
             * Nunca assuma que o OPEN foi bem-sucedido
       OPEN INPUT ARQ-MOVIMENTO
       IF WS-FS-MOV NOT = '00'
           MOVE 'ERRO AO ABRIR DDMOVTO: ' TO WS-MSG
           PERFORM 9000-TRATA-ERRO
       END-IF
             * FS=35 significa que a DD não foi informada no JCL

3. REWRITE sem READ antes

COBOL Sequência correta para atualizar
             * ERRADO: REWRITE sem READ anterior → FS=43 ou comportamento indefinido
       MOVE WS-DADOS TO REG-CLIENTE
       REWRITE REG-CLIENTE   *qual registro vai atualizar?

             * CORRETO: sempre lê antes de reescrever
       MOVE WS-CHAVE TO CLI-CPF
       READ ARQ-CLIENTE ...
       END-READ
             * agora altera os campos desejados
       ADD WS-VALOR TO CLI-SALDO
       REWRITE REG-CLIENTE
       END-REWRITE

🟣 Para quem já programa — VSAM e enfileiramento

Em ambientes de produção, arquivos VSAM indexados abertos em modo I-O com DISP=SHR no JCL podem causar conflito com outros jobs que também querem atualizar o mesmo dataset. O FILE STATUS 91 indica que o VSAM não conseguiu obter exclusividade. Em jobs críticos, use DISP=OLD para garantir acesso exclusivo — mas lembre-se que isso bloqueia outros processos enquanto o job estiver rodando.