using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
/// <summary>
/// 欄位定義
/// </summary>
public class FieldDef
{
/// <summary>
/// 欄位名稱
/// </summary>
public string FieldName;
/// <summary>
/// 起啟位置
/// </summary>
public int StartPos = -1;
/// <summary>
/// 欄位長度
/// </summary>
public int Length;
/// <summary>
/// 建構式
/// </summary>
/// <param name="fldName">欄位名稱</param>
/// <param name="len">欄位長度</param>
public FieldDef(string fldName, int len)
{
FieldName = fldName;
Length = len;
}
}
/// <summary>
/// 固定寬度文件解析
/// </summary>
public class FixedWidthTextParser
{
List<FieldDef> fields = new List<FieldDef>();
Encoding encoding;
int lineLength = 0;
/// <summary>
/// 建構式,傳入文件定義
/// </summary>
/// <param name="enc">文字編碼</param>
/// <param name="def">欄位定義</param>
public FixedWidthTextParser(
Encoding enc,
params FieldDef[] def)
{
encoding = enc;
int startPos = 0;
foreach (FieldDef fd in def)
{
fd.StartPos = startPos;
fields.Add(fd);
startPos += fd.Length;
lineLength += fd.Length;
}
}
/// <summary>
/// 傳入單行資料字串,解析為多欄值
/// </summary>
/// <param name="line">原始單行資料字串</param>
/// <returns>各欄位值之雜湊表</returns>
public Dictionary<string, string> ParseLine(string line)
{
//資料字串轉為byte[]
byte[] data = encoding.GetBytes(line);
//檢查長度是否吻合?
if (data.Length != lineLength)
throw new ApplicationException(
string.Format("字串長度({0}Bytes)不符要求({1}Bytes)!",
data.Length, lineLength));
//宣告雜湊結構存放資料
var result = new Dictionary<string, string>();
//依欄位位置、長度逐一取值
foreach (var fd in fields)
result.Add(fd.FieldName, //由指定位置取得內容並截去尾端空白
encoding.GetString(data, fd.StartPos, fd.Length).Trim());
return result;
}
/// <summary>
/// 解析多行固定欄寬資料
/// </summary>
/// <param name="text">多行文字資料</param>
/// <returns>解析結果</returns>
public List<Dictionary<string, string>> Parse(string text)
{
var all = new List<Dictionary<string, string>>();
using (StringReader sr = new StringReader(text))
{
string line = null;
while ((line = sr.ReadLine()) != null)
all.Add(ParseLine(line));
}
return all;
}
/// <summary>
/// 解析固定欄寬資料檔
/// </summary>
/// <param name="path">檔案路徑</param>
/// <returns>解析結果</returns>
public List<Dictionary<string, string>> ParseFile(string path)
{
if (!File.Exists(path))
throw new ApplicationException(path + "不存在!");
return Parse(File.ReadAllText(path, encoding));
}
}