打印文件的二进制表示

我需要一个函数来打印一个读取文件的二进制表示forms,比如unix中的xxd程序,但是我想自己做。 hex与%x一起工作得很好,但没有内置二进制格式。 有人知道怎么做吗?

我通常不相信用完整的代码实现来回答这些问题,但是我很多年前就把这些代码交给了我,我觉得有必要把它传递下去。 我已经删除了除用法之外的所有注释,因此您可以尝试弄清楚它是如何工作的。

代码库16

#include <stdio.h> #include <ctype.h> // Takes a pointer to an arbitrary chunk of data and prints the first-len bytes. void dump (void* data, unsigned int len) { printf ("Size: %d\n", len); if (len > 0) { unsigned width = 16; char *str = (char *)data; unsigned int j, i = 0; while (i < len) { printf (" "); for (j = 0; j < width; j++) { if (i + j < len) printf ("%02x ", (unsigned char) str [j]); else printf (" "); if ((j + 1) % (width / 2) == 0) printf (" - "); } for (j = 0; j < width; j++) { if (i + j < len) printf ("%c", isprint (str [j]) ? str [j] : '.'); else printf (" "); } str += width; i += j; printf ("\n"); } } } 

输出库16 (Flash视频的前512字节的摘录)

 Size: 512 00 00 00 20 66 74 79 70 - 69 73 6f 6d 00 00 02 00 - ... ftypisom.... 69 73 6f 6d 69 73 6f 32 - 61 76 63 31 6d 70 34 31 - isomiso2avc1mp41 00 06 e8 e6 6d 6f 6f 76 - 00 00 00 6c 6d 76 68 64 - ....moov...lmvhd 00 00 00 00 7c 25 b0 80 - 7c 25 b0 80 00 00 03 e8 - ....|%..|%...... 00 0c d6 2a 00 01 00 00 - 01 00 00 00 00 00 00 00 - ...*............ 00 00 00 00 00 01 00 00 - 00 00 00 00 00 00 00 00 - ................ 00 00 00 00 00 01 00 00 - 00 00 00 00 00 00 00 00 - ................ 00 00 00 00 40 00 00 00 - 00 00 00 00 00 00 00 00 - ....@........... 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 - ................ 00 01 00 02 00 01 9f 38 - 74 72 61 6b 00 00 00 5c - .......8trak...\ 

我假设你已经知道如何判断一个文件的大小,并以二进制模式读取一个文件,所以我将会把它放在讨论之外。 根据您的终端宽度,您可能需要调整变量: width – 代码目前设计为80个字符的终端。

我还假设,当你提到xxd与“二进制”相结合,你的意思是非文本,而不是基数2.如果你想基2, width设置为6,并替换printf ("%02x ", (unsigned char) str [j]); 有了这个:

 { for (int k = 7; k >= 0; k--) printf ("%d", ((unsigned char)str [j] >> k) & 1); printf (" "); } 

所需的更改非常简单,只需要将八位字节的所有8位和掩码全部移除,而不是最低位。 请记得按照一开始似乎违反直觉的顺序来执行此操作,因为我们从左向右打印。

输出基址2 (摘录自Flash视频的前512字节*)

 Size: 512 00000000 00000000 00000000 - 00100000 01100110 01110100 - ... ft 01111001 01110000 01101001 - 01110011 01101111 01101101 - ypisom 00000000 00000000 00000010 - 00000000 01101001 01110011 - ....is 01101111 01101101 01101001 - 01110011 01101111 00110010 - omiso2 01100001 01110110 01100011 - 00110001 01101101 01110000 - avc1mp 00110100 00110001 00000000 - 00000110 11101000 11100110 - 41.... 01101101 01101111 01101111 - 01110110 00000000 00000000 - moov.. 00000000 01101100 01101101 - 01110110 01101000 01100100 - .lmvhd 00000000 00000000 00000000 - 00000000 01111100 00100101 - ....|% 10110000 10000000 01111100 - 00100101 10110000 10000000 - ..|%.. 00000000 00000000 00000011 - 11101000 00000000 00001100 - ...... 

*为了简单起见,让我们假装一个字节总是8位。

根据语言的不同,假设您有按位操作,可以让您对变量的每一位进行操作,您可以执行以下操作。 如果需要编码,将文件读入一个缓冲区或一行,现在迫使它扩展为ASCII(8位/ 1字节字符),当你得到缓冲区时,从7循环到0,并使用和按位和a转移到检查每个位的值,让我举个例子在C:

 // gcc -Wall -Wextra -std=c99 xxd.c #include <stdio.h> #include <string.h> int main() { // Whatever buffer size you chose. char buffer[32]; //Feel free to replace stdin to a File Pointer, or any other stream // Reading into a char, means reading each byte at once while (!feof(stdin)) { // Read at most buffer bytes. Since its ASCII 1 byte = 1 char. fgets(buffer, sizeof(buffer), stdin); // Iterate though each character in the string/buffer. const size_t len = strlen(buffer); for (size_t j = 0; j < len; j++) { // Print the most significant bit first. for (int i = 7; i >=0; i--) { // Check if the i-th bit is set printf(buffer[j] & (1 << i) ? "1" : "0"); } } } return 0; }