1. Tipos de organização de arquivo
No mainframe, a organização do arquivo define como os registros são armazenados e acessados:
| Organização | COBOL | Acesso | Uso típico |
|---|---|---|---|
| Sequencial | SEQUENTIAL | Registro a registro, do início ao fim | Arquivos de movimento, relatórios, extrato |
| Indexado (VSAM KSDS) | INDEXED | Por chave ou sequencialmente | Cadastros, tabelas de referência, posição |
| Relativo | RELATIVE | Por número de registro | Tabelas 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
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)
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 ordemRANDOM— acessa diretamente por chave, sem passar pelos outrosDYNAMIC— 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:
* 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
| Modo | READ | WRITE | REWRITE | DELETE |
|---|---|---|---|---|
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
* 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)
* 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
* 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:
* 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:
* 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:
* 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ódigo | Significado | Situação |
|---|---|---|
00 | Sucesso | Operação concluída sem erros |
10 | Fim de arquivo | READ chegou ao último registro |
22 | Chave duplicada | WRITE com chave que já existe |
23 | Não encontrado | READ/DELETE/REWRITE por chave inexistente |
35 | Arquivo não existe | OPEN de arquivo que não foi alocado no JCL |
37 | Modo inválido | OPEN com modo incompatível com o tipo de arquivo |
47 | READ em arquivo não aberto para INPUT/I-O | Sequência errada de operações |
48 | WRITE em arquivo não aberto para OUTPUT/I-O/EXTEND | Sequência errada |
91 | Arquivo VSAM não disponível | Problema de alocação ou enfileiramento |
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:
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
* 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
* 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
* 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.