导航:
论坛 -> DELPHI技术
斑竹:liumazi,sephil
作者:
dalas (dalas)
★☆☆☆☆
-
普通会员
2021/4/30 22:12:54
标题:
请教一个12GB的文本文件替换换行符
浏览:4283
加入我的收藏
楼主:
Linux 上导出的单文件 12GB 的文本文件,2000万行,UTF-8编码,换行符 0A,需转换为 ANSI编码,同时把换行符替换为 0D0A。 求一个高效转换的代码,可以是vbs或delphi,谢谢!!
----------------------------------------------
-
作者:
2021/4/30 23:06:26
1楼:
方案: 1.试用内存映射 CreateFileMapping 加载大文件 2.读取一段 操作一段 操作完成写入另一个文件 猜测可以在5分钟内完成。
----------------------------------------------
-
作者:
2021/4/30 23:13:11
1楼:
这需求,执行效率基本取决于你的硬盘读写速度,以及你有多少内存可以挥霍。 另外,如果UTF-8的文本文件内只有英文字符,那么可以不用做编码转换;否则就需要先转Unicode然后再转Ansi。
----------------------------------------------
-
作者:
dalas (dalas)
★☆☆☆☆
-
普通会员
2021/4/30 23:42:20
2楼:
@xiaobaosoft (小宝软件) 可以给个例子吗? @scarlette (Scarlette) 文件内容是中英文都有。
----------------------------------------------
-
作者:
dalas (dalas)
★☆☆☆☆
-
普通会员
2021/5/1 0:00:32
3楼:
内存映射不大会用,似乎只能读和替换内容,不能插入字符,换行符由0A替换为0D0A,就需要插入一个字符0D。 如果替换后写入新文件,在创建映射时要指定大小,我又无法预先知道转换后的文件大小。 想不出什么好办法。
----------------------------------------------
-
作者:
lsuper (lsuper)
★☆☆☆☆
-
盒子活跃会员
2021/5/1 0:27:32
4楼:
1、这个必然涉及大量文件 io,时间空间不好省 2、建议思考:为啥要替换?如果只是显示或数据转换,加载时转换即可,类似各种 log 查看软件,如 tail 的处理方式
----------------------------------------------
-
作者:
dalas (dalas)
★☆☆☆☆
-
普通会员
2021/5/1 0:47:27
5楼:
这数据是要装入另一个系统的,那边接口,指定了这种数据格式,不然不认,所以得先转换了再丢给它,哭死.... 编码的问题倒不大,linux上导出时,可以指定GB2312,但换行我搞不定,无法导成0D0A这种,只能拿到txt后,再做处理。 文件可以在服务器上处理,磁盘、内存空间不是问题,就是算法上提高点效率,处理速度快些,目前我用VBS写了个转换的脚本,跑到几小时也跑不出来。
----------------------------------------------
-
作者:
2021/5/1 0:58:55
6楼:
@dalas 例子没有。读取用映射 写出不需要啊。写出就正常写。
----------------------------------------------
-
作者:
2021/5/1 22:10:55
7楼:
可以充分利用服务器多核大内存的处理能力,第一步将数据断行存到一个utf8编码的数组里,第二步,utf8转ansi, 启动并发处理,把cpu多核跑满,把utf8编码数组转换为ansi编码数组,第三步,讲数组用0D0A拼接成单个文件。 编程语言推荐用Rust, 第二步用async/await编写并行代码。 代码编写很容易,没有实际数据,不清楚转换需要多少时间。
----------------------------------------------
-
作者:
2021/5/1 22:17:46
8楼:
没必要把所有数据全部读入内存,可以分片处理,读一段,转换一段,写一段
----------------------------------------------
-
作者:
msdtx (yong)
★☆☆☆☆
-
普通会员
2021/5/2 10:13:02
9楼:
有象形文字会比较烦,如果没有就会很好处理。
----------------------------------------------
-
作者:
2021/5/3 23:09:33
10楼:
按前面的思路编写了个测试程序, 转换10G的数据只需要2分钟,三星960Pro高速固态硬盘64G内存,CPU i9-9900T,Win10 64位
----------------------------------------------
-
作者:
2021/5/3 23:16:04
11楼:
程序运行需要VC++2019Runtime DLL, 请自行网上查找。
此帖子包含附件: 大小: 171.6K
----------------------------------------------
-
作者:
2021/5/3 23:38:58
12楼:
windowd版的exe已经免费提供,没有任何功能限制。楼主如果对源代码感兴趣,可以有偿提供。源代码支持多平台,应该可以编译为Linux下的执行文件。另外,我前期做了一个多路并用的XCOPY,对于大文件搬家提速显著。
----------------------------------------------
-
作者:
2021/5/3 23:57:55
13楼:
上icu吧。。 转码我就记得icu
----------------------------------------------
[alias] co = clone --recurse-submodules up = submodule update --init --recursiveupd = pullinfo = statusrest = reset --hard懒鬼提速https://www.cctry.com/ >http://qalculate.github.io/downloads.htmlhttps://www.cctry.com/
作者:
2021/5/4 8:41:38
14楼:
EmEditor 了解下。
----------------------------------------------
相信自己,若自己都不相信,那还有谁可信。
作者:
2021/5/5 8:23:12
15楼:
目前最快的速度
此帖子包含附件: 大小: 157.1K
----------------------------------------------
-
作者:
2021/5/5 8:25:46
16楼:
附件中是windows 64位的exe文件,第三个参数是缓冲区大小
----------------------------------------------
-
作者:
2021/5/6 11:47:02
17楼:
Delphi 代码实现的话,可以考虑: 1. 千万不要全部加载后处理。光是把 128G 文件读入内存就要好多时间。 2. 读一行,处理一行。 3. 处理完一行,写入另外一个文件。 4. 综上,就是个文件读和文件写的操作。 5. 如果 CPU 多,可以使用 Delphi 的并行处理算法框架。 5.1. 并行处理不熟习的话,直接上多线程。当然,单CPU用多线程也没有意义。 5.2. 并行或者多线程,需要一个中间交换的变量,用于记录当前应该处理第几行,这个变量因为多个线程都要去读和写,因此需要用临界区保护起来。 到这里,基本上应该就能处理完,并且代码也很简单,并不复杂。
----------------------------------------------
-
作者:
2021/5/6 11:52:43
18楼:
我觉得可以更快,主要差异在磁盘IO处理这块 理论上即便是传统硬盘10秒也可以可以读一遍了,写入的话也就几十秒吧。 要是NVME的固态硬盘理论读写速度也就1-2秒,我自己的磁盘测试数据是1.5G每秒写入,读得更快。
----------------------------------------------
武稀松http://www.raysoftware.cn
作者:
2021/5/6 12:59:08
19楼:
不需要转换编码的情况下,只替换0A为ODOA。linux下使用unix2dos命令处理试试。
----------------------------------------------
-
作者:
2021/5/6 16:52:04
20楼:
楼主度假去了?程序都给您写好了,何不拿去跑一跑? 顺便贴一下用Rust写的另一个软件:Filer高速文件分发系统, 需要的可以找我。
此帖子包含附件: 大小: 725.0K
----------------------------------------------
-
作者:
2021/5/7 10:22:15
21楼:
楼上的拿 Rust 到 Delphi 的地方踢场子?
----------------------------------------------
-
作者:
2021/5/7 10:59:20
22楼:
亲,咱也是Delphi的老粉了,用Delphi写了20多年的程序。不过,楼主这活用Rust来写最适合。把一个12G的linux utf8格式的文本转换为Windows ANSI(GBK)格式文件在我的电脑上耗时不到2分钟。 Delphi目前仍有竞争力的场景就剩下写Windows下的GUI程序,继续使用VCL, FireMonkey是个鸡肋,搭配宇宙第一的报表控件FastReport,强大无敌。 写WebServer让位给Rust, 写网页前端让位给svelte。 Delphi语言特征(编译器)这些年一直没有什么进步,面对多核心多线程主流硬件环境,在强大的现代语言(Rust,Go)面前弱爆了。
----------------------------------------------
-
作者:
2021/5/7 12:43:56
23楼:
搞性能先要知道瓶颈在哪里:cpu 内存 主板IO性能 硬盘 这4个里面一般硬盘是瓶颈 如果内存够大,做个内存虚拟磁盘,把文件拷贝过去,程序读一部分、写一部分、删一部分,最后再拷贝出来,已经够快的了 “最”快就得针对操作系统、硬件,往往不具有通用性,差不多得了。
----------------------------------------------
软件是什么,相信很多人都说不清。
作者:
2021/5/7 17:51:35
24楼:
22 楼,看了一下 svelte 的介绍,也就是个前端代码框架。这种框架,和 VCL 比较如何?有没有那么多现成的控件可以用?
----------------------------------------------
-
作者:
2021/5/7 19:29:28
25楼:
程序进一步优化,现在转换一个12G的文件从1分半钟减少到20秒
----------------------------------------------
-
作者:
2021/5/7 19:38:49
26楼:
回24楼: svelte是一个平台,可以与各种框架组合使用,在前端css框架中我推荐bulma, 数据表格我推荐ag-grid, 需要扫描二维码,可以调用Wasm, 这其中zbar就很好用,识别效果堪比微信。用svelte写界面的效率完爆VCL, 做出来的效果好多也是VCL很难实现的,比如动画,多媒体,支持手机等等。
此帖子包含附件: 大小: 289.4K
----------------------------------------------
-
作者:
2021/5/7 22:45:14
27楼:
有时并不一定非要自己搞,提供另外的思路,既然在linux上导出,多做一步是否也行呢?“iconv”,“unixtodos”,还有有些导入工具是可以配置行的末尾是dos格式还是unix格式的,仅仅是个思路。因为若十年前曾经搞过把文本文件批量导入到数据库,当时就是这么处理的。
----------------------------------------------
-
作者:
2021/5/7 23:16:08
28楼:
哈哈😊😄,自己写段代码图个乐,测试一下Rust多线程代码,把CPU跑满极限速度能有多快。
----------------------------------------------
-
作者:
dalas (dalas)
★☆☆☆☆
-
普通会员
2021/5/9 2:56:42
29楼:
谢谢大家,我的问题解决了,编码的问题可以在导出时指定。 换行符的问题,在导入时,平时是用"\n",改成"0x0A"就可以完美解决,连替换都省了。 c5soft 的程序我也有试了一下,转换速度是挺快的,但中文转换后用UE打开会乱码,后来试了个小文件,转换后用记事本打开,不会乱码,但回到UE打开,还是乱码。 记事本另存一下ANSI,再用UE打开,就不会乱码。 这段时间挺忙,做主数据,要写很多代码导数据。
----------------------------------------------
-
作者:
hexi (Hexi)
★☆☆☆☆
-
盒子活跃会员
2021/5/12 0:07:55
30楼:
to c5soft: 我曾经用Delphi多线程处理一个8GB的文本,也只要10几秒。 一个线程负责读取数据块,CPU核数个线程负责处理数据块。 处理工作比转换个回车换行复杂。需要把文本字符串转换为整数,每个字符串以逗号隔开。
----------------------------------------------
-
作者:
2021/5/12 14:25:52
31楼:
回:hexi 前面的程序不只是转换个回车换行,是将文本编码从utf8转换为ANSI,ANSI中文编码是GB18030(向下兼容GBK与GB2312), 每个汉字utf8是三个字节,GB18030(GBK)是两字节,12G的utf8转换为Ansi (CP936)得到8GB大小的文件。 Delphi与Rust都属于没有垃圾回收机制的Native Code编程语言,都可以镶入汇编,在性能上应该有一比,更多的性能压榨可能取决于算法。 在多线程编程能力/处理效率这个维度上看,Rust比Delphi更有优势,Rust除了Thread外有async/await, Delphi只有Thread。Rust最大的优势还在于内存安全:编译器帮你写出没有内存非法读写的代码。从Delphi的角度看,就是您只需要写 a=TSomething.create, 不需要写a.free, 编译器会帮你加上。 Rust是面向未来的语言,是全栈语言,什么都能干。这是一门让程序员爱不释手的编程语言。
----------------------------------------------
-
作者:
2021/5/18 12:20:37
32楼:
{ 读写文件都可以指定编码,不用自己考虑转码问题。 写文件换行符自己指定,不要用WriteLN。 循环读一行写一行。 我最大只有大概5到6GB的文本,磁盘也没楼上那么快。。。 并且我实际情况是从“GBK”转到“UTF8”,从“回车换行”转为“换行”。 PS: Windows通常是回车换行:#13#10 = 0D0A = CRLF UNIX/Linux通常是换行: #10 = 0A = LF MAC OS:不想说它……居然单回车。。。 代码供参考: } procedure TransCode(FIn,FOut:String;CodePageIn,CodePageOut:Integer;OutLineBreak:String); var aOutputFile:TextFile; aOutputBuffer: array[1..32*1024] of byte; aInputfile :TextFile; aInputBuffer: array[1..32*1024] of byte; Aline:String; begin AssignFile(aOutputFile,FOut,CodePageOut); Rewrite(aOutputFile); System.SetTextBuf(aOutputFile,aOutputBuffer); AssignFile(aInputfile,FIn,CodePageIn); Reset(aInputfile); System.SetTextBuf(aInputfile,aInputBuffer); while not EOF(aInputfile) do begin ReadLn(aInputfile,Aline); // return or newline will no longer in Aline. Write(aOutputFile,Aline+OutLineBreak); end; end; procedure TForm1.Button1Click(Sender: TObject); begin //936 means GB18030(GBK,GB2312) //65001 means UTF8 //add your own line break. //#13 is return, #10 is newline. TransCode(Edit1.Text,Edit2.Text,936,65001,#10); end;
----------------------------------------------
Bye bye DDRFAN...
作者:
2021/5/19 19:34:20
33楼:
楼上666
----------------------------------------------
[alias] co = clone --recurse-submodules up = submodule update --init --recursiveupd = pullinfo = statusrest = reset --hard懒鬼提速https://www.cctry.com/ >http://qalculate.github.io/downloads.htmlhttps://www.cctry.com/
作者:
dalas (dalas)
★☆☆☆☆
-
普通会员
2021/5/20 21:57:56
34楼:
楼上的楼上666
----------------------------------------------
-