この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
Talendには様々なコンポーネントが用意されていますが、細かいところはコードを書いて対応したいという事があります。その時には「tJava」を使用すれば解決します。 TalendはEclipseを元に開発されている様なので、プログラミング画面はまんまEclipseです。
環境
Mac OSX 10.10.5 Yosemite Talend Open Studio for Data Integration 5.6.2 JDK 1.7.0_79
プログラムの目的
TSVファイルの項目別の対応でマスキングし、新規TSVファイルを出力する。
TSV
id name post address tel
12345678901 madonna louise ciccone 010-1101 神奈川県横浜市XX区YY町111 045-011-0011
23456789012 prince rogers nelson 011-0010 埼玉県三郷市YY町010 070-1100-1100
34567890123 michael joseph jackson 110-1001 千葉県船橋市YY町101 090-1001-0110
45678901234 中田 ヤステル 222-2222 東京都中野区XX222 080-2222-2222
56789012345 小室 哲夫 333-3333 東京都府中市YY町333 080-3333-3333
左から、登録番号、登録者名、郵便番号、住所、電話番号。
Talend:コンポーネント配置
Talend:コンポーネント設定
tFileInputDelimited
TSVを読み込むコンポーネント。
基本設定
ファイル名/ストリーム: 読み込むファイルパス 行区切り記号: 改行コード フィールド区切り記号: 今回はTSVなので「\t」 ヘッダー: TSVのヘッダーは不要なので「1」 スキーマの編集: 押下してTSVとレイアウトを合わせたものを作成。「➕」でカラム追加できます。
Advanced setting
エンコード: 任意の文字コード(今回はUTF-8)
tJava
Javaコードを書いてメソッドを定義できます。 使用するメソッドは下のの様に書いておきます。コード内容は後述。
tMap
tMapアイコンをダブルクリックするか、「コンポーネント」>「基本設定」>「マップエディタ」を押下してウィンドウを開き、下の画像の様に設定します。 カラム名をドラッグして真ん中のウィンドウ(「Var」と表示されている箇所)に持っていくとtMapに登録されます。 項目「式」にtJavaで設定したメソッドを記述できます。 設定したら、「tFileOutputDelimited」の対応するカラム名にドラッグして接続して完成。 最初はカラム名が表示されていないと思うので、先に「tFileOutputDelimited」で「カラム名の同期」を実行しておくと楽です。
各カラムのtMapの設定は下記の様にします。
SampleClass.maskingId(row2.id)
SampleClass.toHeadUpper(SampleClass.maskingName(row2.name))
SampleClass.maskingPostal(row2.postal)
SampleClass.maskingAddress(row2.address)
SampleClass.maskingNumber(row2.tel)
tFileOutputDelimited
TSVを出力します。
基本設定
ファイル名: TSVファイルの出力先パス 行区切り記号: 改行コード フィールド区切り記号: TSVなので「\t」 ヘッダーを含むにチェックを入れれば、Talendで設定したカラム名がヘッダーになります。
Advanced settings
ここはお好みで。
tJavaでコード作成
準備
1、画面左のリポリジトリの「コード」を右クリックして「フォルダを作成」。 2、作成したフォルダを右クリックして「コードを作成」。 3、Eclipseライクなプログラミング画面が表示されます。
必要なメソッド
今回はカラムごとにマスキング方法が違うので、下記を用意します。
カラム名 | 対応するメソッド | 内容 |
---|---|---|
id | maskingId | 登録ID。3〜7桁目を「*」に置換。 |
name | maskingName | 登録者名。最初と最後の文字を「*」に置換。 |
name | toHeadUpper | 登録者名の頭文字が半角英字の場合に頭文字を大文字にする。 |
postal | maskingPostal | 郵便番号。「-」を削除し、下4桁を「*」に置換。 |
address | maskingAddress | 住所。2〜4、6〜8、10〜14文字目を「*」に置換。 |
tel | maskingNumber | 電話番号。「-」以外を全て「*」に置換。 |
マスキング処理のコード作成
package routines;
public class SampleClass {
/**
* {talendTypes} String
* {Category} User Defined
* 3〜7文字を「*」にする。
* @return
*/
public static String maskingId(String input) {
StringBuilder sb = new StringBuilder();
if (input != null) {
// 引数の文字列を分割
for (int i = 0; i < input.length(); i++) {
// 分割した文字の3〜7文字目()を「*」に置換。
if (i>=2 && i<=6) {
sb.append("*");
}
// それ以外はそのまま。
else {
sb.append(input.substring(i, i+1));
}
}
return sb.toString();
}
return input;
}
/**
* {talendTypes} String
* {Category} User Defined
* 引数の文字列の最初と最後を「*」に置換する。
* @param input
* @return
*/
public static String maskingName(String input) {
// 前後の空白を削除
input = input.trim();
// 名前の文字数を取得
int count = input.length();
// 引数の文字数で分岐
if (count > 1) {
// 準備
String asterisk = "*";
String output = "";
StringBuilder sb = new StringBuilder();
for (int i = 0; i < count; i++) {
// 最初と最後は「*」
if (i==0 || i==count-1) {
sb.append(asterisk);
} else {
sb.append((input.substring(i, i+1)));
}
}
output = sb.toString();
return output;
} else if (count == 1) {
// 1文字なので「*」を返す。
return "*";
} else {
// 0文字なので入力された引数をそのまま返す。
return input;
}
}
/**
* {talendTypes} String
* {Category} User Defined
* 引数の文字列をfirst,middle,lastに分け、それぞれの頭文字を大文字にする。
* @param input
* @return
*/
public static String toHeadUpper(String input) {
// 準備
StringBuilder sb = new StringBuilder();
String output = "";
// 1.文字列を空白で分割
String[] strSplit = input.split(" ");
int splitLength = strSplit.length;
// 2.分割した要素分(苗字と名前など)、頭文字を大文字にする
for (int j = 0; j < splitLength; j++) {
sb.setLength(0); // ループ毎に初期化
// 3.頭文字を抽出
String top = strSplit[j].substring(0,1);
// 4.頭文字が正規表現で先頭が[a-z]の場合
// 正規化の準備(英字小文字の場合は頭文字を大文字にする)
Pattern p = Pattern.compile("^[a-z]"); // 文字列の先頭が[a-z]
if (p.matcher(top).find()) {
// 4-1.文字目以降の文字列を取得
String end = strSplit[j].substring(1, strSplit[j].length());
// 4-2.先頭を大文字に置換
sb.append(top.toUpperCase());
sb.append(end);
} else {
// 4.先頭が英字小文字でない場合はそのままSBに結合
sb.append(strSplit[j]);
}
// 5.名前同士の間に半角空白入れる(最後じゃない場合)
if (j != splitLength-1) {
sb.append(" ");
}
output += sb.toString();
}
// 最初と最後を「*」に置き換えた文字列を返す。
return output;
}
/**
* {talendTypes} String
* {Category} User Defined
* "-"を削除。郵便番号で使用。
* @return
*/
public static String maskingPostal(String input) {
// 「-」を削除して、右から4桁を「*」に置換
return input.substring(0, 3) + "****";
}
/**
* {talendTypes} String
* {Category} User Defined
* 住所の2〜4、6〜8、10〜14文字目を*に置換する。
* @return
*/
public static String maskingAddress(String input) {
if (input != null) {
StringBuilder sb = new StringBuilder();
// 引数の文字列を分割
for (int i = 0; i < input.length(); i++) {
// 分割した文字の2〜4、6〜8、10〜14文字目を「*」に置換。
if ((i>=1 && i<=3) || (i>=5 && i<=9) || (i>=11 && i<=15)) {
sb.append("*");
}
// それ以外はそのまま。
else {
sb.append(input.substring(i, i+1));
}
}
// 文字列を返す。
return sb.toString();
}
return input;
}
/**
* {talendTypes} String
* {Category} User Defined
* 電話番号が"-"以外を「*」に変換して返す。
* @param number 電話番号。
* @return String
*/
public static String maskingNumber(String number) {
char[] c = number.toCharArray();
StringBuilder sb = new StringBuilder();
/*
* Stringをchar配列に分割し、一文字ずつ条件に当てはめて行く。
* '-'ではなく、15文字より手前なら、「*」をStringに入れる。
* それ以外は、charをそのままStringに入れる。
*/
for (int i = 0; i < c.length; i++) {
if (c[i]!='-') {
sb.append("*");
}
else {
sb.append(Character.toString(c[i]));
}
}
// 文字列を返す
return sb.toString();
}
}
注意点:メソッドは「public static」とします。「private」にするとtMapで利用できなかったと思います。
また、メソッドのドキュメンテーションコメントに下記を書いておくとtMapの式ビルダのカテゴリ「ユーザー定義」に表示されます。
/**
* {talendTypes} String
* {Category} User Defined
*/
実行結果
id name postal address tel
12*****8901 *adonna Louise Ciccon* 010**** 神***横*****Y***** ***-***-****
23*****9012 *rince Rogers Nelso* 011**** 埼***郷*****1* ***-****-****
34*****0123 *ichael Joseph Jackso* 110**** 千***橋*****0* ***-****-****
45*****1234 *田 ヤステ* 222**** 東***野*****2 ***-****-****
56*****2345 *室 哲* 333**** 東***中*****3* ***-****-****
さいごに
今回は文字をマスキングする方法を書きましたが、カラム自体を隠してしまう方法もあります。