http://www.sufeinet.com/plugin.php?id=keke_group

苏飞论坛

 找回密码
 马上注册

QQ登录

只需一步,快速开始

分布式系统框架(V2.0) 轻松承载百亿数据,千万流量!讨论专区 - 源码下载 - 官方教程

HttpHelper爬虫框架(V2.7-含.netcore) HttpHelper官方出品,爬虫框架讨论区 - 源码下载 - 在线测试和代码生成

HttpHelper爬虫类(V2.0) 开源的爬虫类,支持多种模式和属性 源码 - 代码生成器 - 讨论区 - 教程- 例子

查看: 10966|回复: 4

[其他] 如何用C# 修改一个exe 或者其它二进制文件指定位置的指定内容

[复制链接]
发表于 2013-8-30 16:45:14 | 显示全部楼层 |阅读模式
请问如何用C# 修改一个exe 或者其它二进制文件指定位置的指定内容,比如某个二进制文件的某处为00 05 E1 D5 我想把它改成别的内容!!!


1. 开通SVIP会员,免费下载本站所有源码,不限次数据,不限时间
2. 加官方QQ群,加官方微信群获取更多资源和帮助
3. 找站长苏飞做网站、商城、CRM、小程序、App、爬虫相关、项目外包等点这里
发表于 2013-8-30 17:01:23 | 显示全部楼层
[code=csharp]        string path = Application.StartupPath + "\\data.db";//二进制文件路径
        private void button1_Click(object sender, EventArgs e)//存为文件
        {
            Person per = new Person() { name = "文文lele", age = 12, height = 1.50 };//实例化一个数据

            Stream st = new FileStream(path, FileMode.Create);
            BinaryWriter bw = new BinaryWriter(st);
            bw.Write(per.age);//先int
            bw.Write(per.name);//再string
            bw.Write(per.height);//最后double
            bw.Close();
            st.Close();
        }

        private void button2_Click(object sender, EventArgs e)//读取文件
        {
            Stream st = new FileStream(path, FileMode.Open);
            BinaryReader br = new BinaryReader(st);

            Person pr = new Person();//一个未被具体指明的

            pr.age = br.ReadInt32();//先int
            pr.name = br.ReadString();//再string
            pr.height = br.ReadDouble();//最后double
            textBox1.Text = pr.ToString();//最后文本框会显示:名字:文文lele\r\n年龄:12\r\n身高1.50
            br.Close();
            st.Close();
        }
    }

    class Person
    {
        public string name { set; get; }
        public int age { set; get; }
        public double height { set; get; }
        public override string ToString()
        {
            return "名字:" + name.ToString() + "\r\n年龄:" + age.ToString() + "\r\n身高:" + height.ToString();
        }
    }[/code]

如果想要使用Stream的long Seek(int Offset,SeekOrigin origin)函数来设置从哪开始读,则读取的代码应该改为如下:
[code=csharp]        private void button2_Click(object sender, EventArgs e))//读取文件
        {
            Stream st = new FileStream(path, FileMode.Open);
            BinaryReader br = new BinaryReader(st);

            Person pr = new Person();//一个未具体化的例子

            st.Seek(4, SeekOrigin.Begin);//因为二进制文件中存储的第一个是32位的年龄(整型默认32位),占4字节,所以名字从第4字节开始(8位为1字节,32位即4字节)
            pr.name = br.ReadString();

            st.Seek(0, SeekOrigin.Begin);//年龄记录在开始处
            pr.age = br.ReadInt32();

            st.Seek(-8, SeekOrigin.End);//身高是64位的双精度浮点型,占8字节,放在最后,所以从后往前数8个字节
            pr.height = br.ReadDouble();
            textBox1.Text = pr.ToString();//最后文本框会显示:名字:文文lele\r\n年龄:12\r\n身高1.50和第一种方法没有变
            br.Close();
            st.Close();
        }[/code]
两种读法或得相同的效果,这里为了使string类型长度固定可以放在最后,也可以使用StringBuilder建立指定长度字符串。








发表于 2013-8-30 17:03:00 | 显示全部楼层

平常我们使用文件存储程序数据时,一般需要将数据转换为文本等存储,等到需要使用的时候再从文件读取,然后重新构建类或结构或数组等对象。这样的转换和重建即浪费了时间效率不够高又导致容易出错,其实最近由于研究二进制文件的存取,我找到了序列化存取的方法。

序列化存取可以做到类对象、结构、数组等内存实体整体保存为二进制的文件,而不需转换,读取的时候,通过反序列化直接从文件构建对象,而不需要重新通过转换而来的数据构建,这样既节省了转换时间,运行速度又比较快。

