Skip to content

Instantly share code, notes, and snippets.

@mak-oh-1977
Created September 13, 2017 22:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mak-oh-1977/04e33d467b6604859462eb4f50578da4 to your computer and use it in GitHub Desktop.
Save mak-oh-1977/04e33d467b6604859462eb4f50578da4 to your computer and use it in GitHub Desktop.
固定長データパース
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