5353 2065 6d20 4150 4320 6f2f
Esta é uma saída típica da representação hex de um arquivo binário. Como cada dígito hexadecimal equivale a 4 bits, e cada byte tem 8 bits, então cada 2 dígitos hexadecimais são 1 byte. Mas o que esses bytes significam?
O significado depende da interpretação.
Opções para visualização de arquivos binários são WinHex (Windows) e os comandos hexdump
ou xxd
(Linux)
Abrir arquivo binários é muito parecido com abrir arquivos texto, usamos a mesma função fopen(), e um ponteiro para arquivo também. A diferença é no modo de abertura. Para arquivos binários devemos informar ao SO que iremos abrir o arquivo no modo binário, adicionando um "b" ao final do modo. Assim, os modos de abertura binários são:
Code | Nome | Descrição |
---|---|---|
"rb" | Read | Abre um arquivo BINÁRIO para leitura, já deve existir o arquivo. |
"wb" | Write | Abre (ou cria) um arquivo BINÁRIO para escrita. Se o arquivo já existir seu conteúdo anterior é descartado. |
"ab" | Append | Abre (ou cria) um arquivo BINÁRIO para escrita. Ponteiro começa no final do arquivo. |
"r+b" | Read Plus | Abre um arquivo BINÁRIO para leitura ou escrita. O arquivo deve existir e poder ser modificado. |
"w+b" | Write Plus | Abre (ou cria) um arquivo BINÁRIO para leitura e escrita. Se o arquivo já existir seu conteúdo anterior é descartado. |
"a+b" | Append Plus | Abre (ou cria) um arquivo BINÁRIO para leitura e escrita. Ponteiro começa no final do arquivo. |
Um comando típico para abrir um arquivo binário em modo de leitura seria:
FILE* fd; // file descriptor char file[] = "file.bin"; // file name fd = fopen(file, "wb"); // abrindo arquivo para escrita
Lembre-se de sempre fechar os arquivos depois de usá-los. Isso com certeza vale para arquivos binários também. A função usada é fclose(fd)
Em arquivos binários realizamos operações de leitura e escrita em blocos de bytes através das funções abaixo.
int fread(void* ptr, int size, int count, FILE* stream ); // leitura int fwrite(const void* ptr, int size, int count, FILE* stream ); // escritaOs parâmetros dessas funções são:
Note que size * count
representa o total de bytes a serem lidos/escritos. A função sizeof()
é muito útil para descobrir o tamanho em bytes de uma variável.
Ambas as funções retornam o total de blocos trnansferidos com sucesso. Podemos usar esse valor para verificar se houve algum problema na leitura/escrita.
Utilizando o mesmo exemplo da aula passada, com a struct Estudante e o arquivo notas.txt
typedef struct{ char nome[100]; double nota; }Estudante; int main(){ int i; Estudante aluno; FILE *arquivo; arquivo = fopen("notas.bin","wb"); if (arquivo == NULL){ printf("Error! opening file"); return 1; } for(i = 0; i < 3; i++){ scanf("%s", aluno.nome); scanf("%lf", &aluno.nota); fwrite(&aluno, sizeof(Estudante), 1, arquivo); } fclose(arquivo); return 0; }
Note que conseguimos salvar a struct inteira dentro do arquivo notas.bin
typedef struct{ char nome[100]; double nota; }Estudante; int main() { int i; Estudante aluno; FILE *arquivo; if ((arquivo = fopen("notas.bin","rb")) == NULL){ printf("Error! opening file"); return 1; } for(n = 0; n < 3; ++n){ fread(&aluno, sizeof(Estudante), 1, arquivo); printf("nome : %s\n nota : %lf\n",aluno.nome, aluno.nota); } fclose(arquivo); return 0; }
É uma boa prática verificar o estado do arquivo após cada operação com ele. Ao final de cada chamada de função que manipule o arquivo, se ocorreu qualquer erro ele fica armazenado no ponteiro do arquivo (fd). Podemos acessar essas informações com as funções abaixo.
feof(fd); // != 0 if End Of File ferror(fd); // != 0 if Error Occured