文字切れを除去する方法 (UTF-8) - SAS

データ/ファイルが色んなDBやらツールやらを介していると、文字の長さが異なったりして、文字切れが発生することがあります。ここでいう文字切れとは、例えば、15バイト/5文字で表現できる文字を14バイトしか読み込まず(読み込めず)、最後の1文字が文字として認識されない状態になることです。「ありがとう」という文字が文字切れが起きると、最後の「う」が認識されなくなり、「ありがと◆」と表示されてしまうみたいな感じです。

文字切れが起きてしまうと、表示がおかしくなってしまいますし、他のシステムにデータを渡した時、エラーが起きてしまう原因になることもあります。

今回は、文字切れがどうしても起きてしまう時の対処方法についてのお話です。

文字切れは、klengthとksubstrを使用することで除去することができます。klengthが、文字切れ部分を文字として認識しないのを利用した方法です。

関数の説明

length
文字のバイト数を取得
klength
文字の文字数を取得
substr
○バイト目~○バイト目を取得
ksubstr
○文字目~○文字目を取得

サンプルコード

data TEST ;
  length A $15. B $15. ;
  /* UTF-8 で以下の全角文字は、1文字3バイト */
  A = "あいうえお" ;
  /* 項目 B で文字切れを作る */
  B = substr(A, 1, 14) ; C = klength(B) ; D = length(B) ; output ;
  B = substr(A, 1, 13) ; C = klength(B) ; D = length(B) ; output ;
run ;
data TEST ;
  set TEST ;
  if not missing(A) then do ;
    E = ksubstr(A, 1, klength(B)) ;
    F = length(E) ;
  end ;
run ;
proc print data=TEST ; run ;
 

項目 E のところが、文字切れをカットしているところです。項目 B で、13,14バイトに文字を切っていますが、文字切れ部分をカットした後、項目 F では12バイト(4文字分)となります。

上記のサンプルでは必要ないのですが、事前に欠損値かどうかを調べているのは、欠損値を klength すると、結果がゼロになり、ksubstr を使用する時に下記のようなエラーが出てしまうためです。

ERROR: Argument three to KSUBSTR is invalid. The value must be greater than zero.
 

どのレコードが文字切れを起こしているのかについては、文字切れ対応前後で、length関数を用いて、バイト数をチェックすることで取得できるかと思います。


上記の方法ですが、UTF-8の4バイト文字は対応できてないかも?です。k 付きの関数が 4バイト文字に対応していないことの影響ぽい?(未検証)

また、サンプルでは、文字コード UTF-8で試していますが、他の文字コードは未検証です。UTF-8だと、1バイト目でその文字が、何バイトの文字なのかわかるので、いける方法ですね。Shift-JISだと、0x5C(円記号)が使われている全角文字の文字切れとかはうまくいかないと思います。

(追記) Shift-JISだと、文字切れ起こしても、1バイト目が別の文字だと認識されてしまうので、上記の方法だと文字切れを検知できないです。0x5C問題は関係なかったですね。

コメント

このブログの人気の投稿

日付フォーマットでない文字項目をSAS日付に変換するときにログ出力されるメッセージを抑制したい - SAS

Linuxコマンド: date で◯か月前 / ◯か月後を取得するときの注意

データセット(.sas7bdatファイル)の文字コードを取得したい - SAS