【Salesforce】String.splitメソッドについての注意点
ApexでCSVをインポートする処理を作っていました。
何度か作ったことがあるものなので、簡単簡単と思いながら作っていると、どうもうまく動きません。
一部のデータでヘッダ行の列数とデータ行の列数が合致しないのです。
かなり省略していますが、こんな感じの処理です。
String csvData; List<String> rowList; String headerString; List<String> headerList; // CSVのヘッダ csvData = '列1,列2,列3,列4,列5' + '\r\n'; // CSVのデータ csvData += '1,2,3,4,5' + '\r\n'; csvData += '1,,,,' + '\r\n'; csvData += ',2,,,5' + '\r\n'; csvData += ',,3,,' + '\r\n'; csvData += ',,,4,' + '\r\n'; csvData += ',,,,5'; // 行ごとに分割する rowList = csvData.split('\r\n'); // 先頭行はヘッダ headerString = rowList.remove(0); // ヘッダを列に分ける headerList = headerString.split(','); // 各行の処理を行う for(String rowString : rowList){ List<String> columnList; // 列に分割する columnList = rowString.split(','); // ヘッダと列数が異なる場合、エラーとする if(headerList.size() != columnList.size()){ // エラー処理 system.debug('【エラー】' + rowString); continue; } system.debug('【正常】' + rowString); }
ヘッダ行とデータ行の列数が異なる場合にエラーとしています。
上のコードで作成しているCSVデータは、ヘッダ行とデータ行でカンマ区切りの数が同じです。
そのため、この場合はエラー処理は通らない想定でした。
しかし、実際に動かすとエラー処理を通りました。
通りまくりでした。
こんな感じのログです。
【正常】1,2,3,4,5 【エラー】1,,,, 【エラー】,2,,,5 【エラー】,,3,, 【エラー】,,,4, 【正常】,,,,5
使い方がおかしいと判断し、リファレンスを読みました。
https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_methods_system_string.htm#apex_System_String_methods
こんなことが書いてあります。
public String[] split(String regExp, Integer limit) limit が 0 より大きい場合 パターンが最大回数 (limit – 1) 適用されます。 リストの長さは limit を超えません。 リストの最後のエントリに、最後に一致した区切り文字より後のすべての入力が含まれます。 limit が正の値でない場合は、パターンが可能な限り何回でも適用され、リストも任意の長さになります。 limit が 0 の場合は、パターンが可能な限り何回でも適用され、リストも任意の長さですが、末尾の空の文字列は破棄されます。
私が使っていたのはsplit(regExp)でしたが、limitが0と同じ扱いになっていたのでしょうか。
limitに負の値を設定することで、末尾の空文字が破棄されなくなるようです。
というわけで、コードを修正して再挑戦です。
String csvData; List<String> rowList; String headerString; List<String> headerList; // CSVのヘッダ csvData = '列1,列2,列3,列4,列5' + '\r\n'; // CSVのデータ csvData += '1,2,3,4,5' + '\r\n'; csvData += '1,,,,' + '\r\n'; csvData += ',2,,,5' + '\r\n'; csvData += ',,3,,' + '\r\n'; csvData += ',,,4,' + '\r\n'; csvData += ',,,,5'; // 行ごとに分割する rowList = csvData.split('\r\n', 0); // 先頭行はヘッダ headerString = rowList.remove(0); // ヘッダを列に分ける headerList = headerString.split(',', -1); // 各行の処理を行う for(String rowString : rowList){ List<String> columnList; // 列に分割する columnList = rowString.split(',', -1); // ヘッダと列数が異なる場合、エラーとする if(headerList.size() != columnList.size()){ // エラー処理 system.debug('【エラー】' + rowString); continue; } system.debug('【正常】' + rowString); }
今度は正常に動作しました。
【正常】1,2,3,4,5 【正常】1,,,, 【正常】,2,,,5 【正常】,,3,, 【正常】,,,4, 【正常】,,,,5
行ごとの分割では空白行を考慮してlimitを0に設定しています。
splitを使う場合は注意しなければいけませんね。
No comments.