------------------如何删除一个2G文件的前5行?-------------

雄牛 2017-06-19 12:40:11
我只想删除一个文件的前5行,再存储,但文件太大了...时间太久...
试了网上很多方法都不行,几百M的还行,但一到1GB就很慢很慢了..
有什么好办法吗?怎么改进

看了stackoverflow的几个方法效果都不太行
https://stackoverflow.com/questions/668907/how-to-delete-a-line-from-a-text-file-in-c

下面的是我现在用的代码


//删除前几行
private void removeTextLine(string filePath, Int32 LineCount)
{
List<string> lines = new List<string>(File.ReadAllLines(filePath, Encoding.Default));//先读取到内存变量
int x = 0;
while (x <= LineCount)
{
lines.RemoveAt(x);//指定删除的行
x++;
}
File.WriteAllLines(filePath, lines.ToArray(), Encoding.Default);//写回硬盤

}
...全文
673 23 打赏 收藏 转发到动态 举报
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
幻夢之葉 2017-06-27
  • 打赏
  • 举报
回复
引用 22 楼 liuyuehui110 的回复:
[quote=引用 20 楼 crystal_lz 的回复:] [quote=引用 19 楼 liuyuehui110 的回复:] [quote=引用 10 楼 cowbo 的回复:] 大虾,这个前5行,好像没去掉是什么原因. [quote=引用 1 楼 jianwen0529 的回复:]

            int LineCount = 5;
            StreamReader sr = File.OpenText(filePath);

            long offset = 0;
            while(LineCount-- > 0 )
                offset += sr.ReadLine().Length;
            sr.Close();

            FileStream fsr = File.OpenRead(filePath);
            FileStream fsw = File.OpenWrite("E:\\1.txt");

            fsr.Seek(offset, SeekOrigin.Begin);

            byte [] buf = new byte[102400];
            int realCount;
            while((realCount = fsr.Read(buf, 0, 102400)) > 0)
                fsw.Write(buf, 0, realCount);

            fsr.Close();
            fsw.Close();
// Win64, 四核 3.1GHZ, 4GB
// 文件大小:2.30G,运行时间:79s
[/quote] 写的有点乱[/quote] 不是有点乱 是直接就有问题的代码 offset += sr.ReadLine().Length; 按照他的逻辑offset是偏移的字节数 而ReadLinet().Length是一行文本长度的字符数 文本的字符个数=字节数?情感一个汉字也是1字节?而且就算文本里面全是英文 那么问题来了 只计算了字符(他所谓的字节)的个数 那么换行符所占用的字节不用计算到偏移里面去?[/quote] 没错![/quote] 逻辑是有很严重的问题,甚至错误处理不好 不过说乱的,还望指教 除了LineCount是楼主的命名以外
crystal_lz 2017-06-22
  • 打赏
  • 举报
回复
而且楼主 我不知道你是去哪里抄来的代码 如果是小文件 你这样也就无所谓 如果是大文件按照你说的都上G了 你还全部一起ReadAllLines?你电脑内存是有多大啊。。。还不如一边ReadLine一边WriteLine。。。
crystal_lz 2017-06-22
  • 打赏
  • 举报
回复
引用 19 楼 liuyuehui110 的回复:
[quote=引用 10 楼 cowbo 的回复:] 大虾,这个前5行,好像没去掉是什么原因. [quote=引用 1 楼 jianwen0529 的回复:]

            int LineCount = 5;
            StreamReader sr = File.OpenText(filePath);

            long offset = 0;
            while(LineCount-- > 0 )
                offset += sr.ReadLine().Length;
            sr.Close();

            FileStream fsr = File.OpenRead(filePath);
            FileStream fsw = File.OpenWrite("E:\\1.txt");

            fsr.Seek(offset, SeekOrigin.Begin);

            byte [] buf = new byte[102400];
            int realCount;
            while((realCount = fsr.Read(buf, 0, 102400)) > 0)
                fsw.Write(buf, 0, realCount);

            fsr.Close();
            fsw.Close();
