UTF-8 環境で、Shift-JIS の固定長ファイルを読み込むのって大変という話 - SAS

前回の記事、「Shift-JIS の固定長ファイルを UTF-8 環境に読み込む (kcvt関数) - SAS」の余談。

Shift-JIS の固定長ファイルを UTF-8 環境に読み込む (kcvt関数) - SAS」 にて、kcvt 関数を用いて、ファイルを読み込んでみました。 テスト用に用いたファイルでは、文字コード変換が必要な項目は1項目だけだったので、まだ良かったのですが、もし変換しなければならない項目が10項目、20項目、、、とあると、その項目の数だけ、length ステートメントと kcvt 関数を書かなければなりません。 これはとても面倒くさいです。

filename ステートメント、または infile ステートメントにて使用できる encoding= オプションを用いれば読め...ません。 このオプションは、CSV ファイルや TSV ファイルのように、区切り文字(セパレータ)があれば使えますが、固定長ファイルでは理想通りには使うことができません。 前回の記事のテストコードを流用して、固定長ファイルの読み込み時に encoding= を使うと、どうなるのか試しに使ってみます。

テストコード - encoding=sjis を追加

filename IN "/folders/myfolders/test.txt" ;
 
data TEST ;
  infile IN recfm=F lrecl=28 encoding=sjis ;
  input @001 CUSTOMER_ID   5.
        @006 NAME        $20.
        @026 AGE           2.
        ;
run ;

実行ログ

 56         filename IN "/folders/myfolders/test.txt" ;
 57         
 58         data TEST ;
 59           infile IN recfm=F lrecl=28  encoding=sjis ;
 60           input @001 CUSTOMER_ID   5.
 61                 @006 NAME        $20.
 62                 @026 AGE           2.
 63                 ;
 64         run ;
 
 NOTE: 入力ファイルIN :
       ファイル名=/folders/myfolders/test.txt,
       所有者名=root,グループ名=vboxsf,
       アクセス権限=-rwxrwx---,
       更新日時=2015年09月06日 19時57分33秒,
       ファイルサイズ (バイト)=140
 
 NOTE: AGEに対して、無効なデータが行1カラム26-27にあります。
 RULE:     ----+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0                      
 1         00001さとう たろう  
 CUSTOMER_ID=1 NAME=さとう たろ� AGE=. _ERROR_=1 _N_=1
 NOTE: AGEに対して、無効なデータが行2カラム26-27にあります。
 2         00002こばやし さな
       27  �
 CUSTOMER_ID=2 NAME=こばやし さ� AGE=. _ERROR_=1 _N_=2
 NOTE: AGEに対して、無効なデータが行3カラム26-27にあります。
 3         00003みたらい しょ
       27  �
 CUSTOMER_ID=3 NAME=みたらい し� AGE=. _ERROR_=1 _N_=3
 NOTE: AGEに対して、無効なデータが行4カラム26-27にあります。
 4         00004やぶき かける  
 CUSTOMER_ID=4 NAME=やぶき かけ� AGE=. _ERROR_=1 _N_=4
 NOTE: AGEに対して、無効なデータが行5カラム26-27にあります。
 5         00005はやし けんた  
 CUSTOMER_ID=5 NAME=はやし けん� AGE=. _ERROR_=1 _N_=5
 NOTE: 5レコードを入力ファイルINから読み込みました。
 NOTE: データセットWORK.TESTは5オブザベーション、3変数です。
 NOTE: DATAステートメント処理(合計処理時間):
       処理時間           0.03 秒
       CPU時間            0.04 秒

項目 NAME に、文字切れされた状態で値が格納されています。 項目 AGE は、欠損値を読み込んでしまい、無効なデータが~と怒られています。

input ステートメントの @~ で指定したデータの位置や長さは、文字コード変換されたの指定したデータの位置や長さを示します。 そのため、文字の長さが長くなってしまった項目 NAME は、長さが足りず、文字切れが起きてしまっています。名前部分が長くなった影響で、項目 AGE もデータ位置がずれてしまい欠損値を読み込んでしまいました。

例えば、項目 NAME の長さを長くしたとしても、どのくらい長くなるかは入っている文字によって異なるので、後続の項目を読み込んだりしてしまいます。

テストデータでは、無効なデータが~と怒られたのでわかりましたが、全ての項目が文字項目の場合だと、ログ上では全く怒られません。 データの中身を見ないと文字切れに気づかないので凄く厄介です。


実行ログ - 全て文字項目の場合

 56         filename IN "/folders/myfolders/test.txt" ;
 57         
 58         data TEST ;
 59           infile IN recfm=F lrecl=28 encoding=sjis ;
 60           input @001 CUSTOMER_ID  $5.
 61                 @006 NAME        $20.
 62                 @026 AGE          $2.
 63                 ;
 64         run ;
 
 NOTE: 入力ファイルIN :
       ファイル名=/folders/myfolders/test.txt,
       所有者名=root,グループ名=vboxsf,
       アクセス権限=-rwxrwx---,
       更新日時=2015年09月06日 19時57分33秒,
       ファイルサイズ (バイト)=140
 
 NOTE: 5レコードを入力ファイルINから読み込みました。
 NOTE: データセットWORK.TESTは5オブザベーション、3変数です。
 NOTE: DATAステートメント処理(合計処理時間):
       処理時間           0.02 秒
       CPU時間            0.02 秒

データの中身を見てみると、見事に文字化け状態になっています。

こんな感じで、残念ながら encoding= オプションでは読み込むことができませんでした。 簡単に固定長ファイルを読み込むことはできなさそうです。

誠に残念ながら、 length ステートメントと kcvt 関数をいっぱい使わないといけないかもしれないので、UTF-8 環境で、Shift-JIS の固定長ファイルを読み込むのって大変という話でした。

世間でどのくらいまだ固定長ファイルがあるのか分からないのですけど、固定長ファイルのメリットは無視して、個人的に徐々に減ってくれればいいなーと思う今日このごろです。

コメント

このブログの人気の投稿

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

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

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