Skip to content

Instantly share code, notes, and snippets.

@rat
Last active June 8, 2017 15:29
Show Gist options
  • Save rat/7834642 to your computer and use it in GitHub Desktop.
Save rat/7834642 to your computer and use it in GitHub Desktop.
#include "file.h"
/**
* Cria um arquivo binário com a extensão .dat de forma segura.
* A função verifica a existência do arquivo antes de tentar criá-lo,
* assim evita a sobrescrita de dados.
*
* @param char *file string com o nome do arquivo que você quer criar.
* @return void
*
* @example para criar um arquivo você só precisa chamar essa função da
* maneira mostrada abaixo:
*
* makeFile("nomeArquivo.dat");
*
* Ao chamar a função como mostrado acima, o sistema vai criar o arquivo,
* e se ele existir, ignora a criação se não existir tenta criar, se não
* tiver permissão lança um erro e sai do programa.
*
* @author Renato Tavares <dr.renatotavares@gmail.com>
* @version 1.0
*
*/
void makeFile(char *file) {
if (access(file, F_OK) != -1) {
// arquivo já existe não preciso criar novamente
} else {
FILE *filePtr;
if ((filePtr = fopen(file, "w")) == NULL) {
printf("Arquivo %s não pode ser criado.", file);
exit(EPERM);
}
fclose(filePtr);
}
}
/**
* Insere um novo registro no arquivo especificado. A função SEMPRE
* insere o novo registro no final do arquivo, assim os dados
* anteriores sempre são preservados.
*
* @param char *file string com o nome do arquivo que você quer inserir.
* @param void *data struct com os dados que você deseja inserir.
* @param size_t len tamanho da struct com os dados a inserir.
* @return void
*
* @example para usar essa função basta chamá-la da seguinte forma:
* fileInsert("ArquivoInserido.dat", &structComDados, sizeof(structComDados));
*
* @author Renato Tavares <dr.renatotavares@gmail.com>
* @version 1.0
*
*/
void fileInsert(char *file, void *data, size_t len) {
FILE *filePtr;
if ((filePtr = fopen(file, "rb+")) == NULL) {
printf("Arquivo %s não pode ser aberto.", file);
exit(EPERM);
} else {
fseek(filePtr, 0L, SEEK_END);
fwrite(data, len, 1, filePtr);
fclose(filePtr);
}
}
/**
* Recupera o próximo ID para ser inserido no arquivo, basta chamar a função
* e recuperar o próximo id em uma variável do tipo int.
*
* @param char *file string com o nome do arquivo que você deseja pegar próximo id.
* @param size_t len tamanho da struct que o arquivo possui.
* @return int O próximo id
*
* @example para usar essa função basta chamá-la da seguinte forma:
* id = getID("ArquivoParaPegarID.dat", sizeof( structDentroDoArquivo ));
*
* @author Renato Tavares <dr.renatotavares@gmail.com>
* @version 1.0
*
*/
int getID(char *file, size_t len) {
int id = 0;
FILE *filePtr;
if ((filePtr = fopen(file, "rb+")) == NULL) {
printf("Arquivo %s não pode ser lido.", file);
exit(EPERM);
}
fseek(filePtr, 0, SEEK_END);
id = 1 + (ftell(filePtr) / len); // Calcula próximo ID
return id;
fclose(filePtr);
}
/**
* Atualiza o arquivo especificado (no registro correspondente ao ID passado)
* com os novos dados, descartando os dados anteriores.
*
* @param char *file string com o nome do arquivo que você deseja atualizar.
* @param void *data os novos dados a serem inseridos.
* @param size_t len tamanho da struct que o arquivo possui.
* @param int id o id que deseja atualizar
* @return void
*
* @example para usar essa função basta chamá-la da seguinte forma:
* fileUpdate("ArquivoParaAtualizar.dat",&structCOmDados, sizeof( structDentroDoArquivo ), IDdocadastroParaMudar);
*
* @author Renato Tavares <dr.renatotavares@gmail.com>
* @version 1.0
*
*/
void fileUpdate(char *file, void *data, size_t len, int id) {
FILE *filePtr;
if ((filePtr = fopen(file, "rb+")) == NULL) {
printf("Arquivo %s não pode ser aberto.", file);
exit(EPERM);
} else {
fseek(filePtr, (id - 1) * len, SEEK_SET);
fwrite(data, len, 1, filePtr);
fclose(filePtr);
}
}
/**
* Deleta o registro solicitado de forma lógica (Soft deletion)
*
* @param char *file string com o nome do arquivo que você deseja remover um registro.
* @param int id o id que deseja remover
* @param contante do tipo de struct que deseja remover (CLIENTES, CARROS, LOCACOES)
* @return void
*
* @example para usar essa função basta chamá-la da seguinte forma:
* fileDelete("arquivoARemover.dat", 1, CLIENTES);
* exemplo acima remove o cliente de ID 1 (um) do arquivo
*
* @author Renato Tavares <dr.renatotavares@gmail.com>
* @version 1.0
*
*/
void fileDelete(char *file, int id, int structs) {
char conf;
FILE *filePtr;
if ((filePtr = fopen(file, "rb+")) == NULL) {
printf("Arquivo %s não pode ser aberto.", file);
exit(EPERM);
} else {
switch (structs) {
case 0:; // Isso é porco, não é certo porém é um BUG do C, não tem como escapar. ;.;
Cliente cliente;
fseek(filePtr, (id - 1) * sizeof (cliente), SEEK_SET);
fread(&cliente, sizeof (cliente), 1, filePtr);
printf("\nRealmente deseja excluir o cliente %s? <S/N>:", cliente.nome);
setbuf(stdin, NULL);
scanf("%c", &conf);
if (conf == 's' || conf == 'S') {
cliente.ativo = 0;
fileUpdate(file, &cliente, sizeof (cliente), cliente.id);
printf("\nCliente removido com sucesso.");
} else {
printf("\nExclusão abortada.");
}
break;
case 1:;
Carro carro;
fseek(filePtr, (id - 1) * sizeof (carro), SEEK_SET);
fread(&carro, sizeof (carro), 1, filePtr);
printf("\nRealmente deseja excluir o carro %s com id %d? <S/N>:", carro.nome, carro.id);
setbuf(stdin, NULL);
scanf("%c", &conf);
if (conf == 's' || conf == 'S') {
carro.ativo = 0;
fileUpdate(file, &carro, sizeof (carro), carro.id);
printf("\nCarro removido com sucesso.");
} else {
printf("\nExclusão abortada.");
}
break;
case 2:;
Locacao locacao;
fseek(filePtr, (id - 1) * sizeof (locacao), SEEK_SET);
fread(&locacao, sizeof (locacao), 1, filePtr);
printf("\nRealmente deseja excluir a locação com id %d? <S/N>:", locacao.id);
setbuf(stdin, NULL);
scanf("%c", &conf);
if (conf == 's' || conf == 'S') {
carro.ativo = 0;
fileUpdate(file, &locacao, sizeof (locacao), locacao.id);
printf("\nCarro removido com sucesso.");
} else {
printf("\nExclusão abortada.");
}
break;
}
fclose(filePtr);
}
}
/**
* Imprime a linha correspondente ao ID passado.
*
* @param char *file string com o nome do arquivo que você deseja imprimir.
* @param int id O id que deseja imprimir
* @param contante do tipo de struct que deseja imprimir (CLIENTES, CARROS, LOCACOES)
* @return void
*
* @example para usar essa função basta chamá-la da seguinte forma:
* FileSingleRead("ArquivoAImprimir.dat", 1, CLIENTES);
* exemplo acima imprime o cliente de ID 1 (um) do arquivo
*
* @author Renato Tavares <dr.renatotavares@gmail.com>
* @version 1.0
*
*/
void FileSingleRead(char *file, int id, int structs) {
FILE *filePtr;
if ((filePtr = fopen(file, "rb+")) == NULL) {
printf("Arquivo %s não pode ser aberto.", file);
exit(EPERM);
} else {
switch (structs) {
case 0:;
Cliente cliente;
fseek(filePtr, (id - 1) * sizeof (cliente), SEEK_SET);
fread(&cliente, sizeof (cliente), 1, filePtr);
if (cliente.ativo)
printf("%s %d", cliente.nome, cliente.id);
break;
case 1:;
Carro carro;
fseek(filePtr, (id - 1) * sizeof (carro), SEEK_SET);
fread(&carro, sizeof (carro), 1, filePtr);
if (carro.ativo)
printf("%d %s %s %f", carro.id, carro.nome, carro.marca, carro.valor);
break;
case 2:;
Locacao locacao;
fseek(filePtr, (id - 1) * sizeof (locacao), SEEK_SET);
fread(&locacao, sizeof (locacao), 1, filePtr);
if (locacao.ativo)
printf("%d %s %s", locacao.id, locacao.cliente, locacao.carro);
break;
}
}
fclose(filePtr);
}
/**
* Imprime todos os registros ativos do arquivo
*
* @param char *file string com o nome do arquivo que você deseja imprimir.
* @param contante do tipo de struct que deseja imprimir (CLIENTES, CARROS, LOCACOES)
* @return void
*
* @example para usar essa função basta chamá-la da seguinte forma:
* fileListaAll("ArquivoAImprimir.dat", CLIENTES);
* exemplo acima imprime o arquivo completamente
*
* @author Renato Tavares <dr.renatotavares@gmail.com>
* @version 1.0
*
*/
void fileListAll(char *file, int structs) {
FILE *filePtr;
if ((filePtr = fopen(file, "rb+")) == NULL) {
printf("Arquivo %s não pode ser aberto.", file);
exit(EPERM);
} else {
switch (structs) {
case 0:;
Cliente cliente;
while (!feof(filePtr)) {
fread(&cliente, sizeof (cliente), 1, filePtr);
if (!feof(filePtr))
if (cliente.ativo)
printf("\n%s %d", cliente.nome, cliente.id);
}
break;
case 1:;
Carro carro;
while (!feof(filePtr)) {
fread(&carro, sizeof (carro), 1, filePtr);
if (!feof(filePtr))
if (carro.ativo)
printf("\n%d %s %s %f", carro.id, carro.nome, carro.marca, carro.valor);
}
break;
case 2:;
Locacao locacao;
while (!feof(filePtr)) {
fread(&locacao, sizeof (locacao), 1, filePtr);
if (!feof(filePtr))
if (locacao.ativo)
printf("\n%d %s %s", locacao.id, locacao.cliente, locacao.carro);
}
break;
}
}
fclose(filePtr);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment