用c语言将文件中十六进制数据与二进制数据相互转换

简介: 用c语言将文件中十六进制数据与二进制数据相互转换

本文中的代码可以将文件中的十六进制存储与二进制存储相互转换。


十六进制->二进制


原理是:每两位存储为一个字符(char)保存。

因为十六进制数最大为 f,即 15,在内存中只需要 4 位就可以表示。而一般情况下一个字符是占一个字节 8 位,所以正好可以存储十六进制两位。

举个栗子:

在文件中存储十六进制为ab,ab转换为二进制,就是1010 1011,刚好八位,可以联想到ASCII码,用一个字符可以表示。

注意转为二进制后,前32个为不可见字符,附图ASCII码。

(将十六进制转为二进制还会压缩一倍的空间?因为ab本来占两个字节,现在转成二进制,即一个char字符,只占用一个字节大小。但是转换过程中时间消耗,我不太确定是否优化了)

#include <stdio.h>
int main() {
    FILE * in  = fopen("./data.txt", "r");
    FILE * out  = fopen("./data", "w");
    while (1) {
        char c;
        unsigned char d = 0;
        for (int i = 0; i < 2; ++i) {
            // 从 in 读取 1 个大小为 1 字节数据保存在 c
            if (fread(&c, 1, 1, in) == 0) {
                fclose(in);
                fclose(out);
                return 0;
            }
          // 读到空格或者换行索引需要回退
            if (c == ' ' || c == '\n') {
                i--;
                continue;
            }
            // 将读到的十六进制字符转成具体的十进制数字
            if (c >= '0' && c <= '9') {
                c -= '0';
            } else if (c >= 'a' && c <= 'f') {
                c -= 'a';
                c += 10;
            } else {
                printf("error");
            }
            //printf("c -> %d  \n", c);
            d <<= 4;
            d |= c;
        }
        //printf("-------> %c\n", d);
        fwrite(&d, 1, 1, out);
    }
    return 0;
}

核心代码:

d <<= 4 and d |= c

解释:

内层for循环为两次,c读取两次:

我们假设第一次读到a字符,第二次读到b字符。

(或运算:参加运算的两个对象只要有一个为1,其值为1)

微信截图_20230519013320.png

如果想知道转换是否正确的话,可以用 hexdump -C + 文件名(data) 检查一下是否正确。(linux命令)


二进制->十六进制


这个就是上边操作相反的过程,读取二进制文件,然后转成十六进制字符保存。

#include <stdio.h>
int main() {
    FILE * in  = fopen("./data.txt", "r");
    FILE * out  = fopen("./data", "w");
    char space = ' ';
    char enter = '\n';
    int idx = 0;
    while (1) {
        char c[2];
        unsigned char d = 0;
        for (int i = 0; i < 4; ++i) {
            // 读取一个字节
            if (fread(&d, 1, 1, in) == 0) {
                fclose(in);
                fclose(out);
                return 0;
            }
            // 一个二进制字节转回两个十六进制字符
            char mask = 0xf;
            c[0] = d >> 4;      // 将低位移走就是该字节保存的第一个十六进制字符
            c[1] = d & mask;    // 保留 d 的低位就是该字节保存的第二个十六进制字符
            // 将十进制数字转回对应的十六进制字符(与上一步转换的代码相反)
            if (c[0] >= 0 && c[0] <= 9) {
                c[0] += '0';
            } else {
                c[0] -= 10;
                c[0] += 'a';
            }
            if (c[1] >= 0 && c[1] <= 9) {
                c[1] += '0';
            } else {
                c[1] -= 10;
                c[1] += 'a';
            }
            // 从 c 地址开始读取两个字节,写到 out 
            fwrite(&c, 1, 2, out);
        }
        // 写空格或者换行 保持格式
        idx++;
        if (idx == 4){
            idx = 0;
            fwrite(&enter, 1, 1, out);
        } else {
            fwrite(&space, 1, 1, out);
        }
    }
    return 0;
}

mask的二进制是0000 1111。

相关文章
|
1月前
|
存储 程序员 编译器
C 语言中的数据类型转换:连接不同数据世界的桥梁
C语言中的数据类型转换是程序设计中不可或缺的一部分,它如同连接不同数据世界的桥梁,使得不同类型的变量之间能够互相传递和转换,确保了程序的灵活性与兼容性。通过强制类型转换或自动类型转换,C语言允许开发者在保证数据完整性的前提下,实现复杂的数据处理逻辑。
|
1月前
|
存储 数据管理 C语言
C 语言中的文件操作:数据持久化的关键桥梁
C语言中的文件操作是实现数据持久化的重要手段,通过 fopen、fclose、fread、fwrite 等函数,可以实现对文件的创建、读写和关闭,构建程序与外部数据存储之间的桥梁。
|
1月前
|
存储 网络协议 算法
【C语言】进制转换无难事:二进制、十进制、八进制与十六进制的全解析与实例
进制转换是计算机编程中常见的操作。在C语言中,了解如何在不同进制之间转换数据对于处理和显示数据非常重要。本文将详细介绍如何在二进制、十进制、八进制和十六进制之间进行转换。
41 5
|
2月前
|
存储 数据建模 程序员
C 语言结构体 —— 数据封装的利器
C语言结构体是一种用户自定义的数据类型,用于将不同类型的数据组合在一起,形成一个整体。它支持数据封装,便于管理和传递复杂数据,是程序设计中的重要工具。
|
2月前
|
存储 编译器 数据处理
C 语言结构体与位域:高效数据组织与内存优化
C语言中的结构体与位域是实现高效数据组织和内存优化的重要工具。结构体允许将不同类型的数据组合成一个整体,而位域则进一步允许对结构体成员的位进行精细控制,以节省内存空间。两者结合使用,可在嵌入式系统等资源受限环境中发挥巨大作用。
73 11
|
2月前
|
算法 C语言
C语言中的文件操作技巧,涵盖文件的打开与关闭、读取与写入、文件指针移动及注意事项
本文深入讲解了C语言中的文件操作技巧,涵盖文件的打开与关闭、读取与写入、文件指针移动及注意事项,通过实例演示了文件操作的基本流程,帮助读者掌握这一重要技能,提升程序开发能力。
139 3
|
3月前
|
存储 编译器 C语言
如何在 C 语言中判断文件缓冲区是否需要刷新?
在C语言中,可以通过检查文件流的内部状态或使用`fflush`函数尝试刷新缓冲区来判断文件缓冲区是否需要刷新。通常,当缓冲区满、遇到换行符或显式调用`fflush`时,缓冲区会自动刷新。
|
3月前
|
存储 编译器 C语言
C语言:文件缓冲区刷新方式有几种
C语言中文件缓冲区的刷新方式主要包括三种:自动刷新(如遇到换行符或缓冲区满)、显式调用 fflush() 函数强制刷新、以及关闭文件时自动刷新。这些方法确保数据及时写入文件。
|
3月前
|
存储 C语言 C++
深入C语言,发现多样的数据之枚举和联合体
深入C语言,发现多样的数据之枚举和联合体
深入C语言,发现多样的数据之枚举和联合体
|
3月前
|
存储 C语言
深入C语言内存:数据在内存中的存储
深入C语言内存:数据在内存中的存储