7
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

SalesforceAdvent Calendar 2022

Day 10

Apex で文字コード変換できるユーティリティクラスを作った

Posted at

はじめに

最近のシステムはほとんどの場合 UTF-8 が標準の文字コードになっており、 Salesforce も例に漏れずあらゆるインタフェースで UTF-8 を採用しています。しかし、稀に Salesforce (Apex) から古いシステムを触る必要があるときや、後処理の都合などで文字列を Shift_JIS や EUC-JP などに変換する必要に迫られる場合があります。Java や Python などの主要なプログラミング言語では標準で文字コードの変換が可能ですが、Apex は文字列の文字コード変換用のメソッドは存在しておらず、少しテクニカルに処理する必要があります。

方針

EncodingUtil.urlEncode を使えばマルチバイト文字は主要な文字コードに変換することができます。
ただしこのメソッドだと ASCII 文字が変換されないので、 EncodingUtil.urlEncode に渡す前にASCII文字列だけを個別に16進数表記の文字列に変換します。すべての文字列を変換先の文字コードの16進数表記にしたら EncodingUtil.convertFromHex で Blob 形式に変換して処理完了となります。

作ったもの

主要な日本語対応の下記文字コードをエンコードできるメソッドを用意しています。

  • EUC-JP
  • Shift_JIS
  • ISO-2022-JP
  • UTF-16(BE)
  • UTF-16(LE)
  • UTF-32(BE)
  • UTF-32(LE)

使い方

// 文字コード変換
Blob eucJp = CharacterEncodingUtil.encodeToEucJp('文字列');
Blob shiftJis = CharacterEncodingUtil.encodeToShiftJis('文字列');
Blob iso2022Jp = CharacterEncodingUtil.encodeToIso2022Jp('文字列');
Blob utf16 = CharacterEncodingUtil.encodeToUtf16('文字列');
Blob utf16le = CharacterEncodingUtil.encodeToUtf16LE('文字列');
Blob utf32 = CharacterEncodingUtil.encodeToUtf32('文字列');
Blob utf32le = CharacterEncodingUtil.encodeToUtf32LE('文字列');
// 改行コードを指定して文字コード変換
Blob eucJp = CharacterEncodingUtil.encodeToEucJp('文字列', CharacterEncodingUtil.NewlineSeparator.CRLF);
Blob shiftJis = CharacterEncodingUtil.encodeToShiftJis('文字列', CharacterEncodingUtil.NewlineSeparator.LF);
Blob iso2022Jp = CharacterEncodingUtil.encodeToIso2022Jp('文字列', CharacterEncodingUtil.NewlineSeparator.CR);
Blob utf16 = CharacterEncodingUtil.encodeToUtf16('文字列', CharacterEncodingUtil.NewlineSeparator.CRLF);
Blob utf16le = CharacterEncodingUtil.encodeToUtf16LE('文字列', CharacterEncodingUtil.NewlineSeparator.LF);
Blob utf32 = CharacterEncodingUtil.encodeToUtf32('文字列', CharacterEncodingUtil.NewlineSeparator.CR);
Blob utf32le = CharacterEncodingUtil.encodeToUtf32LE('文字列', CharacterEncodingUtil.NewlineSeparator.CRLF);
// 変換時のデフォルトの改行コードの変更
CharacterEncodingUtil.defaultNewLineSeparator = CharacterEncodingUtil.NewlineSeparator.LF;
// 改行コード LF で EUC-JP にエンコード
Blob eucJp = CharacterEncodingUtil.encodeToEucJp('文字列');

実装例

Apex で Shift_JIS 形式の CSV をファイルとして保存する処理の実装例

String DIGIT = '0123456789';
String ALPHABET = 'loremipsum';
String HIRAGANA = 'いろはにほへと';
String KATAKANA = 'イロハニホヘト';
String HALF_KATAKANA = 'イロパニボペト';
String KANJI = '高崎髙﨑';
String SPACE = '  \t';
String SYMBOL = '!"#$%&()[]{}`~=-\\';
String EMOJI = '😇🏴󠁧󠁢󠁷󠁬󠁳󠁿👶🏿';

String csvHeader = String.join(new List<String>{
        'DIGIT',
        'ALPHABET',
        'HIRAGANA',
        'KATAKANA',
        'HALF_KATAKANA',
        'KANJI',
        'SPACE',
        'SYMBOL',
        'EMOJI'
}, ',');
String csvBody = String.join(new List<String>{
        DIGIT,
        ALPHABET,
        HIRAGANA,
        KATAKANA,
        HALF_KATAKANA,
        KANJI,
        SPACE,
        SYMBOL,
        EMOJI
}, ',');
ContentVersion cv = new ContentVersion();
cv.ContentLocation = 'S';
cv.PathOnClient = 'example.csv';
cv.Title = 'example.csv';
cv.VersionData = CharacterEncodingUtil.encodeToShiftJis(csvHeader + '\n' + csvBody);
insert cv;

制限/留意事項

  • 変換先の文字コード上に存在しない文字(特に絵文字や機種依存文字など)は ? に変換されます
  • 大量の文字列を変換する場合、CPU時間に注意してください
    • 手元の環境だとShift_JIS変換のマルチバイト文字のみで 10,000 文字あたり 200 ~ 250 ms、ASCII文字のみで 10,000 文字あたり 平均 500 ~ 600 msほど消費します
      • UTF-16, UTF-32 はさらにASCII文字の処理負荷が1.5 ~ 2倍ほど
      • もう少し工夫すればチューニングできる...?
7
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?