aiaify 2020-04-25 17:56 采纳率: 100%
浏览 899
已采纳

如何对单个二进制文件中指定位置的流进行替换或者删除?

限制条件:
1.不能把整个文件所有内容直接读取到内存后拼接重组(文件较大)
2.替换内容长度大于被替换内容

目标示例:
如文件原内容为**12356**,现在要将position位置为4的'3'替换为'34'使最终结果为**123456**,或者删除'3'使最终结果为**1256**。

注:
1.* 意为任意的二进制值
2.希望获取C++或者C#的解决方法代码,有明确解决思路亦可

  • 写回答

3条回答 默认 最新

  • threenewbee 2020-04-25 23:41
    关注

    如果替换内容长度>或者<原来的长度。那么,无论你用什么语言,用什么算法,最优化的情况,需要把修改点到文件结尾的文件重新覆盖重写一遍。
    因为文件是连续存储在磁盘上的。
    如果你可以自己定义文件的格式(也就是说你的文件只由你的程序读取,而不是被别的程序读取),你可以考虑使用链式存储或者稀疏存储,使得替换内容的操作变得高效(代价是浪费一部分存储)
    先把原则和你说清楚。
    如果你需要写程序,可以写给你。

    代码还有一些问题,正在改

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.IO;
    namespace Q1065402
    {
        class MyLinkedFile : IDisposable
        {
            private const int EOF = -1;
            private const int BOF = 0;
            private FileStream fs = null;
            private string filename;
            private int curr = 0;
    
            private byte[] MakeBytes(int pre, int next, int value)
            {
                return BitConverter.GetBytes(pre).Concat(BitConverter.GetBytes(next)).Concat(BitConverter.GetBytes(value)).ToArray();
            }
            private void parseBytes(byte[] arr, out int pre, out int next, out int value)
            {
                pre = BitConverter.ToInt32(arr, 0);
                next = BitConverter.ToInt32(arr, 4);
                value = BitConverter.ToInt32(arr, 8);
            }
    
            public MyLinkedFile(string fn)
            {
                if (!File.Exists(fn))
                    File.WriteAllBytes(fn, MakeBytes(BOF, EOF, 0));
                fs = new FileStream(fn, FileMode.OpenOrCreate);
                filename = fn;
            }
    
            public IEnumerable<int> ReadAll()
            {
                int pre = 0;
                int next = 0;
                int value = 0;
                curr = -1;
                fs.Position = 0;
                byte[] data = new byte[12];
                fs.Read(data, 0, 12);
                parseBytes(data, out pre, out next, out value);
                while (true)
                {
                    if (next == EOF) break;
                    curr++;
                    fs.Position = next * 12;
                    fs.Read(data, 0, 12);
                    parseBytes(data, out pre, out next, out value);
                    yield return value;
                }
            }
    
            private void moveToBegin()
            {
                foreach (var item in ReadAll().Take(1)) ;
            }
    
            public void moveToEnd()
            {
                foreach (var item in ReadAll());
            }
    
            public void Append(int val)
            {
                int pre = 0;
                int next = 0;
                int value = 0;
                byte[] data = new byte[12];
                fs.Read(data, 0, 12);
                parseBytes(data, out pre, out next, out value);
                fs.Position -= 12;
                fs.Write(MakeBytes(pre, (int)(fs.Length / 12), value), 0, 12);
                pre = (int)fs.Position / 12;
                fs.Position = fs.Length;
                fs.SetLength(fs.Length + 12);
                fs.Write(MakeBytes(pre, next, val), 0, 12);
                curr++;
            }
    
            public void Dispose()
            {
                if (fs != null)
                {
                    fs.Close();
                    fs.Dispose();
                    fs = null;
                    filename = "";
                }
            }
        }
        class Program
        {
            static void Main(string[] args)
            {
                using (MyLinkedFile lf = new MyLinkedFile(@"c:\1.bin"))
                {
                    lf.moveToEnd();
                    lf.Append(21);
                    lf.Append(22);
                    lf.Append(23);
                    //foreach (var item in lf.ReadAll())
                    //    Console.WriteLine(item);
                }
            }
        }
    }
    
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥15 扩散模型sd.webui使用时报错“Nonetype”
  • ¥15 stm32流水灯+呼吸灯+外部中断按键
  • ¥15 将二维数组,按照假设的规定,如0/1/0 == "4",把对应列位置写成一个字符并打印输出该字符
  • ¥15 NX MCD仿真与博途通讯不了啥情况
  • ¥15 win11家庭中文版安装docker遇到Hyper-V启用失败解决办法整理
  • ¥15 gradio的web端页面格式不对的问题
  • ¥15 求大家看看Nonce如何配置
  • ¥15 Matlab怎么求解含参的二重积分?
  • ¥15 苹果手机突然连不上wifi了?
  • ¥15 cgictest.cgi文件无法访问