有没有更好的方法将十六进制打印到文件?

时间:2014-07-03 02:03:48

标签: c binary hex

我正在尝试将二进制格式转换为十六进制格式,二进制数据每秒都有一个流程,我的代码如下:

for(int i = 0; i < strlen(s); i++)
{
   sprintf(in+i*2, "%02x", s[i]);
}
fprintf(fp, "%s\n", in);

但它太慢,因为数据如此迅速地进入。

有没有更好的方法来处理它?<​​/ p>

是否有像fnprintf(fp,size,“%。* 02x \ n”,num,in)这样的函数?

2 个答案:

答案 0 :(得分:3)

第一个问题是你在循环的每次传递中调用strlen。请注意,strlen必须计算字节数,直到找到字符串的结尾。如果您的字符串长度为100个字节,则循环将调用strlen 100次,每次strlen将计算100个字节。结果是strlen将在循环结束前计算总共10000个字节。

第二个问题是你在每次循环中都会调用sprintfprintf系列的所有成员都具有相当重的功能,在高性能代码中应该避免使用。鉴于将字节转换为两位十六进制数字很容易,您实际上并不需要sprintf

所以,如果您消除strlensprintf,代码会是什么样子。 (通过检查输出缓冲区溢出,我也投入了一些安全性。这就是bend正在使用的内容。)

#define BUFSIZE 200

int digit;
char *sptr, *bptr, *bend;
char string[BUFSIZE];
char buffer[BUFSIZE];

bptr = buffer;
bend = &buffer[BUFSIZE - 2];
for ( sptr = string; *sptr != '\0'; sptr++ )
{
    digit = (*sptr >> 4) & 0xf;
    *bptr++ = ( digit > 9 ) ? digit + 'a' - 10 : digit + '0';

    digit = *sptr & 0xf;
    *bptr++ = ( digit > 9 ) ? digit + 'a' - 10 : digit + '0';

    if ( bptr >= bend )
        break;
}
*bptr = '\0';

fprintf( fp, "%s\n", buffer );

答案 1 :(得分:1)

一些事情:

  1. 在循环条件中停止使用strlen()。编译器可以意识到它的值是恒定的并且优化了重复,这是可行的,但是为什么在你不需要首先使用它时依赖它呢?

  2. 停止使用这种昂贵的功能来解决一项微不足道的任务。所有你关心的是在每个字节中输出两个半字节的字符数字,所以这样做

  3. 您很难用fputc的潜在宏版本来击败简单查找序列的性能。转储到缓冲的io流时,您可能会处于或接近epsilon开销:

    #include <stdio.h>
    #include <stdlib.h>
    
    void hex_dump(FILE *fp, const void *src, size_t slen)
    {
        static const char digits[] = "0123456789abcdef";
        const unsigned char *p = src;
        while (slen--)
        {
            putc(digits[(*p >> 4) & 0xF], fp);
            putc(digits[*p++ & 0xF], fp);
        }
        putc('\n', fp);
    }
    
    
    int main()
    {
        const char msg[] = "A simple message to print";
        hex_dump(stdout, msg, sizeof(msg));
    }
    

    <强>输出

    412073696d706c65206d65737361676520746f207072696e7400
    

    注意:我选择putc是故意的。它可以(并且经常是)一个宏,它可以缓冲FILE流的缓冲。理由:Faaaast。

    当然,您可以使用简单的strlen转发器来解决上述问题。如:

    void hex_dump_str(const char *s)
    {
        hex_dump(s, strlen(s));
    }
    

    或者完全自定义它以在nulchar上终止并消除strlen扫描,因为您可以在实际转储到流时执行此操作。这是你的选择。类似的东西:

    void hex_dump_str(FILE *fp, const char *src)
    {
        static const char digits[] = "0123456789abcdef";
        const unsigned char *p = (const unsigned char*)src;
        while (*p)
        {
            putc(digits[(*p >> 4) & 0xF], fp);
            putc(digits[*p++ & 0xF], fp);
        }
        putc('\n', fp);
    }
    

    祝你好运。