二进制文件的读写(C语言&python)

先放一个例子:

  这个例子是从本地读出一个文件存入数组,然后让文件的每一个二进制位(一个字节)与0x12相与,之后的数据存入另一个二进制文件:

利用fread、fwrite函数

#include <stdio.h>
#include <stdlib.h>
long _filesize(FILE *stream)
{
       long curpos, length;
       curpos = ftell(stream);
       fseek(stream, 0L, SEEK_END);
       length = ftell(stream);
       fseek(stream, curpos, SEEK_SET);
       return length;
}
int main()
{
       FILE *fp;
       FILE *wp;
       if ((fp = fopen("flag", "rb")) == NULL)
              return 0;
       printf("You can get flag by reading the code.\n");
       long buffsize = _filesize(fp);
       char *buff = (char *)malloc(buffsize * sizeof(char));
       fread(buff, buffsize, 1, fp);
       fclose(fp);
       char m[10000];
       for (int i = 0; i < buffsize; i++) {
              m[i] = buff[i];
       }
       /*for (int i = 0; i < buffsize; i++) {   //显示前10个字符
              printf("%x ", m[i]);
       }*/
/*
       for (i = 0; i < buffsize; i++) {   //显示前10个字符
              printf("%x ", (unsigned char)buff[i]);
       }*/
       for (int i = 0; i < buffsize; i++) {   //显示前10个字符
              m[i] ^= 0x12;
              m[i] -= 10;
       }
       wp = fopen("flagout", "wb");
       fwrite(m, 1, buffsize, wp);
       fclose(wp);
       free(buff);
       system("pause");
       return 0;
}

C语言读取二进制文件:

FILE *fp;
if ((fp = fopen("flag", "rb")) == NULL)
       return 0;
long buffsize = _filesize(fp);
char *buff = (char *)malloc(buffsize * sizeof(char));
fread(buff, buffsize, 1, fp);
fclose(fp);
free(buff);

写入文件:

FILE *wp;
 wp = fopen("flagout", "wb");
fwrite(m, 1, buffsize, wp);
fclose(wp);

fseek函数

函数名:fseek函数

头文件:#include<stdio.h>

功能:把与fp有关的文件位置指针放到一个指定位置。

格式: int fseek(FILE *stream, long offset, int fromwhere);

范例一:fseek(fp, 0L, SEEK_END);

解释:文件指针定位到文件末尾,偏移0个字节

范例二: fseek(fp,50L,0);或fseek(fp,50L,SEEK_SET);

解释:其作用是将位置指针移到离文件头50个字节处。

起始点对应的数字代表的文件位置
SEEK_SET0文件开头
SEEK_CUR1文件当前位置
SEEK_END2文件末尾

说明:

offset:偏移量

fromwhere:起始位置

其中,“位移量”是long型数据,它表示位置指针相对于“起始点”移动的字节数。

如果位移量是一个正数,表示从“起始点”开始往文件尾方向移动;

如果位移量是一个负数,则表示从“起始点”开始往文件头方向移动。

“起始点”不能任意设定,它只能是在stdio.h中定义的三个符号常量之一:

注意:<br
fseek函数的文件指针,应该为已经打开的文件。如果没有打开的文件,那么将会出现错误。

以上内容来自网络上资料,整理结果。

下面请看例题:

例题代码:

#include <stdio.h>
#include <stdlib.h>//fseek函数调用
int main()
{
 // 开始文件中的内容为aaaaaaaaa
FILE * fp = fopen("a.txt", "r+");
 if (fp == NULL) {
printf("file error\n");
exit(1);
}
fseek(fp, 2, SEEK_SET);//光标移到文件开始起第二个字节处。
fwrite("yun", 1, 3, fp); //文件内写入内容yun
fclose(fp);
 return 0;
}

Python读写二进制文件

struct模块

struct模块的内容不多,也不是太难,下面对其中最常用的方法进行介绍:

1、 struct.pack

