Last active
June 8, 2017 15:29
-
-
Save rat/7834642 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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