// Win64, 四核 3.1GHZ, 4GB
// 文件大小:2.30G,运行时间:79s
[/quote] 写的有点乱[/quote] 不是有点乱 是直接就有问题的代码 offset += sr.ReadLine().Length; 按照他的逻辑offset是偏移的字节数 而ReadLinet().Length是一行文本长度的字符数 文本的字符个数=字节数?情感一个汉字也是1字节?而且就算文本里面全是英文 那么问题来了 只计算了字符(他所谓的字节)的个数 那么换行符所占用的字节不用计算到偏移里面去?
  • 打赏
  • 举报
回复
引用 20 楼 crystal_lz 的回复:
[quote=引用 19 楼 liuyuehui110 的回复:] [quote=引用 10 楼 cowbo 的回复:] 大虾,这个前5行,好像没去掉是什么原因. [quote=引用 1 楼 jianwen0529 的回复:]

            int LineCount = 5;
            StreamReader sr = File.OpenText(filePath);

            long offset = 0;
            while(LineCount-- > 0 )
                offset += sr.ReadLine().Length;
            sr.Close();

            FileStream fsr = File.OpenRead(filePath);
            FileStream fsw = File.OpenWrite("E:\\1.txt");

            fsr.Seek(offset, SeekOrigin.Begin);

            byte [] buf = new byte[102400];
            int realCount;
            while((realCount = fsr.Read(buf, 0, 102400)) > 0)
                fsw.Write(buf, 0, realCount);

            fsr.Close();
            fsw.Close();
// Win64, 四核 3.1GHZ, 4GB
// 文件大小:2.30G,运行时间:79s
[/quote] 写的有点乱[/quote] 不是有点乱 是直接就有问题的代码 offset += sr.ReadLine().Length; 按照他的逻辑offset是偏移的字节数 而ReadLinet().Length是一行文本长度的字符数 文本的字符个数=字节数?情感一个汉字也是1字节?而且就算文本里面全是英文 那么问题来了 只计算了字符(他所谓的字节)的个数 那么换行符所占用的字节不用计算到偏移里面去?[/quote] 没错!
  • 打赏
  • 举报
回复
引用 10 楼 cowbo 的回复:
大虾,这个前5行,好像没去掉是什么原因. [quote=引用 1 楼 jianwen0529 的回复:]

            int LineCount = 5;
            StreamReader sr = File.OpenText(filePath);

            long offset = 0;
            while(LineCount-- > 0 )
                offset += sr.ReadLine().Length;
            sr.Close();

            FileStream fsr = File.OpenRead(filePath);
            FileStream fsw = File.OpenWrite("E:\\1.txt");

            fsr.Seek(offset, SeekOrigin.Begin);

            byte [] buf = new byte[102400];
            int realCount;
            while((realCount = fsr.Read(buf, 0, 102400)) > 0)
                fsw.Write(buf, 0, realCount);

            fsr.Close();
            fsw.Close();
// Win64, 四核 3.1GHZ, 4GB
// 文件大小:2.30G,运行时间:79s
[/quote] 写的有点乱
足球中国 2017-06-20
  • 打赏
  • 举报
回复
直接把前5行置为空呗。
真相重于对错 2017-06-20
  • 打赏
  • 举报
回复
使用内存映射文件、
绿领巾童鞋 2017-06-20
  • 打赏
  • 举报
回复
TXT文件?如果是软处理估计就只能 读取 删除 再另存为
雄牛 2017-06-19
  • 打赏
  • 举报
回复
可以了,但那个ReadLine()有时会出现判断错误,无法取完整行
雄牛 2017-06-19
  • 打赏
  • 举报
回复
大虾,这个前5行,好像没去掉是什么原因.
引用 1 楼 jianwen0529 的回复:

            int LineCount = 5;
            StreamReader sr = File.OpenText(filePath);

            long offset = 0;
            while(LineCount-- > 0 )
                offset += sr.ReadLine().Length;
            sr.Close();

            FileStream fsr = File.OpenRead(filePath);
            FileStream fsw = File.OpenWrite("E:\\1.txt");

            fsr.Seek(offset, SeekOrigin.Begin);

            byte [] buf = new byte[102400];
            int realCount;
            while((realCount = fsr.Read(buf, 0, 102400)) > 0)
                fsw.Write(buf, 0, realCount);

            fsr.Close();
            fsw.Close();
// Win64, 四核 3.1GHZ, 4GB
// 文件大小:2.30G,运行时间:79s
xuggzu 2017-06-19
  • 打赏
  • 举报
