DELPHI盒子
!实时搜索: 盒子论坛 | 注册用户 | 修改信息 | 退出
检举帖 | 全文检索 | 关闭广告 | 捐赠
技术论坛
 用户名
 密  码
自动登陆(30天有效)
忘了密码
≡技术区≡
DELPHI技术
lazarus/fpc/Free Pascal
移动应用开发
Web应用开发
数据库专区
报表专区
网络通讯
开源项目
论坛精华贴
≡发布区≡
发布代码
发布控件
文档资料
经典工具
≡事务区≡
网站意见
盒子之家
招聘应聘
信息交换
论坛信息
最新加入: laidabin
今日帖子: 0
在线用户: 3
导航: 论坛 -> DELPHI技术 斑竹:liumazi,sephil  
作者:
男 dalas (dalas) ★☆☆☆☆ -
普通会员
2021/4/30 22:12:54
标题:
请教一个12GB的文本文件替换换行符 浏览:4283
加入我的收藏
楼主: Linux 上导出的单文件 12GB 的文本文件,2000万行,UTF-8编码,换行符 0A,需转换为 ANSI编码,同时把换行符替换为 0D0A。
求一个高效转换的代码,可以是vbs或delphi,谢谢!!
----------------------------------------------
-
作者:
男 xiaobaosoft (小宝软件) ▲▲△△△ -
普通会员
2021/4/30 23:06:26
1楼: 方案:
1.试用内存映射 CreateFileMapping 加载大文件
2.读取一段 操作一段  操作完成写入另一个文件

猜测可以在5分钟内完成。
----------------------------------------------
-
作者:
男 scarlette (Scarlette) ★☆☆☆☆ -
普通会员
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写了个转换的脚本,跑到几小时也跑不出来。
----------------------------------------------
-
作者:
男 xiaobaosoft (小宝软件) ▲▲△△△ -
普通会员
2021/5/1 0:58:55
6楼: @dalas
例子没有。读取用映射

写出不需要啊。写出就正常写。
----------------------------------------------
-
作者:
男 c5soft (大道至简) ▲▲▲▲▲ -
普通会员
2021/5/1 22:10:55
7楼: 可以充分利用服务器多核大内存的处理能力,第一步将数据断行存到一个utf8编码的数组里,第二步,utf8转ansi, 启动并发处理,把cpu多核跑满,把utf8编码数组转换为ansi编码数组,第三步,讲数组用0D0A拼接成单个文件。

编程语言推荐用Rust, 第二步用async/await编写并行代码。

代码编写很容易,没有实际数据,不清楚转换需要多少时间。
----------------------------------------------
-
作者:
男 c5soft (大道至简) ▲▲▲▲▲ -
普通会员
2021/5/1 22:17:46
8楼: 没必要把所有数据全部读入内存,可以分片处理,读一段,转换一段,写一段
----------------------------------------------
-
作者:
男 msdtx (yong) ★☆☆☆☆ -
普通会员
2021/5/2 10:13:02
9楼: 有象形文字会比较烦,如果没有就会很好处理。
----------------------------------------------
-
作者:
男 c5soft (大道至简) ▲▲▲▲▲ -
普通会员
2021/5/3 23:09:33
10楼: 按前面的思路编写了个测试程序, 转换10G的数据只需要2分钟,三星960Pro高速固态硬盘64G内存,CPU i9-9900T,Win10 64位
此帖子包含附件:c5soft_20215323932.zip 大小:262.4K
----------------------------------------------
-
作者:
男 c5soft (大道至简) ▲▲▲▲▲ -
普通会员
2021/5/3 23:16:04
11楼: 程序运行需要VC++2019Runtime DLL, 请自行网上查找。
此帖子包含附件:
PNG 图像
大小:171.6K
----------------------------------------------
-
作者:
男 c5soft (大道至简) ▲▲▲▲▲ -
普通会员
2021/5/3 23:38:58
12楼: windowd版的exe已经免费提供,没有任何功能限制。楼主如果对源代码感兴趣,可以有偿提供。源代码支持多平台,应该可以编译为Linux下的执行文件。另外,我前期做了一个多路并用的XCOPY,对于大文件搬家提速显著。
----------------------------------------------
-
作者:
男 keymark (嬲) ▲▲▲△△ -
普通会员
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/
作者:
男 letianwuji (大器晚成) ▲▲▲▲▲ -
普通会员
2021/5/4 8:41:38
14楼: EmEditor
了解下。
----------------------------------------------
相信自己,若自己都不相信,那还有谁可信。
作者:
男 c5soft (大道至简) ▲▲▲▲▲ -
普通会员
2021/5/5 8:23:12
15楼: 目前最快的速度
此帖子包含附件:
PNG 图像
大小:157.1K
----------------------------------------------
-
作者:
男 c5soft (大道至简) ▲▲▲▲▲ -
普通会员
2021/5/5 8:25:46
16楼: 附件中是windows 64位的exe文件,第三个参数是缓冲区大小
此帖子包含附件:c5soft_20215582546.zip 大小:157.4K
----------------------------------------------
-
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2021/5/6 11:47:02
17楼: Delphi 代码实现的话,可以考虑:

