【发布时间】:2012-08-21 12:33:18
【问题描述】:
如何从文件中读取 64 位无符号整数?我将它存储为实际的二进制数据,而不是字符串表示形式。
【问题讨论】:
-
好吧,那么你会使用 fread,而不是 fscanf.. 因为那是从字符串中读取的。 cplusplus.com/reference/clibrary/cstdio/fread
如何从文件中读取 64 位无符号整数?我将它存储为实际的二进制数据,而不是字符串表示形式。
【问题讨论】:
有人谈到可移植性问题,所以我在这里发布修改后的版本 (无符号长长)。请参阅代码中的注释。
#include <stdio.h>
//#include <stdlib.h> //this need to working system("pause"); only
//system("pause"); need only to don't close window
//if program running by double click on exe in windows.
//#include <inttypes.h> //this need to working with uint64_t and no need to working with (unsigned long long)
//function to dump hex from file.
void hexdump(const char *const filename)
{
FILE *file;
unsigned char byte;
file = fopen(filename, "rb");
if (file == NULL)
return;
fprintf(stdout, "hexdump of `%s': ", filename);
while (fread(&byte, 1, 1, file) == 1)
fprintf(stdout, "0x%02x ", byte);
fprintf(stdout, "\n");
}
int main(void) {
//x64
//write text, write binary,
//read text, read binary
FILE *fout, *filein;
char *filename_txt = "myfile.txt"; //text filename
char *filename_bin = "myfile.bin"; //bin filename
//two x64 numbers
//uint64_t
//uint64_t my64 = 258; //258 (dec) = 102(hex) = 0000 0000 0000 0102 -> 0201 0000 0000 0000 -> 2010000000000000 -> to file
//uint64_t my642 = 1234567891011121314; //1234567891011121314(dec) = 112210F4B2D230A2 (hex) = 1122 10F4 B2D2 30A2 -> A230 D2B2 F410 2211 -> A230D2B2F4102211 -> to file
//unsigned long long x64
unsigned long long my64 = 1234567887654321; //as 64 bit integer
unsigned long long my642 = 0x462D53C650DB1; //the same number, as hex
// write as text
fout = fopen(filename_txt, "wt");
//uint64_t
// fprintf(fout, "%" PRIu64 "\n", my64);
// fprintf(fout, "%" PRIu64 "\n", my642);
//unsigned long long
fprintf(fout, "%llu%llu\n", my64);
fprintf(fout, "%llu%llu\n", my642);
fclose(fout);
// write as bytes
fout = fopen(filename_bin, "wb");
fwrite(&my64, sizeof(my64), 1, fout); //write first number
fwrite(&my642, sizeof(my64), 1, fout); //write second number
fclose(fout);
// read as text
filein = fopen(filename_txt, "rt");
if(filein==NULL){printf("Cann't open file \"myfile.txt\" for reading...\n");}
else{
printf("Try to reading file as text\n");
char buf[1000];
while (fgets(buf,1000,filein)!=NULL)
printf("%s",buf); //just print buf as string.
fclose(filein);
}
// read as bytes
/* check that the content of the file is not printable, i.e. not text */
hexdump(filename_bin);
filein = fopen(filename_bin, "rb");
if (filein == NULL){
printf("Cann't open file \"myfile.bin\" for reading...\n");
return -1;
}
else{
//uint64_t value;
unsigned long long int value;
printf("Try to reading file as bytes\n");
value = 0;
while(fread(&value, sizeof(value), 1, filein) == 1){
// fprintf(stdout, "The value read was %" PRIu64 "\n", value); //uint64_t
fprintf(stdout, "The value read was %llu%llu\n", value); //unsigned long long
}
fclose(filein);
}
//system("pause");
return 0;
}
1 字节整数可以写为二进制并从二进制中读取 如果变量具有类型 - 无符号字符。
【讨论】:
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
//function to dump hex from file.
void hexdump(const char *const filename)
{
FILE *file;
unsigned char byte;
file = fopen(filename, "rb");
if (file == NULL)
return;
fprintf(stdout, "hexdump of `%s': ", filename);
while (fread(&byte, 1, 1, file) == 1)
fprintf(stdout, "0x%02x ", byte);
fprintf(stdout, "\n");
}
int main(void) {
//x64
//write text, write binary,
//read text, read binary
FILE *fout, *filein;
char *filename_txt = "myfile.txt"; //text filename
char *filename_bin = "myfile.bin"; //bin filename
//unsigned long long my64 = 0x1234567887654321;
//two x64 numbers
uint64_t my64 = 258; //258 (dec) = 102(hex) = 0000 0000 0000 0102 -> 0201 0000 0000 0000 -> 2010000000000000 -> to file
uint64_t my642 = 1234567891011121314; //1234567891011121314(dec) = 112210F4B2D230A2 (hex) = 1122 10F4 B2D2 30A2 -> A230 D2B2 F410 2211 -> A230D2B2F4102211 -> to file
// write as text
fout = fopen(filename_txt, "wt");
fprintf(fout, "%" PRIu64 "\n", my64);
fprintf(fout, "%" PRIu64 "\n", my642);
fclose(fout);
// write as bytes
fout = fopen(filename_bin, "wb");
fwrite(&my64, sizeof(my64), 1, fout);
fwrite(&my642, sizeof(my64), 1, fout);
fclose(fout);
// read as text
filein = fopen(filename_txt, "rt");
if(filein==NULL){printf("Cann't open file \"myfile.txt\" for reading...\n");}
else{
printf("Try to reading file as text\n");
char buf[1000];
while (fgets(buf,1000,filein)!=NULL)
printf("%s",buf);
fclose(filein);
}
// read as bytes
/* check that the content of the file is not printable, i.e. not text */
hexdump(filename_bin);
filein = fopen(filename_bin, "rb");
if (filein == NULL){
printf("Cann't open file \"myfile.bin\" for reading...\n");
return -1;
}
else{
uint64_t value;
printf("Try to reading file as bytes\n");
value = 0;
while(fread(&value, sizeof(value), 1, filein) == 1){
fprintf(stdout, "The value read was %" PRIu64 "\n", value);
}
fclose(filein);
}
system("pause");
return 0;
}
【讨论】:
fread / fwrite 可能不够。 (uint64_t 如果可用则指定为使用 2 的补码而不使用填充位,但字节序仍然是一个问题。)
类似这样的:
FILE * fp = fopen("file.bin", "rb");
uint64_t value;
if (fread(&value, sizeof value, fp) != sizeof value) { /* error */ }
// ...
fclose(fp);
如果是您编写数据,这应该是开箱即用的。如果数据来自其他地方,请检查二进制格式的文档以说明序列化格式和您的平台之间的表示差异(例如,可能需要字节交换)。
另一种在教学上更有用但效率较低的方法是将数据读入缓冲区并应用您自己的处理。这更灵活(例如,您可以处理像 3-2-1-4-7-8-6-5 这样的疯狂字节序),但可能要慢很多:
unsigned char buf[sizeof uint64_t];
if (fread(buf, sizeof buf, fp) != sizeof buf) { /* error */ }
uint64_t leval = buf[0] + (buf[1] << 8) + /* ... */;
uint64_t beval = buf[7] + (buf[6] << 8) + /* ... */;
uint64_t ceval = (buf[0] << 16) + (buf[1] << 8) + buf[2] + (buf[3] << 24) + /* ... */;
【讨论】:
它是如何编码的? endianness 中的二进制数通常不同。如果你想假设它与当前主机的字节序相同,你可以直接使用fread。否则,您需要在阅读后进行字节交换。
对于奖励积分,假设您可以控制它的序列化方式,您可以使用一些标志或字节顺序标记来指示字节顺序。
【讨论】: