プログラマ38の日記

主にプログラムメモです。

Salesforce: 文字化けの制御で注意したいこと

他のシステムとの整合をとるため、Salesforceで入力できる文字を制限をかけたり、変換したい場合があります。

次のような要件があると思います。

  1. Shift_JISで定義されていない文字をエラーとしたい
  2. Shift_JISで定義されていない文字は、全角四角"□"に変換したい

※この例で、Shift_JISはCP932とします。

 

1の要件には次のようなコードが簡単です。

String convertbefore= 'a①bⅰc𠀋ef𠀋g'; //文字化けするか判定する文字

String charSet = 'Windows-31J';
String encodeStr = EncodingUtil.urlEncode(convertbefore,charSet);
String decodeStr = EncodingUtil.urlDecode(encodeStr, charSet);

if( convertbefore == decodeStr ) {
System.debug('文字化けする文字は無い');
} else {
System.debug('文字化けする文字が有る');
}

EncodingUtil.urlEncodeとurlDecodeで、文字化けする文字が「?」になるのを利用して、元の文字と比較することで、文字化けする文字列かどうかは判断できます。

ただ、この場合はどの文字が文字化けするかまではわかりません。

 

2の要件では、文字化けする文字まで特定する必要があります。この時にサロゲートペアの文字の対処が必要です。

サロゲートペアの文字でも、EncodingUtil.urlEncodeとurlDecodeで、文字化けする文字が「?」1文字となるのは変わりません。

String convertbefore= 'a①bⅰc𠀋ef𠀋g';

String charSet = 'Windows-31J';
String encodeStr = EncodingUtil.urlEncode(convertbefore,charSet);
String decodeStr = EncodingUtil.urlDecode(encodeStr, charSet);


Integer beforeidx = 0;
Integer decodeidx = 0;

String convertafter = '';

for( ; decodeidx < decodeStr.length() ;  ){


  String charval_before = '';
  if(    convertbefore.substring(beforeidx,beforeidx+1).codepointat(0) >= 55296
                && convertbefore.substring(beforeidx,beforeidx+1).codepointat(0) <= 56319 ){
    charval_before = convertbefore.substring(beforeidx , beforeidx+2);    
    beforeidx++;
  } else {
    charval_before = convertbefore.substring(beforeidx , beforeidx+1);
  }

  String charval_decode = decodeStr.substring(decodeidx, decodeidx + 1);

  if( charval_before == charval_decode ){
    convertafter += charval_before;
  } else {
    convertafter += '□';
  }

  beforeidx++;
  decodeidx++;
}

System.debug(convertafter);

 1文字ずつ同じかどうか見て、違った文字は文字化けした文字として扱い”□"に置き換えていますが、サロゲートペアの文字は、きちんと上位サロゲートと下位サロゲートで1文字として文字を作る必要があります。