当前位置: 首页 > Linux

快速去除UTF-8BOM

时间:2023-04-06 19:59:35 Linux

工作中或多或少都会遇到UTF-8BOM(后面直接简称为BOM)。有时第三方工具不支持,只好自己去掉BOM。比如阿里云导出的SQL文件是有BOM的,但是Navicat不支持,所以需要去掉BOM。下面使用的测试文件是阿里云导出的SQL文件,265M。文件在测试过程中已经被缓存(按时间显示的文件系统输入接近于0)。使用sed去除BOMsed-e'1s/^\xef\xbb\xbf//'文件使用time查看sed方法耗时:$/usr/bin/time-vsed-e'1s/^\xef\xbb\xbf//'sqlResult_1601835.sql>/dev/null...用户时间(秒):0.33系统时间(秒):0.11此作业获得的CPU百分比:98%经过(挂钟)时间(h:mm:ssorm:ss):0:00.46...用户时间较大,因为sed会处理每一行,但实际上只有第一行有BOM,所以浪费了CPU。sed还支持就地更新(-i):$/usr/bin/time-vsed-e'1s/^\xef\xbb\xbf//'sqlResult_1601835.sql-i...用户时间(秒):1.31系统时间(秒):3.89此作业获得的CPU百分比:71%经过(挂钟)时间(h:mm:ss或m:ss):0:07.32...因为它将被写入文件,会比较慢,可以用strace发现sed是通过输出到一个临时文件,然后覆盖原来的文件来更新的。open("sqlResult_1601835.sql",O_RDONLY)=3open("./sedGlXm60",O_RDWR|O_CREAT|O_EXCL,0600)=4...rename("./sedGlXm60","sqlResult_1601835.sql")使用tail去toBOMtail--bytes=+4file使用tail直接跳过BOM,然后直接复制文件内容,减少不必要的CPU处理:$/usr/bin/time-vtail--bytes=+4sqlResult_1601835.sql>/dev/null...用户时间(秒):0.01系统时间(秒):0.12此作业获得的CPU百分比:96%经过(挂钟)时间(h:mm:ss或m:ss):0:00.14...但tail必须将自己重定向到新文件并覆盖旧文件。strip-bom为了结合sed和tail的优点,我写了一个支持就地更新文件的strip-bom。首先测试重定向:$/usr/bin/time-vphpstrip-bom.pharsqlResult_1601835.sql>/dev/null...用户时间(秒):0.11系统时间(秒):0.22此作业的CPU百分比得到:98%已用(挂钟)时间(h:mm:ss或m:ss):0:00.35...仅比sed快20%,用户时间减少但系统时间增加。因为是循环读写,每个循环都是一次读写调用,所以我加了一个参数调整每次读的blocksize,这样可以减少循环次数和系统调用次数,可以提速60%比sed:$/usr/bin/time-vphpstrip-bom.phar-b16384sqlResult_1601835.sql>/dev/null...用户时间(秒):0.06系统时间(秒):0.12CPU百分比工作得到:96%已用(挂钟)时间(h:mm:ss或m:ss):0:00.19测试就地更新,比sed快30%:$/usr/bin/time-vphpstrip-bom.phar-i-b16384sqlResult_1601835.sql用户时间(秒):0.23系统时间(秒):0.67此作业获得的CPU百分比:17%经过(挂钟)时间(h:mm:ss或m:ss):0:05.11copy_file_rangeLinux4.5增加了一个系统调用:ssize_tcopy_file_range(intfd_in,loff_t*off_in,intfd_out,loff_t*off_out,size_tlen,unsignedintflags);可以直接在两个文件描述符之间复制内容,通常只需要一次系统调用,所以可以参考sed复制到一个临时文件,然后覆盖旧文件。实现代码在:Gisttest:$/usr/bin/time-v./copy_file_rangesqlResult_1601835.sql...Usertime(s秒):0.00系统时间(秒):2.47此作业获得的CPU百分比:37%经过(挂钟)时间(h:mm:ss或m:ss):0:06.52减少的系统调用仅比sed更快一点,复制到临时文件仍然比strip-bom就地更新慢。Dos2unix去BOM。一直以为是dos2unix转CRLF。看完Feng_Yu的评论后,我阅读了手册页。原来dos2unix有很多功能,包括去BOM的选项(-r):$/usr/bin/time-vdos2unix-rsqlResult_1601835.sqldos2unix:ConvertingfilesqlResult_1601835.sqltoUnixformat...Commandbeing定时:“dos2unix-rsqlResult_1601835.sql”用户时间(秒):10.01系统时间(秒):0.90此作业获得的CPU百分比:60%经过(挂钟)时间(h:mm:ss或m:ss):0:18.20dos2unix实现和sed类似,也是先写入一个临时文件然后覆盖,和sed一样,每一行都处理,所以性能不好。