关于在 Perl 中将混合编码文件转换为 UTF8 的问题

2024-03-29

我正在将我们大学中国研究系古老的基于 DOS 的图书馆程序生成的文件转换为更有用和更易于访问的文件。

我正在处理的问题之一是导出的文本文件(大小约为 80MB)采用混合编码。我在 Windows 上。

我认为德语元音变音和其他高级 ASCII 字符以 cp1252 编码,而 CJK 字符以 GB18030 编码。由于“重叠”编码,我不能只是将整个文件拖到Word或其他东西中并让它进行转换,因为我会得到这样的结果:

orig:

+Autor:
-Yan, Lianke / ÑÖÁ¬¿Æ      # encoded Chinese characters
+Co-Autor:
-Min, Jie / (šbers.)       # encoded German U-umlaut (Ü)

result:

+Autor:
-Yan, Lianke / 阎连科       # good
+Co-Autor:
-Min, Jie / (歜ers.)       # bad... (should be: "Übers.")

因此,我编写了一个包含多个子例程的脚本,可以分几步转换非 ASCII 字符。它执行以下操作(除其他外):

  1. 用字母数字代码替换一些高阶 ASCII 字符(š、á 等)(不太可能自然出现在文件中的其他任何位置)。前任。:-Min, Jie / (šbers.) -> -Min, Jie / (uumlautgrossbers.)
    注意:我手工制作了“转换表”,所以我只考虑了文档中实际出现的特殊字符。因此,转换并不完全完成,但对我来说产生了足够的结果,因为我们的书籍主要是德语、英语和中文,只有很少的语言,如意大利语、西班牙语、法语等,几乎没有捷克语等语言的。

  2. replace á, £, ¢, ¡, í带有字母数字代码仅当它们之前或之后没有高 ASCII 范围中的另一个字符时\x80-\xFF。 (这些是 cp1252 编码版本ß, ú, ó, í and "small nordic o with cross-stroke" 并且出现在 cp1252 和 GB18030 编码的字符串中。)

  3. 读入整个文件并将其从 GB18030 转换为 UTF8,从而将编码的汉字转换为真正的汉字。

  4. 将字母数字代码转换回其 Unicode 等效代码。

尽管该脚本大部分都可以工作,但会出现以下问题:

  • 转换原始80MB文件后,Notepad++仍然认为它是ANSI文件并按原样显示。我需要按“编码->以 UTF-8 编码”才能正确显示。

我想知道的是:

  1. 一般来说,有没有更好的方法将混合编码文件转换为UTF-8?

  2. 如果没有,我应该使用use utf8这样我就可以直接输入字符而不是它们的十六进制表示形式codes2char子程序?

  3. 文件开头的 BOM 能否解决 NP++ 最初将其显示为 ANSI 文件的问题?如果是这样,我应该如何修改我的脚本以便输出文件具有 BOM?

  4. 转换后,我可能想调用更多子例程(例如,将整个文件转换为 CSV 或 ODS 格式)。我需要继续使用开场白吗?codes2char子程序?

该代码由几个在最后调用的子例程组成:

!perl -w
use strict; 
use warnings;
use Encode qw(decode encode); 
use Encode::HanExtra;

our $input = "export.txt";
our $output = "export2.txt";

sub switch_var {                # switch Input and Output file between steps
    ($input, $output) = ($output, $input);
}

sub specialchars2codes {
open our $in, "<$input" or die "$!\n"; 
open our $out, ">$output" or die "$!\n"; 

while( <$in> )  {   
    ## replace higher ASCII characters such as a-umlaut etc. with codes.
    s#\x94#oumlautklein#g;
    s#\x84#aumlautklein#g;
    s#\x81#uumlautklein#g;
    ## ... and some more. (ö, Ö, ä, Ä, Ü, ü, ê, è, é, É, â, á, à, ì, î, 
    ## û, ù, ô, ò, ç, ï, a°, e-umlaut and ñ in total.)

    ## replace problematic special characters (ß, ú, ó, í, ø, ') with codes.
    s#(?<![\x80-\xFF])\xE1(?![\x80-\xFF])#eszett#g;
    s#(?<![\x80-\xFF])\xA3(?![\x80-\xFF])#uaccentaiguklein#g;
    s#(?<![\x80-\xFF])\xA2(?![\x80-\xFF])#oaccentaiguklein#g;
    s#(?<![\x80-\xFF])\xA1(?![\x80-\xFF])#iaccentaiguklein#g;
    s#(?<![\x80-\xFF])\xED(?![\x80-\xFF])#nordischesoklein#g;

    print $out $_;
    }   
close $out;
close $in;
}

