项目中比较多的会对文件进行操作,例如文件的上传下载,文件的压缩和解压等IO操作。在.NET项目中较多的会使用DataSet,DataTable进行数据的缓存。
项目中对文本文件的操作比较简单,但是如果需要将文本文件的内容写入系统的缓存中,操作起来,会稍微的繁琐一些。现在总结一个较为通用的方法,将文本文件的内容缓存进入DataSet数据集中。
private DataSet _iifSet;
/// <summary>
/// 将文本文件转化为DataSet
/// </summary>
/// <param name="filePath"></param>
/// <returns></returns>
public DataSet Parse(string filePath)
{
if (string.IsNullOrEmpty(filePath)) { throw new ArgumentNullException(filePath); }
try
{
_iifSet = new DataSet();
var fileText = System.IO.File.ReadAllText(filePath);
var lines = fileText.Split('\n');
CreateTables(lines, _iifSet);
FillSet(lines, _iifSet);
return _iifSet;
}
catch (IOException ex)
{
throw new IOException(ex.Message);
}
}
/// <summary>
/// 读取行数组并将其解析为数据集的表
/// </summary>
/// <param name="lines">String iif文件中的行数组</param>
/// <param name="set"></param>
private void FillSet(IReadOnlyList<string> lines, DataSet set)
{
for (var i = 0; i < lines.Count; i++)
{
if (IsTableHeader(lines[i]))
{
continue;
}
if (lines[i] == "" || lines[i] == "\r" || lines[i] == "\n\r" || lines[i] == "\n")
{
continue;
}
if (lines[i].IndexOf(";__IMPORTED__", StringComparison.Ordinal) != -1)
{
continue;
}
var line = lines[i];
while (!IsFullLine(line, set))
{
i++;
line += lines[i];
}
ParseRecord(line, set);
}
}
/// <summary>
/// 解析记录
/// </summary>
/// <param name="line"></param>
/// <param name="set"></param>
private void ParseRecord(string line, DataSet set)
{
if (IsTableHeader(line))
{
return;
}
var tablename = line.Split('\t')[0];
var parameters = CreateDataRowParams(line, set.Tables[tablename].Columns.Count);
if (parameters.Length > 0)
set.Tables[tablename].Rows.Add(parameters);
}
private bool IsFullLine(string line, DataSet set)
{
if (IsTableHeader(line))
{
return true;
}
var values = line.Split('\t').Length;
var tableName = line.Split('\t')[0];
var columns = set.Tables[tableName].Columns.Count;
return values >= columns;
}
private bool IsTableHeader(string tab)
{
return tab.StartsWith("!");
}
/// <summary>
/// 创建datatable
/// </summary>
/// <param name="lines"></param>
/// <param name="set"></param>
private void CreateTables(IReadOnlyList<string> lines, DataSet set)
{
foreach (var t in lines.Where(IsTableHeader))
{
set.Tables.Add(CreateTable(t));
}
}
private DataTable CreateTable(string line)
{
var values = line.Split('\t');
values[0] = values[0].Substring(1);
var dt = new DataTable(values[0]);
values[0] = null;
foreach (var name in values)
{
if (string.IsNullOrEmpty(name))
continue;
var dc = new DataColumn(name, typeof(string));
try
{
dt.Columns.Add(dc);
}
catch (DuplicateNameException)
{
dc = new DataColumn(name + "_duplicateCol" + dt.Columns.Count);
dt.Columns.Add(dc);
}
}
return dt;
}
public string GetTableName(string line)
{
var values = line.Split('\t');
if (values[0].StartsWith("!"))
{
values[0] = values[0].Substring(1);
}
return values[0];
}
public readonly static object[] EmptyStringArray = { };
private object[] CreateDataRowParams(string line, int maxLength)
{
var raw = line.Split('\t');
var length = raw.Length - 1;
if (length == 0 || maxLength == 0)
return EmptyStringArray;
if (length > maxLength)
length = maxLength;
var values = new string[length];
for (var i = 0; i < length; i++)
{
values[i] = raw[i + 1];
}
if (values[values.Length - 1].EndsWith("\n"))
{
values[values.Length - 1] = values[values.Length - 1].Substring(0, values[values.Length - 1].LastIndexOf('\n'));
}
else if (values[values.Length - 1].EndsWith("\n\r"))
{
values[values.Length - 1] = values[values.Length - 1].Substring(0, values[values.Length - 1].LastIndexOf("\n\r", StringComparison.Ordinal));
}
else if (values[values.Length - 1].EndsWith("\r"))
{
values[values.Length - 1] = values[values.Length - 1].Substring(0, values[values.Length - 1].LastIndexOf('\r'));
}
return values;
}
protected virtual void Dispose(bool cleanAll)
{
_iifSet?.Dispose();
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
有关dataset的一些常用的操作,基本属性和方法在这里就不做介绍了。