如何从 C 中的二进制文件中读取插入符号?
How to read caret notations from a binary file in C?
我有一个需求,每次一个字节读取二进制文件中的字符,并在满足特定条件时将它们连接起来。我 运行 在读取空字符时遇到问题,即 ^@,如插入符符号中所示。 snprintf 和 strcpy 都没有帮助我将这个空字符与其他字符连接起来。这很奇怪,因为当我使用
打印这个字符时
printf("%c",char1);
它打印出插入符号中的空字符,即 ^@。所以我的理解是连snprintf都应该拼接成功了
谁能告诉我如何实现这样的串联?
谢谢
C 字符串以 null 结尾。如果您的输入数据可以包含空字节,则您无法安全地使用字符串函数。相反,考虑只分配一个足够大的缓冲区(或根据需要动态调整它的大小)并将每个传入字节写入该缓冲区中的正确位置。
由于您不使用原始 ANSI 字符串,因此不能使用旨在与原始 ANSI 字符串一起使用的函数,因为解释字符串的方式。
在 C(和 C++)中,字符串通常以 null 结尾,即最后一个字符是 [=14=]
(值 0x00
)。至少对于字符串操作和 input/ouput(如 printf()
或 strcpy()
)的标准函数来说是这样。
例如,行
const char *text = "Hello World";
幕后变成
const char *text = "Hello World[=11=]";
因此,当您从文件中读取 [=14=]
并将其放入您的字符串时,您最终得到的实际上是一个空字符串。
为了让问题更清楚,举个简单的例子:
// Let's just assume the sequence 0x00, 0x01 is some special encoding
const char *input = "Hello[=12=]World!";
char output[256];
strcpy(output, input);
// strncpy() is for string manipulation, as such it will stop once it encounters a null terminator
printf("%s\n", output); // This will print 'Hello'
memcpy(output, input, 14); // 14 is the string length above plus null terminator
printf("%s\n", output); // This will again print 'Hello' (since it stops at the terminator)
printf("%s\n", output + 7); // This will print "World" (you're skipping the terminator using the offset)
以下是我整理的一个简单示例。它不一定显示最佳实践,也可能存在一些错误,但它应该向您展示一些可能的概念,如何使用原始字节数据,尽可能避免使用标准字符串函数。
#include <stdio.h>
#define WIDTH 16
int main (int argc, char **argv) {
int offset = 0;
FILE *fp;
int byte;
char buffer[WIDTH] = ""; // This buffer will store the data read, essentially concatenating it
if (argc < 2)
return 1;
if (fp = fopen(argv[1], "rb")) {
for(;;) {
byte = fgetc(fp); // get the next byte
if (byte == EOF) { // did we read over the end of the file?
if (offset % WIDTH)
printf("%*s %*.*s", 3 * (WIDTH - offset % WIDTH), "", offset % WIDTH, offset % WIDTH, buffer);
else
printf("\n");
return 0;
}
if (offset % WIDTH == 0) { // should we print the offset?
if (offset)
printf(" %*.*s", WIDTH, WIDTH, buffer); // print the char representation of the last line
printf("\n0x%08x", offset);
}
// print the hex representation of the current byte
printf(" %02x", byte);
// add printable characters to our buffer
if (byte >= ' ')
buffer[offset % WIDTH] = byte;
else
buffer[offset % WIDTH] = '.';
// move the offset
++offset;
}
fclose(fp);
}
return 0;
}
编译后,将任何文件作为第一个参数传递以查看其内容(不应太大以免破坏格式)。
我有一个需求,每次一个字节读取二进制文件中的字符,并在满足特定条件时将它们连接起来。我 运行 在读取空字符时遇到问题,即 ^@,如插入符符号中所示。 snprintf 和 strcpy 都没有帮助我将这个空字符与其他字符连接起来。这很奇怪,因为当我使用
打印这个字符时printf("%c",char1);
它打印出插入符号中的空字符,即 ^@。所以我的理解是连snprintf都应该拼接成功了
谁能告诉我如何实现这样的串联?
谢谢
C 字符串以 null 结尾。如果您的输入数据可以包含空字节,则您无法安全地使用字符串函数。相反,考虑只分配一个足够大的缓冲区(或根据需要动态调整它的大小)并将每个传入字节写入该缓冲区中的正确位置。
由于您不使用原始 ANSI 字符串,因此不能使用旨在与原始 ANSI 字符串一起使用的函数,因为解释字符串的方式。
在 C(和 C++)中,字符串通常以 null 结尾,即最后一个字符是 [=14=]
(值 0x00
)。至少对于字符串操作和 input/ouput(如 printf()
或 strcpy()
)的标准函数来说是这样。
例如,行
const char *text = "Hello World";
幕后变成
const char *text = "Hello World[=11=]";
因此,当您从文件中读取 [=14=]
并将其放入您的字符串时,您最终得到的实际上是一个空字符串。
为了让问题更清楚,举个简单的例子:
// Let's just assume the sequence 0x00, 0x01 is some special encoding
const char *input = "Hello[=12=]World!";
char output[256];
strcpy(output, input);
// strncpy() is for string manipulation, as such it will stop once it encounters a null terminator
printf("%s\n", output); // This will print 'Hello'
memcpy(output, input, 14); // 14 is the string length above plus null terminator
printf("%s\n", output); // This will again print 'Hello' (since it stops at the terminator)
printf("%s\n", output + 7); // This will print "World" (you're skipping the terminator using the offset)
以下是我整理的一个简单示例。它不一定显示最佳实践,也可能存在一些错误,但它应该向您展示一些可能的概念,如何使用原始字节数据,尽可能避免使用标准字符串函数。
#include <stdio.h>
#define WIDTH 16
int main (int argc, char **argv) {
int offset = 0;
FILE *fp;
int byte;
char buffer[WIDTH] = ""; // This buffer will store the data read, essentially concatenating it
if (argc < 2)
return 1;
if (fp = fopen(argv[1], "rb")) {
for(;;) {
byte = fgetc(fp); // get the next byte
if (byte == EOF) { // did we read over the end of the file?
if (offset % WIDTH)
printf("%*s %*.*s", 3 * (WIDTH - offset % WIDTH), "", offset % WIDTH, offset % WIDTH, buffer);
else
printf("\n");
return 0;
}
if (offset % WIDTH == 0) { // should we print the offset?
if (offset)
printf(" %*.*s", WIDTH, WIDTH, buffer); // print the char representation of the last line
printf("\n0x%08x", offset);
}
// print the hex representation of the current byte
printf(" %02x", byte);
// add printable characters to our buffer
if (byte >= ' ')
buffer[offset % WIDTH] = byte;
else
buffer[offset % WIDTH] = '.';
// move the offset
++offset;
}
fclose(fp);
}
return 0;
}
编译后,将任何文件作为第一个参数传递以查看其内容(不应太大以免破坏格式)。