sub convert2unicode {

open(our $in,  "< :encoding(GB18030)", $input)  or die "$!\n";
open(our $out, "> :encoding(UTF-8)",  $output)  or die "$!\n";

print "Convert ASCII to UTF-8\n\n";

while (<$in>) {         
        print $out $_;      
}

close $in;
close $out;
}

sub codes2char {

open(our $in,  "< :encoding(UTF-8)", $input)    or die "$!\n";
open(our $out, "> :encoding(UTF-8)", $output)   or die "$!\n";

print "replace Codes with original characters.\n";


    while (<$in>) {
        s#lidosoumlautklein#\xF6#g;
        s#lidosaumlautklein#\xE4#g;
        s#lidosuumlautklein#\xFC#g;
        ## ... and some more.
        s#eszett#\xDF#g;
        s#uaccentaiguklein#\xFA#g;
        s#oaccentaiguklein#\xF3#g;
        s#iaccentaiguklein#\xED#g;
        s#nordischesoklein#\xF8#g;

        print  $out $_;
    }
close($in)   or die "can't close $input: $!";
close($out)  or die "can't close $output: $!";
}

##################
## Main program ##
##################

&specialchars2codes;
&switch_var;
&convert2unicode;
&switch_var;
&codes2char;

哇,这很长。我希望它不会太复杂

EDIT:

这是上面示例字符串的十六进制转储:

01A36596                                                        2B 41                    +A
01A365A9   75 74 6F 72 3A 0D 0A 2D  59 61 6E 2C 20 4C 69 61  6E 6B 65   utor:  -Yan, Lianke
01A365BC   20 2F 20 D1 D6 C1 AC BF  C6 0D 0A 2B 43 6F 2D 41  75 74 6F    / ÑÖÁ¬¿Æ  +Co-Auto
01A365CF   72 3A 0D 0A 2D 4D 69 6E  2C 20 4A 69 65 20 2F 20  28 9A 62   r:  -Min, Jie / (šb
01A365E2   65 72 73 2E 29 0D 0A                                         ers.)  

另外两个来说明:

1.

000036B3                                                     2D 52 75                   -Ru
000036C6   E1 6C 61 6E 64 0D 0A                                         áland  

2.

015FE030            2B 54 69 74 65  6C 3A 0D 0A 2D 57 65 6E  72 6F 75      +Titel:  -Wenrou
015FE043   64 75 6E 68 6F 75 20 20  CE C2 C8 E1 B6 D8 BA F1  20 28 47   dunhou  ÎÂÈá¶Øºñ (G
015FE056   65 6E 74 6C 65 6E 65 73  73 20 61 6E 64 20 4B 69  6E 64 6E   entleness and Kindn
015FE069   65 73 73 29 2E 0D 0A                                         ess).  

在这两种情况下,都有十六进制值 E1。在第一种情况下,它代表德语升号 s(ß,“Rußland”=“俄罗斯”),在第二种情况下,它是多字节 CJK 字符“柔”的一部分(读作:“rou”)。

在库程序中,汉字是通过必须首先加载的附加程序输入和显示的,据我所知,该程序在低级别连接到图形驱动程序,捕获编码的汉字并显示它们作为角色,而忽略其他一切。德语元音变音等由库程序本身处理。

我不完全理解它是如何工作的,即程序如何知道 HexE1 是否被视为单个字符á并因此根据转换codepage X当它是多字节字符的一部分并因此根据codepage Y

我发现的最接近的近似值是,如果特殊字符前面或后面有其他特殊字符,则它可能是中文字符串的一部分。 (例如。ÎÂÈá¶Øºñ)


  1. 如果混合编码使得每行/记录/字段/任何内容都采用一致的编码,则您可以单独读取和转换每行/记录/字段/任何内容。但这里的情况听起来并非如此。
  2. 这不是一个坏主意。
  3. UTF-8 通常不使用 BOM,但如果您确实想尝试输出字符 U+FEFF(在 UTF-8 中,这是 3 个字节)ef bb bf)。如果您能找出 NP++ 错误检测文件的确切原因,那就更好了。
  4. 读取 UTF-8 编码的文件时,使用 UTF-8 输入层打开它是一个好主意。如果你想,<:utf8是一个更短的等价于< :encoding(UTF-8).