struct.pack用于将Python的值根据格式符,转换为字符串(因为Python中没有字节(Byte)类型,可以把这里的字符串理解为字节流,或字节数组)。其函数原型为:struct.pack(fmt, v1, v2, …),参数fmt是格式字符串,关于格式字符串的相关信息在下面有所介绍。v1, v2, …表示要转换的python值。

2、 struct.unpack

struct.unpack做的工作刚好与struct.pack相反,用于将字节流转换成python数据类型。它的函数原型为:struct.unpack(fmt, string),该函数返回一个元组。
下面的例子将两个整数转换为字符串(字节流):

import struct

a = 20
b = 400
s = struct.pack('ii', a, b)
print(s, type(s))
#输出:b'\x14\x00\x00\x00\x90\x01\x00\x00' <class 'bytes'>
print('length: ', len(s))
#输出:length: 8
s2 = struct.unpack('ii', s)
print(s2)
#输出:(20, 400)

s2 = struct.unpack('ii', s)

报错:unpack requires a buffer of 4 bytes

==>解压需要一个4字节的缓冲区,也就是说’ii’表示8个字节的缓冲

格式符”i”表示转换为int,’ii’表示有两个int变量。

进行转换后的结果长度为8个字节(int类型占用4个字节,两个int为8个字节)

可以使用python的内置函数repr来获取可识别的字符串,其中十六进制的0x00000014, 0x00001009分别表示20和400。

3、 struct.calcsize

struct.calcsize用于计算格式字符串所对应的结果的长度,如:struct.calcsize(‘ii’),返回8。因为两个int类型所占用的长度是8个字节。

1 import struct
2 print "len: ", struct.calcsize('i') # len: 4
3 print "len: ", struct.calcsize('ii') # len: 8
4 print "len: ", struct.calcsize('f') # len: 4
5 print "len: ", struct.calcsize('ff') # len: 8
6 print "len: ", struct.calcsize('s') # len: 1
7 print "len: ", struct.calcsize('ss') # len: 2
8 print "len: ", struct.calcsize('d') # len: 8
9 print "len: ", struct.calcsize('dd') # len: 16

4、 struct.pack_into、 struct.unpack_from
这两个函数在Python手册中有所介绍,但没有给出如何使用的例子。其实它们在实际应用中用的并不多。Google了很久,才找到一个例子,贴出来共享一下:

1 #!/usr/bin/env python
2 #encoding: utf8
3
4 import sys
5 reload(sys)
6 sys.setdefaultencoding("utf-8")
7
8 import struct
9 from ctypes import create_string_buffer
10
11 buf = create_string_buffer(12)
12 print repr(buf.raw) # '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
13
14 struct.pack_into("iii", buf, 0, 1, 2, -1)
15 print repr(buf.raw) # '\x01\x00\x00\x00\x02\x00\x00\x00\xff\xff\xff\xff'
16
17 print struct.unpack_from("iii", buf, 0) # (1, 2, -1)

struct 类型表

FormatC TypePython typeStandard sizeNotes
xpad byteno value
ccharstring of length 11
bsigned charinteger1(3)
Bunsigned charinteger1(3)
?_Boolbool1(1)
hshortinteger2(3)
Hunsigned shortinteger2(3)
iintinteger4(3)
Iunsigned intinteger4(3)
llonginteger4(3)
Lunsigned longinteger4(3)
qlong longinteger8(2), (3)
Qunsigned long longinteger8(2), (3)
ffloatfloat4(4)
ddoublefloat8(4)
schar[]string1
pchar[]string
Pvoid *integer(5), (3)

一个python读取二进制文件,然后经过一系列变换重新写入文件:

import struct
with open("flagout","rb") as f:
              readbuf=f.read(3914)#3914=len(f.read())
              data=struct.unpack("3914B",readbuf)                     
#print(data)
listbuf=[]
for i in data:
              i+=10
              i^=0x12
              listbuf.append(i&0xff)#有溢出
#print(listbuf)
with open('out', 'wb')as fp:
    for x in listbuf:
        a = struct.pack('B', x)
        fp.write(a)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值