4

我想使用 Rebol 3 读取 Latin1 中的文件并将其转换为 UTF-8。是否有我可以使用的内置函数或一些外部库?我在哪里可以找到它?

4

4 回答 4

4

这是一个应该更快的版本,并且至少使用更少的内存。

latin1-to-utf8: func [
    "Transcodes a Latin-1 encoded string to UTF-8"
    bin [binary!] "Bytes of Latin-1 data"
] [
    to binary! head collect/into [
        foreach b bin [
            keep to char! b
        ]
    ] make string! length? bin
]

它利用了与相应 Unicode 代码点具有相同数值的 Latin-1 字符。如果您想从另一个不是这种情况的字符集进行转换,您可以对 进行计算b以重新映射字符。

由于各种原因,它使用更少的内存并且速度更快:

  • 通常,collect创建一个块。我们使用collect/into并传递一个字符串作为目标。字符串比整数块或字符块使用更少的内存。
  • 我们将字符串预分配到输入数据的长度,这样可以节省重新分配。
  • 我们让 Rebol 的本机代码转换字符,而不是自己进行数学运算。
  • 循环中的代码更少,因此它应该运行得更快。

这种方法仍然是一次将文件全部加载到内存中,并且仍然会生成一个中间值来存储结果,但至少中间值更小。也许这会让你处理更大的文件。

如果您需要它是 UTF-8 的原因是您需要在 Rebol 中将文件作为字符串处理,只需跳过to binary!并按原样返回字符串。或者您可以只处理二进制源数据,只需使用to char!每个字节转换二进制中的字节即可。

于 2014-02-13T19:45:12.750 回答
4

Rebol 有一个无效的 utf?用于搜索不属于有效 UTF-8 序列的字节的二进制值的函数。我们可以循环直到找到并替换所有这些,然后将我们的二进制值转换为字符串:

latin1-to-utf8: function [binary [binary!]][
    mark: :binary
    while [mark: invalid-utf? mark][
        change/part mark to char! mark/1 1
    ]
    to string! binary
]

此函数修改原始二进制文件。我们可以创建一个新字符串来保持二进制值不变:

latin1-to-utf8: function [binary [binary!]][
    mark: :binary
    to string! rejoin collect [
        while [mark: invalid-utf? binary][
            keep copy/part binary mark  ; keeps the portion up to the bad byte
            keep to char! mark/1        ; converts the bad byte to good bytes
            binary: next mark           ; set the series beyond the bad byte
        ]
        keep binary                     ; keep whatever is remaining
    ]
]

奖励:这是上面的Rebmu版本 - <code>rebmu/args 片段 #{DECAFBAD} 其中snippet是:

; modifying
IUgetLOAD"invalid-utf?"MaWT[MiuM][MisMtcTKm]tsA

; copying
IUgetLOAD"invalid-utf?"MaTSrjCT[wt[MiuA][kp copy/partAmKPtcFm AnxM]kpA]
于 2014-04-05T02:47:19.620 回答
3

目前没有内置任何内容,抱歉。这是我不久前编写并与 Rebol 3 一起使用的 Latin-1 到 UTF-8 转换的简单实现:

latin1-to-utf8: func [
    "Transcodes a Latin-1 encoded string to UTF-8"
    bin [binary!] "Bytes of Latin-1 data"
] [
    to-binary collect [foreach b bin [keep to-char b]]
] 

注意:此代码针对易读性进行了优化,而不是以任何方式针对性能进行了优化。(从性能的角度来看,这完全是愚蠢的。您已被警告过。)

更新:合并了@BrianH 的简洁的“Latin-1 字节值对应于 Unicode 代码点”优化,这使得上述内容崩溃为单行(同时稍微不那么愚蠢)。仍然。有关内存使用的更优化版本,请参阅@BrianH 的好答案。

于 2014-02-12T00:49:39.320 回答
1
latin1-to-utf8: func [
    "Transcodes bin as a Latin-1 encoded string to UTF-8"
    bin [binary!] "Bytes of Latin-1 data"
    /local t
] [
    t: make string! length? bin
    foreach b bin [append t to char! b ]
    t
]
于 2014-03-30T00:15:30.243 回答