至于最初的混乱是如何工作的,似乎“附加程序”只是将任何看起来像汉字的东西转换为中文,而忽略其他任何东西(然后标准驱动程序使用欧洲编码显示),而“库程序”只输出它收到的任何代码。因此,转换文件的更直接方法可能是镜像:使用:encoding(latin-1)(或其他),然后替换中文字符(例如s/\xc8\xe1/柔/).

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

关于在 Perl 中将混合编码文件转换为 UTF8 的问题 的相关文章

  • 如何在PHP中设置文本文件编码?

    如何在 PHP 中设置文本文件编码 例如 UTF 8 让我告诉你我的问题 这是我的代码 Output fwrite 具有类似的输出 但是当我创建test txt通过记事本并设置字符集UTF 8输出就是我想要的 我想在 PHP 文件中设置字符
  • 是否可以让 SQL Server 将排序规则转换为 UTF-8 / UTF-16

    在我正在处理的一个项目中 我的数据存储在 SQL Server 中 并具有排序规则Danish Norwegian CI AS 数据通过 FreeTDS 和 ODBC 输出到将数据作为 UTF 8 处理的 python 一些字符 如 和 编
  • 是否可以使用perl读取pdf文件中的文本?

    我想在 perl 中解析 pdf 文件中的文本 而不将 pdf 转换为任何其他格式 是否可以 是的你可以 看看CAM PDF http search cpan org dist CAM PDF 包裹 您可以使用此模块来提取文本 my pdf
  • Perl:避免从标准输入贪婪读取?

    考虑以下 perl 脚本 read pl my line
  • 如何让 XSLT 在 Java 中返回 UTF-8

    我正在尝试让我的 XSL 脚本使用 UTF 8 编码 像 和希腊字符这样的字符就像垃圾一样出现 让它工作的唯一方法是将结果写入文件 如果我将它写入输出流 它只会返回垃圾 System out 有效 但这可能是因为它被重定向到文件 结果需要从
  • json_encode() 非 utf-8 字符串?

    所以我有一个字符串数组 并且所有字符串都使用系统默认值ANSI编码并从 SQL 数据库中提取 因此有 256 种不同的可能的字符字节值 单字节编码 有什么方法可以让我得到json encode 工作并显示这些字符而不必使用utf8 enco
  • Python UTF-8转换问题

    在我的数据库中 我存储了一些 UTF 8 字符 例如 名称 字段中的 通过 Django ORM 当我读到这个时 我得到了类似的东西 gt gt gt p name u xce xb1 gt gt gt print p name 我本来希望
  • Perl Mongo 查找对象 ID

    你会认为这是一件简单的事情 我有一个集合中的对象 ID 列表 我想根据对象 ID 获取单个记录 谷歌搜索过 但没有任何帮助 所以我有对象 ID 5106c7703abc120a04070b34 my client MongoDB Mongo
  • 如何从 Perl 中的字符串中去除无效的 XML 字符?

    我正在寻找一种标准的 经过批准的 可靠的方法 可以在将字符串写入 XML 文件之前从字符串中删除无效字符 我在这里讨论的是包含退格键 H 和换页符等的文本块 There has成为执行此操作的标准库 模块函数 但我找不到它 我在用着XML
  • 编写脚本时,#!/usr/bin/perl 和 #!/usr/bin/env perl 有什么区别?

    显然 这同样适用于用 python bash sh 等替代 perl 昆汀下面的答案显然是正确的 所以我接受了它 但我想我实际上的意思是 两种使用 的方式的优点和缺点是什么 调用 perl python bash 作为脚本的解释器 有人提到
  • 如何使用 Perl 从 NCBI 获取 FASTA 核苷酸格式的基因特征?

    我可以手动下载 FASTA 文件 如下所示 gt lcl CR543861 1 gene 1 ATGCTTTGGACA gt lcl CR543861 1 gene 2 GTGCGACTAAAA 通过单击 发送到 并选择 基因特征 FAST
  • 将传入字符串的 unicode 表示形式转换为 UTF-8?

    我正在读取一些已经转换为 html 样式 代码的数据 我现在需要将其转换回 UTF 8 字符以供查看 不幸的是我无法使用浏览器查看该字符串 我读过有关 java 中的转换的内容 似乎如果你有一个 uxxxx 字符串 那么编译器会为你转换 然
  • Perl 中字符串之间的字符匹配计数

    我有一个字符串 例如字符串 1 需要与另一个字符串 字符串 2 匹配 两个字符串的长度相同并且不区分大小写 我想打印两个字符串之间的字符匹配数 E g String 1 stranger String 2 strangem Match co
  • 如何从字符串中删除除字母、数字、空格、感叹号和问号之外的所有内容?

    如何删除除以下内容之外的所有内容 字符串中的字母 数字 空格 感叹号 问号 该方法支持国际语言 UTF 8 非常重要 您可以使用正则表达式 myString replace w s g 这将替换除单词字符 空格 感叹号或问题之外的所有内容
  • 如何在 Java/Eclipse 中使用特殊字符

    如何在 Java Eclipse 中使用 显示 或 等字符 当我尝试直接使用它们时 例如在源代码中 Eclipse无法保存文件 我能做些什么 编辑 如何找到 unicode 转义序列 问题是您使用的字符无法以文件设置的编码 Cp1252 表
  • Perl 单元测试只针对模块,而不针对程序吗?

    我在网上找到的文档和我拥有的书 Perl测试 或者说或者建议 Perl 的单元测试通常是在创建模块时完成的 这是真的 有没有办法使用单元测试实际程序Test More和表兄弟姐妹 当然 您可以使用测试脚本测试 更多 http search
  • Moose:属性值更改时缓存的计算结果会过期吗?

    在我们的类中 我们有一个模式 我们创建一个属性来表示 计算值 出于显而易见的原因 我们想要缓存计算值 然后当基础值之一发生变化时使缓存失效 所以我们目前有这个 package FooBar use Moose has foo gt acce
  • Navicat utf8 不适用于 mysql 数据库

    我目前正在尝试合并两个不同步的表达式引擎数据库之间的数据更改 为此我选择使用 navicat 该网站在模板中大量使用希腊字符集 当我在 phpmyadmin 中查看希腊语表字段数据时 我按预期看到了希腊语字符 当我将它们加载到 Navica
  • Java中的字节和字符转换

    如果我将一个字符转换为byte然后回到char 那个角色神秘地消失了 变成了别的东西 这怎么可能 这是代码 char a line 1 byte b byte a line 2 char c char b line 3 System out
  • 黑色左/右三角形大小不同

    我使用黑色左指三角形 右左指三角形几何形状作为网站上的链接 并使用它们的 HTML 代码 和 9664 9654 由于某种原因 即使我在没有其他元素的空白页面上使用三角形 它们也不会以相同的大小显示 在 Chrome 上 向左指向的位置比向

