具有错误编码字符的大型MYSQL转储

时间:2014-01-31 21:55:10

标签: mysql xml regex perl

我编写了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行

1 个答案:

答案 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程序来读取第一个文件并删除字符。