Created
September 13, 2017 22:41
-
-
Save mak-oh-1977/04e33d467b6604859462eb4f50578da4 to your computer and use it in GitHub Desktop.
固定長データパース
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Linq; | |
using System.Reflection; | |
using System.Text; | |
using System.Threading.Tasks; | |
namespace FixedData | |
{ | |
[FixedTextFile(Encode = "Shift_JIS")] | |
public class Todofuken | |
{ | |
/// <summary> | |
/// 都道府県コード | |
/// </summary> | |
[Fixed(ByteLength = 2)] | |
public string Code { set; get; } | |
/// <summary> | |
/// 都道府県名 | |
/// </summary> | |
[Fixed(ByteLength = 10)] | |
public string Name { set; get; } | |
/// <summary> | |
/// コンストラクタ | |
/// </summary> | |
/// <param name="code">都道府県コード</param> | |
/// <param name="name">都道府県名</param> | |
public Todofuken(string code, string name) | |
{ | |
this.Code = code; | |
this.Name = name; | |
} | |
public Todofuken() | |
{ | |
} | |
} | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
var a = new Todofuken("1", "北海道"); | |
//固定長ファイルを出力する | |
string s = FixedTextFileAttribute.Convert2FixedText<Todofuken>(a); | |
Console.WriteLine(s); | |
var b = (Todofuken)FixedTextFileAttribute.Convert2Object<Todofuken>(s); | |
Console.WriteLine("code=" + b.Code + ":Name=" + b.Name); | |
} | |
} | |
/// <summary> | |
/// クラス、構造体の固定長ファイル出力定義用属性 | |
/// </summary> | |
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)] | |
public class FixedTextFileAttribute : Attribute | |
{ | |
/// <summary> | |
/// エンコード | |
/// </summary> | |
public string Encode; | |
/// <summary> | |
/// クラスまたは構造体に定義されたエンコーディングを取得する | |
/// </summary> | |
/// <typeparam name="T">対象のクラス、構造体</typeparam> | |
/// <returns>エンコード</returns> | |
public static Encoding GetEncoding<T>() | |
{ | |
var encAttr = Attribute.GetCustomAttribute( | |
typeof(T), typeof(FixedTextFileAttribute)) as FixedTextFileAttribute; | |
return Encoding.GetEncoding(encAttr.Encode); | |
} | |
/// <summary> | |
/// 指定された属性に従って固定長テキストを作成して返す | |
/// </summary> | |
/// <typeparam name="T">出力対象データクラス、構造体</typeparam> | |
/// <param name="o">出力データが格納されたオブジェクト</param> | |
/// <returns></returns> | |
public static string Convert2FixedText<T>(object o) | |
{ | |
var values = (T)o; | |
//指定されたエンコードを取得する | |
Encoding enc = GetEncoding<T>(); | |
//データを固定長文字列にする | |
StringBuilder result = new StringBuilder(); | |
foreach (PropertyInfo info in typeof(T).GetProperties()) | |
{ | |
//出力対象除外項目判定:Reject属性が設定されている項目を除外する | |
var reject = Attribute.GetCustomAttribute(info, typeof(RejectAttribute)); | |
if (reject != null) | |
{ | |
continue; | |
} | |
//固定長定義属性を取得する | |
var fixedAttr = Attribute.GetCustomAttribute( | |
info, typeof(FixedAttribute)) as FixedAttribute; | |
//属性が設定されていないならその項目を出力対象から除外する | |
if (fixedAttr == null) | |
{ | |
continue; | |
} | |
//出力項目値を出力する | |
string value = info.GetValue(values, null).ToString(); | |
//指定バイトを超えている場合、後ろから1文字づつ削って指定バイトに調整する | |
while (fixedAttr.ByteLength < enc.GetByteCount(value)) | |
{ | |
value = value.Substring(0, value.Length - 1); | |
} | |
//不足長を指定文字で埋める | |
//※PadRight,PadLeftの指定桁は文字数であり、バイト数ではない。 | |
// 従って、不足バイト数ではなく不足文字数に換算して指定する | |
int padLen = fixedAttr.ByteLength - (enc.GetByteCount(value) - value.Length); | |
result.Append(value.PadRight(padLen, ' ')); | |
} | |
return result.ToString(); | |
} | |
public static object Convert2Object<T>(string s) | |
{ | |
var ret = (T)Activator.CreateInstance<T>(); | |
int pos = 0; | |
foreach (PropertyInfo info in typeof(T).GetProperties()) | |
{ | |
//出力対象除外項目判定:Reject属性が設定されている項目を除外する | |
var reject = Attribute.GetCustomAttribute(info, typeof(RejectAttribute)); | |
if (reject != null) | |
{ | |
continue; | |
} | |
//固定長定義属性を取得する | |
var fixedAttr = Attribute.GetCustomAttribute( | |
info, typeof(FixedAttribute)) as FixedAttribute; | |
//属性が設定されていないならその項目を出力対象から除外する | |
if (fixedAttr == null) | |
{ | |
continue; | |
} | |
var v = s.Substring(pos, fixedAttr.ByteLength); | |
info.SetValue(ret, v); | |
pos += fixedAttr.ByteLength; | |
} | |
return ret; | |
} | |
} | |
/// <summary> | |
/// 項目毎の固定長出力定義属性 | |
/// </summary> | |
[AttributeUsage(AttributeTargets.Property)] | |
public class FixedAttribute : Attribute | |
{ | |
//バイト長 | |
public int ByteLength; | |
} | |
/// <summary> | |
/// 固定長出力しない項目を指定するための属性 | |
/// </summary> | |
[AttributeUsage(AttributeTargets.Property)] | |
public class RejectAttribute : Attribute | |
{ | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment