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