随机推荐

  • 如何在 JTextPane 中为文本和下划线设置不同的颜色?

    刚刚尝试为 JTextPane 中的文本着色 但问题是文本和下划线不能有不同的颜色 我应该怎么做或者这是否可能 下面的示例以红色打印所有文本和下划线 JTextPane pane new JTextPane StyleContext con
  • 事件未在首页加载时加载,但在刷新后有效

    我正在创建一个名为员工管理系统的应用程序Rails 7 为了添加员工 我创建了一个表单 在这里 我使用nested form fields gem 来添加员工的联系人 问题是当第一次加载表单时 当我想添加或删除联系人字段时 它会重定向到同一
  • 从 dplyr 中选择函数时出错

    当我使用 dplyr 中的 select 函数时 它不起作用 并给出一个错误 指出我要选择的列名称是未使用的参数 但是 如果我在函数调用之前指定 dplyr 如 s dplyr select 那么它会正常工作 这是一个示例 df sampl
  • GCE:如何创建从外部端口80到内部端口5555的转发规则

    我第一次使用谷歌计算引擎 我想设置一个网络负载平衡器 具有静态IP 侦听端口80 但转发到侦听端口5555的后端服务器 我发现的所有示例都显示转发80到80 这在以下方面没有帮助我的情况 ref https cloud google com
  • 许多元素上的 ngClass 使网站非常慢

    我目前正在我的 Angular 6 应用程序中制作一个树视图 我正在使用它 嵌套和所有内容 我遇到的问题之一是 当我的页面有很多元素 几千个 并且它们都有 ngClass 在它们上 根据所选节点显示不同的颜色 页面往往会挂起很多 我创建了一
  • 通过鼠标单击并拖动绘制矩形 - javascript

    我试图在 Javascript 中绘制一个矩形 实际上是一个选择框 以选择选择中的 SVG 元素 我尝试修复单击并拖动矩形的代码 http jsfiddle net 7uNfW 26 http jsfiddle net 7uNfW 26 但
  • 如何在同一应用程序中运行 Spring Boot 管理客户端和服务器

    我想在同一个应用程序中运行 spring boot 管理服务器和客户端 我更改了服务器端口 当我更改服务器端口时 spring admin 将访问我更改的端口 这样我就可以运行管理服务器 但我看不到我的网络应用程序页面 我需要这样的输出 本
  • 根据请求更改表单字段

    应用程序有一个类别字段 可以在会话中设置 也可以不设置 如果是 我不想看到表单上的字段 只需将其作为隐藏字段 其值等于请求中的值 如果未设置 那么我想显示一个下拉菜单 我已经设置了表单以包含下拉列表 这是该字段的默认设置 我的问题是 将小部
  • 将扰乱的 PDF 字符重新映射为可读文本

    我确实遇到了一个问题 因为 cups PDF 创建的 PDF 文档中的字符被映射到奇怪的符号 在 Ubuntu Linux 14 04 和 16 04 上 我认为它是某种 unicode 即使 Python 告诉我它的字符串类型 type
  • Magento CE :: 第一次订购有折扣吗?

    是否有任何合理的方式可以为客户的第一笔订单提供折扣 我想这会要求用户注册一个免费帐户 这很好 但在那之后 我就陷入了困境 Magento 中的促销功能无法满足此类需求 Google 也找不到任何好的潜在客户 Ideas 没有任何开箱即用的方
  • 如果在 Inno Setup 中更新安装,则排除 ssPostInstall 步骤中的部分代码部分

    我尝试对两者使用相同的安装程序 全新安装和更新 因此 如果用户第一次尝试安装我的应用程序 它将运行完整安装 包括 MySQL 安装程序作为先决条件 以及 MySQL 安装的一部分 Code 就会正常执行 但是 如果用户已经安装了我的应用程序
  • 通过 Vertex AI 用户管理笔记本中的启动后脚本创建自定义内核

    我正在尝试使用启动后脚本创建一个 Vertex AI 用户管理笔记本 其 Jupyter Lab 在首次启动时有一个专用的虚拟环境和相应的计算内核 我已成功创建实例 然后作为 Jupyter Lab gt Terminal 中的第二个手动步
  • 在 IE8 中,jquery-ui 的对话框将其内容的高度设置为零。我怎样才能解决这个问题?

    我正在使用 jquery UI 的对话框小部件在我的 Web 应用程序中呈现模式对话框 我通过将所需 DOM 元素的 ID 传递到以下函数来实现此目的 var setupDialog function eltId eltId dialog
  • 集成 bootstrap-select 以与 Ember 配合使用

    我想得到引导选择 https github com silviomoreto bootstrap select使用 Ember js Ember 对视图对象的管理存在一些问题 导致其无法按预期工作 JSFiddle http jsfiddl
  • 不兼容的 firebase 库

    我使用的是最新版本com google firebase firebase core 16 0 3和最新版本的com google firebase firebase messaging 17 3 1 但它们取决于不同的版本com goog
  • 列出 Google Fonts API 中的所有可变字体?

    我需要通过 Google Fonts API 获取所有可用的可变字体的列表 我可以从这个端点获取所有字体名称 您可以添加一些参数 但我认为其中不包括可变字体过滤器 我认为在进行 API 调用后我无法过滤结果 这里的 Open Sans 是一
  • 创建的 Iframe 和扩展、google chrome 扩展之间的通信

    我尝试从从我的扩展程序加载的 iframe 发送消息到我的扩展程序 后台脚本或内容脚本 创建的 Iframe 通过内容脚本从扩展加载 我正在寻找一种沟通方式 但我所有的尝试都失败了 清单 json author background pag
  • 在 Pandas DataFrame 上滚动应用速度更快?

    改进这个问题 https stackoverflow com questions 21040766 python pandas rolling apply two column input into function它提供了一个巧妙的解决方
  • 使用泛型类型反射执行类

    我想在使用反射 查找接口实现 找到它之后 在使用泛型类型的类上动态执行方法 下面是我陷入困境的一个例子 非常感谢您的帮助 Setup public interface IActionRequired
  • 关于在 Perl 中将混合编码文件转换为 UTF8 的问题

    我正在将我们大学中国研究系古老的基于 DOS 的图书馆程序生成的文件转换为更有用和更易于访问的文件 我正在处理的问题之一是导出的文本文件 大小约为 80MB 采用混合编码 我在 Windows 上 我认为德语元音变音和其他高级 ASCII