mysql - 带有错误编码字符的大型 MYSQL 转储

标签 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 解析)。我可以采取什么措施来加快删除无效字符的速度,从而比当前方法更快?

编辑 这是错误字符串的十六进制示例

3c6669656c64206e616d653d226e6f7465223e4e6f7420436f6d706c657465643a20204920676f74204f535046207475726e6564207570206275742 04920636f756c646ee2742067657420697420646f776e6772616465642e20205468652066696c6573206f6e207468652066747020666f6c64657220636f7 56c646ee274206265206f70656e65642062792074686520353020666f7220736f6d6520726561736f6e2e2020200d0a0d0a20413a736f6d65686f73742d3 530232066696c6520636f7079206674703a2f2f6361743a636174403132372e302e302e312f686f6d652f646e6f632f526f75746572732f35302f626f6f 742e6c6472206366333a35302d4f532d3130302e312e426f6f742e6c6472200d0a4d494e4f523a20434c492043616e6e6f74206f70656e20696e7075742 066696c65206674703a2f2f6361743a636174403132372e302e302e312f686f6d652f6361742f526f75746572732f35302f626f6f742e6c64722e0d0a66 696c6520636f7079206674703a2f2f6361743a636174403132372e302e302e312f526f75746572732f35302f626f6f742e6c6472206366333a35302d4f5 32d3130302e312e426f6f742e6c64723c2f6669656c643e

(随意使用转换器... http://www.string-functions.com/hex-string.aspx ,或者查看下面的注释以查看正常输出中的文本,但其显示可能会因浏览器而改变..)

编辑 有几个不同长度大小的文件,最大的是1.4G,38,695,571行

最佳答案

如果您使用的是 perl 5.14 或更高版本,您可以利用 perl 对字符而不是字节进行操作的事实,并使用更快的 tr/// 命令:

$line =~ tr/\x09\x0A\x0D\x20-\x{D7FF}\x{E000}-\x{FFFD}\x{10000}-\x{10FFFF}//cd ;

如果这还不够快,我会编写一个小的 C 程序来读取第一个文件并修剪掉字符。

关于mysql - 带有错误编码字符的大型 MYSQL 转储,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21490782/

相关文章:

php - 基于 2 个参数从 MySQL 数据库中选择

php - 如何制作受控的 "shuffle"订单?

java数据库与mysql的连接错误

c# - 读取/解密加密的XML文件,然后进行内部处理

java - 寻找用于语法突出显示的 Java GUI 组件/想法

regex - 在 R Dataframe 列中拆分单词

php - MySQL + PHP - 根据邮政编码从数据库中获取城市

jquery - 将 Jquery Accordion 应用于 XML 标记

regex - 用 vim 替换单词边界

mysql - 如何在字符串中添加空格以搜索菜单?