套件的使用有使用上的方便性,但如果遇到效能問題,究竟誰勝誰負
FileHelper簡單介紹
官網上可以發現,有讀、寫功能,固定的長度或是特定符號分割例如CSV檔
例如電文是固定長度格式,那麼就可以採用官網上的Read Fixed File
Class需要如下列這樣編寫
[FixedLengthRecord()] //宣告該物件使用固定長度
public class FileModle
{
[FieldFixedLength(10)] //抓取長度10
[FieldTrim(TrimMode.Both)] //讀取後執行Trim
public string? Name { get; set; }
[FieldFixedLength(10)]
FieldTrim(TrimMode.Both)]
public string? Phone { get; set; }
[FieldFixedLength(100)]
[FieldTrim(TrimMode.Both)]
public string? Description { get; set; }
[FieldFixedLength(100)]
[FieldTrim(TrimMode.Both)]
[FieldOptional()] //如果該欄位不一定會有,則可以使用FieldOptional
[FieldNullValue(typeof(string), "")] //如果該欄位不一定會有,但也要給他初始值則可以使用FieldNullValue
public string? Else { get; set; }
}
用法可以如此編寫
var engine = new FixedFileEngine<FileModle>();
var result1 = engine.ReadFile(path);
在使用上確實非常簡潔可讀性也高,但如果有遇到大資料量時效能又是如何
所以本次利用常用的方式(SubString)來做個對比
環境:VS2022、Net6 Console
完整程式碼為
using FileHelpers;
using System.Text;
using TestFileHelper;
Console.WriteLine("Hello");
string path = @"e:\temp\MyTest.txt";
if (File.Exists(path))
{
File.Delete(path);
FileStream fs = File.Create(path);
string item = "1234567890098765432100000000001111111111222222222233333333334444444444555555555566666666667777777777888888888899999999998888888888999999999966666666667777777777444444444455555555552222222222333333333300000000001111111111";
int count = 1000000;
for (int i = 0; i < 1000000; i++)
{
string data = item;
if (i != count)
data += "\r\n";
byte[] info = new UTF8Encoding(true).GetBytes(data);
fs.Write(info, 0, info.Length);
}
fs.Close();
}
Console.WriteLine(DateTime.Now.ToString("HH:mm:ss.ffff") + " FileHelper Start");
var engine = new FixedFileEngine<FileModle>();
var result1 = engine.ReadFile(path);
Console.WriteLine(DateTime.Now.ToString("HH:mm:ss.ffff") + " FileHelper End");
Console.WriteLine(DateTime.Now.ToString("HH:mm:ss.ffff") + " SubString Start");
SubStringSplit subStringSplit = new();
var result2 = subStringSplit.Execute(path);
Console.WriteLine(DateTime.Now.ToString("HH:mm:ss.ffff") + " SubString End");
Console.ReadLine();
使用到兩個物件
using FileHelpers;
namespace TestFileHelper
{
[FixedLengthRecord()]
public class FileModle
{
[FieldFixedLength(10)]
[FieldTrim(TrimMode.Both)]
public string? Name { get; set; }
[FieldFixedLength(10)]
[FieldTrim(TrimMode.Both)]
public string? Phone { get; set; }
[FieldFixedLength(100)]
[FieldTrim(TrimMode.Both)]
public string? Description { get; set; }
[FieldFixedLength(100)]
[FieldTrim(TrimMode.Both)]
[FieldOptional()]
[FieldNullValue(typeof(string), "")]
public string? Else { get; set; }
}
public class SubStringSplit
{
public IList<FileModle> Execute(string path)
{
List<FileModle> result = new();
using StreamReader sr = new(path);
string? line = null;
while ((line = sr.ReadLine()) != null)
{
if(line.Length >= 120)
{
FileModle fileModle = new()
{
Name = line.Substring(0, 10).Trim(),
Phone = line.Substring(10, 10).Trim(),
Description = line.Substring(20, 100).Trim()
};
if (line.Length == 220)
fileModle.Else = line.Substring(120, 100).Trim();
else
fileModle.Else = "";
result.Add(fileModle);
}
}
return result;
}
}
}
本次使用一百萬筆的數據量,可以看到大約都在三秒上下,相差0.2~0.5秒左右
但如果觀看記憶體的使用量呢
FileHelper花費3.322秒,記憶體使用931MB
SubString花費2.941秒,記憶體使用761MB
最後總結SubString在一百萬筆的資料量下,效能略勝,且記憶體使用的少
資料來源參考