回复
1. 文件过大,想操作快,最直接方案就是硬件上解决。
2. 只考虑软件的话,而且编程相对方便,应考虑c++语言,因为它相对更快。
3. 具体代码操作应先定位,在采取字节块读取和存储,而不是按字符串方式操作,因为字符串操作是最慢的。
  • 打赏
  • 举报
回复
一个自定义的基于文件的存储,你应该有个比文本文件高级一些的自己的设计出来。 比如说你可以使用 abc0001.dat、abc0002.dat、abc0003.dat.......这样一系列的文件来保存数据,而不是仅仅使用一个单一的文件。那么删除数据插入数据就相对灵活了,因为只在一个文件中插入删除,或者只是(当插入数据非常巨大时)把文件重新编个号码(例如把0002改为0005,后边的文件编号依次增加)。你可以保证每一个小文件都不超过32M,而不是什么几百兆、甚至上G。 对于单一文件而言,你也可以将文件内容“分块儿”进行随机存取,每一块儿的前边几个字节分别表示“块儿号、块大小、已经使用的数据大小、链表下一个块儿号”。这样你读取“行”的时候就应该只是在这个“已经使用的数据大小”范围内来ReadLine,超过这个区间则应该将 Position 跳到下一个数据块儿去,才开始读数据。 总之,不是那么简单暴力就成,起码应该有一点点自己的设计技术在里边。
bloodish 2017-06-19
  • 打赏
  • 举报
回复
WinHex不知道楼主有没有用过? 超级强大的二进制文件编辑工具,采用文件内存映射的方式进行编辑处理. 它有API提供,所以可以试一下WinHex API. whxapidoc 但话说回来,从你要实现的功能来看,速度想要有数量级的提升还是有难度的.
xuzuning 2017-06-19
  • 打赏
  • 举报
回复
为什么数据库删除记录会很快呢? 是因为他并没有释放被删除记录所占据的硬盘空间,只是标记为自由空间。这样在之后的插入中,这些空间可能会被利用(如果规模相当的话) 由此可引申出:通过修改文件系统的文件信息中的初始磁盘偏移,就应该能达成你的需求
秋的红果实 2017-06-19
  • 打赏
  • 举报
回复
1# + 从第六行开始读取,然后直接存入目标文件,比你原来的省大约一半时间 另外,必须要这样做吗? 你将文件删除5行后,要怎么操作?可以直接读取文件到内存,然后替换掉前5行,或者直接从第6行开始“使用”,不就行了么 还有,如此大的数据,改用数据库,效率会提升不少,现有成熟的数据库,都提供了高效的使用机制,如查询,可以充分利用索引,提高效率,而且维护方便,比如你的问题,要在数据库了,在开头、中间任何部位,删除几条数据,也就几秒的事
by_封爱 版主 2017-06-19
  • 打赏
  • 举报
回复
txt没办法的 又不是数据库 .. 放弃吧
  • 打赏
  • 举报
回复
无论如何都是复制一遍整个文件的思路,这个设计机制也就是限于此。如果你要很好地管理数据(例如就象数据库文件那样),那么你必须有高级一点的知识,从头重新设计。
  • 打赏
  • 举报
回复
这种机制决定了,也就是哪种结果。
tanta 2017-06-19
  • 打赏
  • 举报
回复
一般出现这种问题都是设计上有问题。
幻夢之葉 2017-06-19
  • 打赏
  • 举报
回复

            int LineCount = 5;
            StreamReader sr = File.OpenText(filePath);

            long offset = 0;
            while(LineCount-- > 0 )
                offset += sr.ReadLine().Length;
            sr.Close();

            FileStream fsr = File.OpenRead(filePath);
            FileStream fsw = File.OpenWrite("E:\\1.txt");

            fsr.Seek(offset, SeekOrigin.Begin);

            byte [] buf = new byte[102400];
            int realCount;
            while((realCount = fsr.Read(buf, 0, 102400)) > 0)
                fsw.Write(buf, 0, realCount);

            fsr.Close();
            fsw.Close();
// Win64, 四核 3.1GHZ, 4GB
// 文件大小:2.30G,运行时间:79s
加载更多回复(3)

110,536

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