PCとASの文字列の取り扱いの違い その1

この文字列をIBM i (AS/400)に保存すると何文字?

パソコン(Windows)とIBM i (AS/400)とでは、文字を取り扱うコード体系が異なるためおのずと文字列の取り扱いも変わってきています。
たとえば、PC側で入力した文字列をAS側に保存しようとしたとします。
このとき保存しようとした文字列が"1バイト文字と2バイト文字が混在"していたら、PCで計算したバイト長と実際に保存されバイト長が変わってしまいます。
保存にBDEを使用していた場合、IDCO400ドライバで保存できる長さにカットされる場合もあります。
これは、1バイト文字と2バイト文字の間にShift-In/Shift-Out文字が挿入されるからなので、前もってPC側で入力する際に保存後の状態を見越して文字列の長さチェックをすればよいということになります。  
実際に長さを計算するには、文字列の先頭から1バイト文字か2バイト文字かをチェックし、1バイト文字から2バイト文字に変わった際にSIとSOの2バイトを実際の文字のバイト長に加算すればOKです。
以下は上記のコーディング例です。
文字種の判別にDelphiのByteTypeを使用しています。
この関数で文字列のバイト長は取得できるので、更新前に文字列の長さチェックを行えば安心です。

 


{*******************************************************************************
 機能: 文字列の長さを取得
 引数:
   str     : 対象文字列
   ASMode  : KI/KOを考慮するかどうかのフラグ。考慮する場合はTRUE。
 戻値:
   文字列長
*******************************************************************************}
function GetLength(str: String; ASMode: Boolean): Integer;
var
  i: Integer;
  InDBCS: Boolean;
begin
  // AS/400 (KI/KO考慮)
  if (ASMode) then
  begin
    InDBCS := False;
    Result := Length(str);

    for i := 1 to Length(str) do
    begin
      case ByteType(str, i) of
        mbSingleByte:
          InDBCS := False;
        mbLeadByte:
          //半角から全角に切り替わった時点でKI/KO分加算
          if (InDBCS = False) then
          begin
            InDBCS := True;
            Result := Result + 2;
          end;
        mbTrailByte:
          ;
      end;
    end;

  end
  // 通常
  else
  begin
    Result := Length(str);
  end;
end;