他のシステムとの整合をとるため、Salesforceで入力できる文字を制限をかけたり、変換したい場合があります。
次のような要件があると思います。
※この例で、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文字として文字を作る必要があります。