パディングを使いこなせ(空白埋めやゼロ埋め)
固定長IFファイルの作成では必要不可欠な処理、パディング。
文字長を一定にしたり、ブラの隙間に夢を詰めたりいろんな使い方がされる。
このエントリでは以下の3種類の方法を紹介する。
- 基本的なパディング(String.Format)
- 指定の文字でパディング(PadLeft、PadRight)
- マルチバイト文字が含まれるパディング(応用編)
基本的なパディング
空白埋め
まずは文字列を指定の桁になるまで空白(スペース)で埋める方法
string value = "test"; // "______test" String.Format("{0, 10}", value); // "test______" String.Format("{0, -10}", value);
{0}はString.Formatでよく使われるインデックス番号。
カンマ以降の数字で桁数を決める。プラスなら右寄せ、マイナスなら左寄せと言った感じ
ゼロ埋め
次に数値を指定の桁になるまでゼロで埋める方法
int value = 123; // "0000000123" String.Format("{0:D10}", value); // "0000000123" String.Format("{0:0000000000}", value); // "____000123" String.Format("{0, 10:D6}", value);
文字列のときとはちょっと変わって、{0:D桁数}もしくは{0:桁数分の0}のように指定する。
最終行は{0, 全体桁数:ゼロ埋め桁数}となる。
ちなみにvalueに文字列を入れるとゼロ埋めされないので注意!
また数値型でもdecimalやdoubleはFormatExceptionになるので要注意!
じゃぁ、decimalやdouble型でゼロ埋めしたり、他の文字で埋めるにはどうすりゃいいのさ?
指定の文字でパディング
String.Formatではパディングできないdecimalやdouble。
空白やゼロ以外でパディングする場合。
などは、以下のような方法で対応可能。
decimal value = 123M; // "0000000123" value.ToString().PadLeft(10, '0'); // "1230000000" value.ToString().PadRight(10, '0'); // "xxxxxxx123" value.ToString().padLeft(10, 'x');
こんな感じでPadLeft()、PadRight()を使うことで解決できる。
Oracleとか使ってる人にはこっちのほうが馴染み深いかも(LPADやRPADみたいな)
文字はchar型のため、シングルクォーテーションで括る必要がある。
ちなみに第2引数の文字を省略すると空白で埋められる。
マルチバイト文字が含まれるパディング
実は上記で説明してきたパディングはマルチバイト文字(日本語とか)を入力するといろいろとおかしくなる。
例えば、"あいう".PadLeft(10)とすると"△△△△△△△あいう”となってしまう。
※△は半角スペース
バイトではなく桁数で埋められているため、こんなんで固定長IFファイルなんて作ったら……。
じゃぁ、どうするのか?
「埋めるバイト数」から「文字列のバイト数」と「文字列の長さ」を引いて分だけ埋めれば良い。
// 文字列.PadRight(桁数 - (文字列のバイト数 - 文字列の長さ)); value.PadRight(10 - (Encoding.GetEncoding("Shift_JIS").GetByteCount(value) - value.Length));
仕事で使った具体的な実装例は以下の通り。
// 項目属性の列挙体 enum PadType { Char ,Number } // パディング処理 public string PaddingInBytes(string value, PadType type, int byteCount) { Encoding enc = Encoding.GetEncoding("Shift_JIS"); if (byteCount < enc.GetByteCount(value)) { // valueが既定のバイト数を超えている場合は、切り落とし value = value.SubString(0, byteCount); } switch (type) { case PadType.Char: // 文字列の場合 左寄せ+空白埋め return value.PadRight(byteCount - (enc.GetByteCount(value) - value.Length)); case PadType.Number: // 数値の場合 右寄せ+0埋め return value.PadLeft(byteCount, '0'); default: // 上記以外は全部空白 return value.PadLeft(byteCount); } } static Main(string[] args) { Console.WriteLine(this.PaddingInBytes("あいう", PadType.Char, 10)); Console.WriteLine(this.PaddingInBytes("123", PadType.Number, 15)); }
ってな感じ。
あえて列挙体で「Char」なのか「Number」なのか指定しているけど、typeofで型を引数に渡してあげても同様のことができる。
http://kuroeveryday.blogspot.jp/2014/03/padding.html より転載