Rebol 3 を使用して、Latin1 のファイルを読み取り、UTF-8 に変換したいと考えています。使用できる組み込み関数、または外部ライブラリはありますか? どこで見つけられますか?
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 snippet #{DECAFBAD} ここsnippet
で:
; modifying
IUgetLOAD"invalid-utf?"MaWT[MiuM][MisMtcTKm]tsA
; copying
IUgetLOAD"invalid-utf?"MaTSrjCT[wt[MiuA][kp copy/partAmKPtcFm AnxM]kpA]
これは、少し高速で、少なくともメモリの使用量が少ないバージョンです。
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!
それぞれに使用して変換するだけです。
現時点では何も組み込まれていません。これは、私が書いて少し前に 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 の素敵な回答を参照してください。
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
]