1. 千万不要全部加载后处理。光是把 128G 文件读入内存就要好多时间。
2. 读一行,处理一行。
3. 处理完一行,写入另外一个文件。
4. 综上,就是个文件读和文件写的操作。
5. 如果 CPU 多,可以使用 Delphi 的并行处理算法框架。
5.1. 并行处理不熟习的话,直接上多线程。当然,单CPU用多线程也没有意义。
5.2. 并行或者多线程,需要一个中间交换的变量,用于记录当前应该处理第几行,这个变量因为多个线程都要去读和写,因此需要用临界区保护起来。

到这里,基本上应该就能处理完,并且代码也很简单,并不复杂。
----------------------------------------------
-
作者:
男 wr960204 (武稀松) ★☆☆☆☆ -
盒子活跃会员
2021/5/6 11:52:43
18楼: 我觉得可以更快,主要差异在磁盘IO处理这块
理论上即便是传统硬盘10秒也可以可以读一遍了,写入的话也就几十秒吧。
要是NVME的固态硬盘理论读写速度也就1-2秒,我自己的磁盘测试数据是1.5G每秒写入,读得更快。
----------------------------------------------
武稀松http://www.raysoftware.cn
作者:
男 sandaitanke (sayyou) ★☆☆☆☆ -
盒子活跃会员
2021/5/6 12:59:08
19楼: 不需要转换编码的情况下,只替换0A为ODOA。linux下使用unix2dos命令处理试试。
----------------------------------------------
-
作者:
男 c5soft (大道至简) ▲▲▲▲▲ -
普通会员
2021/5/6 16:52:04
20楼: 楼主度假去了?程序都给您写好了,何不拿去跑一跑?
顺便贴一下用Rust写的另一个软件:Filer高速文件分发系统, 需要的可以找我。
此帖子包含附件:
PNG 图像
大小:725.0K
----------------------------------------------
-
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2021/5/7 10:22:15
21楼: 楼上的拿 Rust 到 Delphi 的地方踢场子?
----------------------------------------------
-
作者:
男 c5soft (大道至简) ▲▲▲▲▲ -
普通会员
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)面前弱爆了。
----------------------------------------------
-
作者:
男 hawke2e (hawke2e) ★☆☆☆☆ -
普通会员
2021/5/7 12:43:56
23楼: 搞性能先要知道瓶颈在哪里:cpu 内存 主板IO性能 硬盘  这4个里面一般硬盘是瓶颈
如果内存够大,做个内存虚拟磁盘,把文件拷贝过去,程序读一部分、写一部分、删一部分,最后再拷贝出来,已经够快的了
“最”快就得针对操作系统、硬件,往往不具有通用性,差不多得了。
----------------------------------------------
软件是什么,相信很多人都说不清。
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2021/5/7 17:51:35
24楼: 22 楼,看了一下 svelte 的介绍,也就是个前端代码框架。这种框架,和 VCL 比较如何?有没有那么多现成的控件可以用?
----------------------------------------------
-
作者:
男 c5soft (大道至简) ▲▲▲▲▲ -
普通会员
2021/5/7 19:29:28
25楼: 程序进一步优化,现在转换一个12G的文件从1分半钟减少到20秒
此帖子包含附件:c5soft_202157192928.zip 大小:164.3K
----------------------------------------------
-
作者:
男 c5soft (大道至简) ▲▲▲▲▲ -
普通会员
2021/5/7 19:38:49
26楼: 回24楼: svelte是一个平台,可以与各种框架组合使用,在前端css框架中我推荐bulma, 数据表格我推荐ag-grid, 需要扫描二维码,可以调用Wasm, 这其中zbar就很好用,识别效果堪比微信。用svelte写界面的效率完爆VCL, 做出来的效果好多也是VCL很难实现的,比如动画,多媒体,支持手机等等。
此帖子包含附件:
PNG 图像
大小:289.4K
----------------------------------------------
-
作者:
男 teclick (nelson) ★☆☆☆☆ -
普通会员
2021/5/7 22:45:14
27楼: 有时并不一定非要自己搞,提供另外的思路,既然在linux上导出,多做一步是否也行呢?“iconv”,“unixtodos”,还有有些导入工具是可以配置行的末尾是dos格式还是unix格式的,仅仅是个思路。因为若十年前曾经搞过把文本文件批量导入到数据库,当时就是这么处理的。
----------------------------------------------
-
作者:
男 c5soft (大道至简) ▲▲▲▲▲ -
普通会员
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核数个线程负责处理数据块。
处理工作比转换个回车换行复杂。需要把文本字符串转换为整数,每个字符串以逗号隔开。
----------------------------------------------
-
作者:
男 c5soft (大道至简) ▲▲▲▲▲ -
普通会员
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是面向未来的语言,是全栈语言,什么都能干。这是一门让程序员爱不释手的编程语言。
----------------------------------------------
-
作者:
男 ddrfan (若苗瞬) ▲▲▲▲▲ -
普通会员
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...
作者:
男 keymark (嬲) ▲▲▲△△ -
普通会员
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
----------------------------------------------
-
信息
登陆以后才能回复
Copyright © 2CCC.Com 盒子论坛 v3.0.1 版权所有 页面执行195.3125毫秒 RSS