如何修改一个大文件? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Distributions
Ubuntu
Fedora
CentOS
中文资源站
网易开源镜像站
join
V2EX    Linux

如何修改一个大文件?

  •  
  •   join
    leyafo 2021-06-01 19:54:31 +08:00 3908 次点击
    这是一个创建于 1654 天前的主题,其中的信息可能已经有所发展或是发生改变。
    假设我有一个 1G 的大文件,我要修改中间某个地方的 1 个 byte,这个时候可以用 file.seek 定位到具体的位置,再用 append 模式写。
    但如果我要删除一段内容,再添加一段新的内容呢?(内容的长度不确定),这个时候是怎么做的?
    一个编辑器如何做到这个功能?
    一个像 sqlite 这样涉及到大量读写的数据库系统又是如何做到的?
    照 posix 现有的 api 来看要么只能全读内存再调用 fsync 写入。或者用 mmap 这种底层的 api 提高写入速度。有相关的书籍介绍这个问题的吗?
    19 条回复    2021-06-03 00:58:43 +08:00
    join
        1
    join  
    OP
       2021-06-01 20:01:14 +08:00
    WAL 是不是解决这个问题用的?
    no1xsyzy
        2
    no1xsyzy  
       2021-06-01 22:18:35 +08:00
    从块文件的层面去考虑的话,长度改变后面的全部都要重新写一遍。
    文件系统可能允许文件分为多个块或者簇,它们可以变长的话可能可以解决。
    sqlite 说是有并发问题的…… 应当也是全读全写?可能有 padding 空间?可能允许乱序?
    lululau
        3
    lululau  
       2021-06-01 22:21:00 +08:00
    做不到,文本编辑器要么是重新写一遍,要么是用一个新文件替换到原有文件
    join
        4
    join  
    OP
       2021-06-01 22:24:18 +08:00
    @lululau 感谢,我纠结了一天也没在网上找到合适的方案。原来的确是我的想法有问题。
    XiaoxiaoPu
        5
    XiaoxiaoPu  
       2021-06-01 22:58:12 +08:00
    数据库会尽量避免改变长度。可以看下 LSM 树的原理,将磁盘随机写操作转化为顺序写操作,相比 B+树的存储结构好理解一些。
    coldear
        6
    coldear  
       2021-06-02 02:54:08 +08:00
    长度不确定没发 in place, 关系型数据库都字段都是固定长度的。
    mingl0280
        7
    mingl0280  
       2021-06-02 03:12:17 +08:00
    数据库原理没有学好就是这样的。
    数据库文件本身内部会有数据库软件的分页,每个分页的长度固定,然后数据库软件会在文件前部保持一个对页的索引,这样数据库的 IO 就只需要读写一个页(如果不够长会重新分配页,一般在文件尾部直接增长)。效率比重写一大截文件好很多。
    但是,如果你是一个普通的二进制文件,那么你只能把后半截保存下来然后删掉重写……
    kokutou
        8
    kokutou  
       2021-06-02 07:06:15 +08:00 via Android
    有个办法是长度对齐,空余的填 0 。
    然后写入就是一块一块的写入。自己计算末尾 0 的个数。

    有的游戏存档是这样做的,虽然没到 1g 这么大,但是这样都是相同长度,应该是因为程序写起来方便吧。
    join
        9
    join  
    OP
       2021-06-02 08:55:14 +08:00 via iPhone
    @mingl0280 是的,感谢指点。我确实这块没学好,赶紧学习去。如果按你这样说的,sqlite 岂不是数据库越大,性能越差?但看起来好像不是这样的,他们也没用 lsm,只是用 b 树。
    join
        10
    join  
    OP
       2021-06-02 08:56:12 +08:00 via iPhone
    @kokutou 这个还是会越写越慢吧?中间插入后面全部要改。
    jorneyr
        11
    jorneyr  
       2021-06-02 10:22:32 +08:00
    sqlite 之类的,创建一个大一些的文件,写入的数据都是从文件中预定一段然后写入,并不是顺序的写入。
    kokutou
        12
    kokutou  
       2021-06-02 11:03:17 +08:00 via Android
    @join 是一段固定长度的 0,写入的时候就写这么长,覆盖写入。
    sxw
        13
    sxw  
       2021-06-02 15:44:08 +08:00
    @join 可以用 "r+" 打开文件,seek 到要修改的地方。https://es2q.com/blog/2019/02/22/modify_file_without_rewrite/
    join
        14
    join  
    OP
       2021-06-02 16:58:19 +08:00 via iPhone
    @sxw 仔细再看各位大佬的讨论,这个问题没那么简单的。
    sxw
        15
    sxw  
       2021-06-02 17:02:36 +08:00
    @join 抱歉没写清楚,我回复的是 #10
    liuxu
        16
    liuxu  
       2021-06-02 21:12:28 +08:00
    1 个 G 不是大文件吧,现在内存条再怎么涨价也就 300 块钱 8G,买一个插上
    mingl0280
        17
    mingl0280  
       2021-06-02 22:18:59 +08:00 via Android
    @join SQLite 数据库确实越大性能越差,不知道你这个看起来不是这样是哪来的……BTree 就是维护的 Pager 索引,也不知道你说的只用 b 树是哪来的。
    join
        18
    join  
    OP
       2021-06-02 23:52:09 +08:00 via iPhone
    @mingl0280 不是抬杠,官网说了最大支持 10tb,他们也确实用的是 b tree 。
    @liuxu 写代码不能有这种想法,万一是 10g 100g 1t 的文件呢?
    liuxu
        19
    liuxu  
       2021-06-03 00:58:43 +08:00
    @join 万一 1PB 呢
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5404 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 31ms UTC 01:49 PVG 09:49 LAX 17:49 JFK 20:49
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86