我编写了perl代码来解析mysqldump中的xml。问题是数据库将数据存储在latin-1(它是一个旧系统......)中。用户将UTF-8数据粘贴到系统中,该系统在mysql xml转储中出现。 (上游系统超出了我的控制范围,所以我无法删除不良数据,这显然是最好的方法..)
现在我正在浏览文件并清除带有正则表达式的错误编码字符,以便我的xml解析器在遇到这些字符时不会死亡。
sub correctBadEncoding
{
my ( $path2File,$nameOfFile) = @_;
my $file2Convert ;
my $tempFile2Convert;
open($file2Convert ,'<:raw' ,$path2File. $nameOfFile)|| die("Unable to read ".$path2File. $nameOfFile."\n");
open($tempFile2Convert ,'>:encoding(UTF-8)' ,$path2File."tmp_".$nameOfFile)|| die("Unable to read temp path for ".$path2File. $nameOfFile."\n");
while (my $line = <$file2Convert>)
{
$line =~ s/[^\x09\x0A\x0D\x20-\x{D7FF}\x{E000}-\x{FFFD}\x{10000}-\x{10FFFF}]//gox;#strips just about everything out
#thanks to http://stackoverflow.com/questions/1016910/how-can-i-strip-invalid-xml-characters-from-strings-in-perl
my $oc2Write = Encode::encode("UTF-8", $line);
print $tempFile2Convert $oc2Write;
}
close($file2Convert);
close($tempFile2Convert);
unlink($path2File. $nameOfFile) or print "Failed to remove old file(for encoding)!";
move($path2File."tmp_".$nameOfFile, $path2File. $nameOfFile) or print "Failed to move temp to true file(for encoding)!";
return 1;
}
问题是需要大约1到2.5个小时才能浏览每行文件并删除不良字符。如果我使用已清理的文件并运行xml解析过程,则需要大约15-30分钟来处理数据并执行我需要的操作(包括xml解析)。有什么办法可以加快删除比当前方法更快的无效字符吗?
修改 的 这是坏字符串的十六进制示例
3c6669656c64206e616d653d226e6f7465223e4e6f7420436f6d706c657465643a20204920676f74204f535046207475726e656420757020627574204920636f756c646ee2742067657420697420646f776e6772616465642e20205468652066696c6573206f6e207468652066747020666f6c64657220636f756c646ee274206265206f70656e65642062792074686520353020666f7220736f6d6520726561736f6e2e2020200d0a0d0a20413a736f6d65686f73742d3530232066696c6520636f7079206674703a2f2f6361743a636174403132372e302e302e312f686f6d652f646e6f632f526f75746572732f35302f626f6f742e6c6472206366333a35302d4f532d3130302e312e426f6f742e6c6472200d0a4d494e4f523a20434c492043616e6e6f74206f70656e20696e7075742066696c65206674703a2f2f6361743a636174403132372e302e302e312f686f6d652f6361742f526f75746572732f35302f626f6f742e6c64722e0d0a66696c6520636f7079206674703a2f2f6361743a636174403132372e302e302e312f526f75746572732f35302f626f6f742e6c6472206366333a35302d4f532d3130302e312e426f6f742e6c64723c2f6669656c643e
(随意使用转换器... http://www.string-functions.com/hex-string.aspx,或查看下面的评论以查看正常输出中的文字,但其显示可能会因浏览器而改变。)
修改 有几个文件长度不同,最大的是1.4G,38,695,571行
答案 0 :(得分:1)
如果您使用的是perl 5.14或更高版本,则可以利用perl对字符而不是字节进行操作的事实,并使用更快的tr///
命令:
$line =~ tr/\x09\x0A\x0D\x20-\x{D7FF}\x{E000}-\x{FFFD}\x{10000}-\x{10FFFF}//cd ;
如果仍然不够快,我会写一个小的C程序来读取第一个文件并删除字符。