我正在制作一个文本编辑器,并且为了编辑文件,我真的需要某种方式来只读取文件中的某些字节,这是我使用fs.createReadStreamuisng start和endoptions实现的.
我还需要替换文件中的某些字节.我不确定如何做到这一点.到目前为止,我提出的最佳解决方案是使用流读取文件,然后写入新文件,当我遇到我正在寻找的字节时,我会编写新内容,从而替换旧的内容新的东西.
这可能不是最好的方法,你可能知道.要编辑4个字节,我正在读取一个巨大的2GB文件并编写2GB(假设我正在编辑2GB文件),至少效率不高.
实现这一目标的最佳方法是什么?我花了两周的时间做这个,我也想过使用Buffers,但是Buffers将整个文件加载到内存中,如果它是2GB的文件,这又是无效的.
如何在不读取整个文件的情况下更换文件中的某些字节,并且不安装一些具有C++代码的npm软件包.我不希望我的编辑器必须编译C++代码.
如果这样做并不简单,那么如何在不读取整个文件的情况下从文件中删除某些字节呢?如果我可以这样做,那么我可以删除要替换的字节,并使用类似的东西fs.write()来添加我想要替换的字节.
编辑#1:
玩弄后,我发现,如果我打开一个文件fs.open,旗r+,然后fs.write是替代的东西.所以,如果文字是"Lorem ipsum",我fs.write"!!!!" 结果将是"!!!! m ipsum".
如果我要编写的所有内容都是完美的长度,这样就可以正常工作.:/
我知道在新内容不是完美的长度的情况下该怎么办,但我不知道如何.:/也许如果有某种"空字节"......
编辑#2:
如上所述,fs.open(使用r+flags选项)+ fs.write允许我覆盖文件中的内容而不读取整个文件,这非常棒.现在,我遇到了一个新问题.我们来看以下文件:
one\n
two\n
three\n
Run Code Online (Sandbox Code Playgroud)
如果我fs.open在字节0然后fs.write"是",我最终得到:
yes\n
two\n
three\n
Run Code Online (Sandbox Code Playgroud)
如果我这样做,而是fs.write"niet",我最终得到:
niettwo\n
three\n
Run Code Online (Sandbox Code Playgroud)
注意如何\n字是用"T"所取代,这是因为如何fs.write使用时更换字节工程r+在fs.open.这是我现在想解决的问题.
一个会如何做这样的事情"从这个字节到该字节,这些其他字节替换"所以我的函数可以是这样function replaceBytes(filePath, newBytes, startByte, endByte)和那样只会从更换startByte到endByte,无论多久newBytes,不管是不是更短或更长的长度endByte - startByte.
编辑#3:
好的,我想出了新内容比正在被替换的旧内容更长的情况.谢谢\x00,我已经弄清楚了.如果新内容和旧内容的长度相同,那就不难理解,因为那里没什么可做的.
但旧内容比新内容短的情况仍然没有得到解决.
对于那些好奇的人来说,旧内容的工作代码比新内容更长:https://github.com/noedit/file/blob/592a35134440a03d3e3c3e366f6cda7f565c11aa/lib/replaceBytes.js#L27-L34
虽然它确实在那里放了一个空字节,这取决于编辑器,它可能会显示为一个字符,因此看起来很奇怪.:/
正如您所发现的,fs.write使用r+mode可以覆盖字节.这足以满足添加和删除的片段长度完全相同的情况.
当添加的文本比删除的文本短时,我建议您不要填写\x00字节,正如您在其中一个编辑中所建议的那样.这些在大多数类型的文件中都是完全有效的字符(在源代码中,它们通常会导致编译器/解释器抛出错误).
简短的回答是,这通常是不可能的.这不是一个抽象问题; 在文件系统级别,文件以连续字节的块存储.没有通用的方法来插入/删除文件的中间.
正确的方法是寻找你需要改变的第一个字节,然后写出文件的其余部分(除非你到达你添加/删除相同字节数的点,在这种情况下)你可以停止写作).
为了避免在长时间写入或类似事件期间崩溃的问题,通常写入临时文件位置,然后写入mv临时文件来代替要保存的实际文件.
| 归档时间: |
|
| 查看次数: |
1387 次 |
| 最近记录: |