C: Escrita e Leitura uma seqüência de e para um arquivo binário
-
19-09-2019 - |
Pergunta
Eu quero armazenar cordas em um arquivo binário, juntamente com um monte de outros dados, im usando o código abaixo (quando eu usá-lo para valer as cordas será malloc) eu posso escrever para o arquivo. Ive olhou para ele em um editor hexadecimal. Im não tem certeza im escrevendo o terminador nulo corretamente (ou se eu preciso). quando eu li para trás para fora eu recebo o mesmo comprimento de cadeia que eu armazenados, mas não a string. o que estou fazendo de errado?
FILE *fp = fopen("mybinfile.ttt", "wb");
char drumCString[6] = "Hello\0";
printf("%s\n", drumCString);
//the string length + 1 for the null terminator
unsigned short sizeOfString = strlen(drumCString) + 1;
fwrite(&sizeOfString, sizeof(unsigned short), 1, fp);
//write the string
fwrite(drumCString, sizeof(char), sizeOfString, fp);
fclose(fp);
fp = fopen("mybinfile.ttt", "rb");
unsigned short stringLength = 0;
fread(&stringLength, sizeof(unsigned short), 1, fp);
char *drumReadString = malloc(sizeof(char) * stringLength);
int count = fread(&drumReadString, sizeof(char), stringLength, fp);
//CRASH POINT
printf("%s\n", drumReadString);
fclose(fp);
Solução
Você está fazendo de errado durante a leitura. você colocar o & para a variável ponteiro é por isso que dá falha de segmentação.
Eu removi que ele funciona bem e retorna Olá corretamente.
int count = fread(drumReadString, sizeof(char), stringLength, fp);
Outras dicas
Eu vejo um par de questões, algumas problemática, alguns estilística.
- Você realmente deve testar os valores de retorno de
malloc
,fread
efwrite
já que é possível que a alocação pode falhar, e nenhum dado pode ser lido ou escrito. -
sizeof(char)
é sempre 1, não há necessidade de multiplicar por ele. - A matriz
"Hello\0"
personagem é, na verdade, 7 bytes de comprimento. Você não precisa adicionar um terminador nulo supérfluo. - Eu prefiro o
char x[] = "xxx";
idioma em vez de especificar um comprimento definido (a menos que queira uma série mais longa do que a string é claro). - Quando você
fread(&drumReadString ...
, na verdade você está substituindo o ponteiro , e não a memória que ele aponta. Esta é a causa de sua queda. Deve serfread(drumReadString ...
.
Um casal de dicas:
1
A terminação \0
está implícito em qualquer cadeia de aspas duplas, e adicionando um adicional de, no final você acaba com dois. As duas inicializações seguintes são idênticos:
char str1[6] = "Hello\0";
char str2[6] = { 'H', 'e', 'l', 'l', 'o', '\0', '\0'};
Assim
char drumReadString[] = "Hello";
é suficiente, e dependendo do tamanho da matriz é opcional quando é inicializado como este, o compilador irá descobrir o tamanho necessário (6 bytes).
2
Ao escrever uma string, você pode muito bem basta escrever todos os caracteres de uma só vez (em vez de escrever um por vezes um sizeOfString personagem):
fwrite(drumCString, sizeOfString, 1, fp);
3
Apesar de não tão comum para um cenário normal pc desktop, malloc pode retornar NULL e você será beneficiado com o desenvolvimento de um habbit de sempre verificar o resultado porque em ambientes incorporados, obtendo NULL não é um resultado improvável.
char *drumReadString = malloc(sizeof(char) * stringLength);
if (drumReadString == NULL) {
fprintf(stderr, "drumReadString allocation failed\n");
return;
}
Você não escrever o NUL terminar, você não precisa, mas então você tem que pensar sobre a adição de que durante a leitura. ie malloc StringLength + 1 char, ler caracteres StringLength e adicionar um \0
no final do que foi lido.
Agora, o aviso habitual: se você estiver escrevendo arquivo binário do jeito que você está fazendo aqui, você tem muitas suposições não declaradas que tornam a sua formato difícil de porta, às vezes até mesmo para outra versão do mesmo compilador - Eu vi alinhamento padrão em struct muda entre versões do compilador.
Alguns mais a acrescentar à paxdiablo e AProgrammer - se você estiver indo para usar malloc no futuro, apenas fazê-lo a partir do ir buscar. É melhor forma e significa que você não terá de depuração quando passar.
Além disso eu não estou vendo totalmente o uso do short sem sinal, se você está pensando em escrever um arquivo binário, consideram que o tipo char não assinado é geralmente de tamanho em bytes, o que torna muito conveniente para o efeito.
Você simplesmente remover seu & drumReadString na function.You fread simplesmente usar drumReadString nessa função como Ganesh mentioned.Because, drumReadString é um array.Array é semelhante aos ponteiros que apontam para o local da memória diretamente.