简要说明一下,序列化主要是通过实现System.Runtime.Serialization.IFormatter接口的System.Runtime.Serialization.Formatters.Binary.BinaryFormatter类来实现的,其中的void  Serialize(Streamst, object ob)来实现序列化,这个函数就可以将object对象ob序列化为二进制流输入给Stream流st,这个方法有重载,具体看MSDN,但对于我们只想简单序列化,这样写也就够了。object Deserialize(Stream st)这个方法可以实现反序列化,从给定的Stream流st中反序列化出一个object对象,只需强制转换为目标对象就可以了。

为了说明问题,新建了一个示例工程(winForm程序),就一个界面,实现一个类的存和取如下(如果要序列化存储结构和数组只需要将Person对象换成相应对象即可,另外设计器自动生成的代码没有贴出来):

20130717001421140.jpg


20130717001823531.jpg



[code=csharp]using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace 序列化的二进制文件存取
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        
        /// <summary>
        /// 存储文件位置
        /// </summary>
        public static string savePath = "序列化存储文件.data";//指定存储在程序启动文件夹下的"序列化存储文件.data"内

        /// <summary>
        /// 存
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button_Save_Click(object sender, EventArgs e)
        {
            //新建Person类对象
            Person newPerson = new Person();
            newPerson.name = textBox_name.Text;
            newPerson.age = Convert.ToInt32(textBox_age.Text);
            newPerson.grade = Convert.ToInt32(textBox_grade.Text);

            //这个对象用于序列化对象
            System.Runtime.Serialization.Formatters.Binary.BinaryFormatter binaryFormatter
                = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
            ////或者用这个接口创建实例也可以
            //System.Runtime.Serialization.IFormatter binaryFormatter
            //    = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();

            ////序列化person对象newPerson,先转化为二进制再存为文件
            //System.IO.MemoryStream ms = new System.IO.MemoryStream();
            //binaryFormatter.Serialize(ms, newPerson);
            //byte[] buffer = ms.GetBuffer();
            //System.IO.Stream st = new System.IO.FileStream(savePath, System.IO.FileMode.Create);
            //st.Write(buffer, 0, buffer.Length);
            //st.Close();

            //序列化person对象newPerson并存为文件
            System.IO.Stream st = new System.IO.FileStream(savePath, System.IO.FileMode.Create);//新建文件流
            binaryFormatter.Serialize(st, newPerson);//序列化类对象,并输入流
            st.Close();            
        }

        /// <summary>
        /// 取
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button_Read_Click(object sender, EventArgs e)
        {
            //这个对象用于反序列化对象
            System.Runtime.Serialization.Formatters.Binary.BinaryFormatter binaryFormatter
                = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();

            //浏览存储的对象文件
            OpenFileDialog op=new OpenFileDialog(){Filter="PerSon类文件(*.data)|*.data",InitialDirectory=Application.StartupPath};
            op.ShowDialog();

            if (System.IO.File.Exist(op.FileName))//如果浏览到文件
            {
                System.IO.Stream st = new System.IO.FileStream(op.FileName, System.IO.FileMode.Open);//指向数据文件的二进制流
                Person per = (Person)binaryFormatter.Deserialize(st);//反序列化,得到的是一个object对象,需要强制转换
                textBox_Show.Text = per.ToString();//显示对象信息
                st.Close();
            }
            else
                textBox_Show.Text = "没有相关文件!";
        }
    }

    /// <summary>
    /// 类示例
    /// </summary>
    [Serializable]//加上这个属性后此类创建的对象才能被序列化
    class Person
    {
        public string name { set; get; }
        public int age { set; get; }
        public int grade { set; get; }
        public override string ToString()
        {
            return "名字:" + name.ToString() + "\r\n年龄:" + age.ToString() + "\r\n年级:" + grade.ToString();
        }
    }
}
[/code]


 楼主| 发表于 2013-9-3 16:07:37 | 显示全部楼层
太感谢了!!!
回复

使用道具 举报

发表于 2013-9-4 10:04:16 | 显示全部楼层
yangying 发表于 2013-8-30 17:03
平常我们使用文件存储程序数据时,一般需要将数据转换为文本等存储,等到需要使用的时候再从文件读取,然后 ...

学习了
您需要登录后才可以回帖 登录 | 马上注册

本版积分规则

QQ|手机版|小黑屋|手机版|联系我们|关于我们|广告合作|苏飞论坛 ( 豫ICP备18043678号-2)

GMT+8, 2024-5-2 04:38

© 2014-2021

快速回复 返回顶部 返回列表