Arquivos binários Impressão e precisão desejada
-
24-09-2019 - |
Pergunta
Estou imprimindo uma variável, digamos Z1, que é uma matriz 1-D contendo números de ponto flutuante em um arquivo de texto para que eu possa importar para o MATLAB ou GNUPLOT para plotagem. Ouvi dizer que os arquivos binários (.dat) são menores que os arquivos .txt. A definição que eu uso atualmente para imprimir para um arquivo .txt é:
void create_out_file(const char *file_name, const long double *z1, size_t z_size){
FILE *out;
size_t i;
if((out = _fsopen(file_name, "w+", _SH_DENYWR)) == NULL){
fprintf(stderr, "***> Open error on output file %s", file_name);
exit(-1);
}
for(i = 0; i < z_size; i++)
fprintf(out, "%.16Le\n", z1[i]);
fclose(out);
}
Eu tenho três perguntas:
Os arquivos binários são realmente mais compactos do que os arquivos de texto?;
Se sim, gostaria de saber como modificar o código acima para poder imprimir os valores da matriz Z1 em um arquivo binário. Eu li que o FPRINTF precisa ser substituído pelo FWRITE. Meu arquivo de saída diz que o DODO.dat deve conter os valores da matriz Z1 com um número flutuante por linha.
Eu tenho %.16Le no meu código, mas acho que %.15LE está certo, pois tenho 15 dígitos de precisão com o longo dobro. Eu coloquei um ponto (.) Na posição de largura, pois acredito que isso permite que a expansão para um campo arbitrário mantenha o número desejado. Estou certo? Como exemplo com %.16LE, posso ter uma saída como 1.0047914240730432E-002, o que me dá 16 dígitos de precisão e a largura do campo tem a largura correta para exibir o número corretamente. A colocação de um ponto (.) Na posição de largura está em vez de um valor de largura uma boa prática?
Muito obrigado...
ATUALIZAR Está mudando para:
for(i = 0; i < z_size; i++)
fwrite(&z1, sizeof(long double), 1, out);
Ok, além da mudança para "WB+"? Não consigo ler o arquivo binário no MATLAB.
Solução
Sim, os arquivos binários são mais compactos, mas você perde a portabilidade e há vários outros problemas em potencial, portanto, a menos que seus arquivos de dados sejam problemáticos ou lentos para exportar/importar, é uma boa ideia manter o texto se você puder (você sempre pode comprimi -los para armazenamento, por exemplo, com zip)
Abra seu arquivo com "WB" em vez de "W" e use
fwrite()
- Você não tem mais "linhas" em seu arquivo - será apenas um fluxo de valores de ponto flutuante (binário)Você pode estar ficando confuso entre
double
elong double
- umalong double
pode ter até 16 bytes de tamanho e ter uma precisão de até 32 dígitos (no entanto, isso é dependente da implementação - o duplo longo pode geralmente ser de 10, 12 ou 16 bytes). UMAdouble
é geralmente 8 bytes e tem uma precisão de cerca de 16 dígitos.
Matlab pode não ser capaz de lidar com long double
(como não é bem padronizado), provavelmente você só quer escrever duplas em seu arquivo de dados, por exemplo
for (i = 0; i < z_size; i++)
{
double z = (double)z1[i];
fwrite(&z, sizeof(double), 1, out);
}