在我的上一篇博文: unity Excel读写 实现了unity下的Excel读写,但是这种读写方式在大规模读写的情况下,比方说次数过万的情况下,时间会很糟糕,所以本文提出了一种优化方法做优化,不多说,先放优化结果
可以看到,30万次的写入总共花费时长5s,没有改进的话写入几百次花费的时间就会超过这个时间。
30万次读取总共花费7s。
大概的思路就是之前的读写每次都会New很多类出来,new类是很费性能的,我们把需要的类记录下来下次使用,就可以节省很多时间。代码如下:
改进后的Excel写入代码
public static Dictionary<string, ExcelWorksheet> ExcelSheetDict;
public static Dictionary<string, ExcelPackage> ExcelPackageDict;
/// <summary>
/// 获取指定路径sheet的方式
/// </summary>
/// <param name="sheet"></param>
public static void GetPackageAndSheet(string excelPath, string sheetName)
{
if (ExcelPackageDict == null)
{
ExcelPackageDict = new Dictionary<string, ExcelPackage>();
ExcelSheetDict = new Dictionary<string, ExcelWorksheet>();
}
ExcelWorksheet worksheet;
if (ExcelSheetDict.ContainsKey(excelPath + sheetName))
{
return;
}
else
{
FileInfo newFile = new FileInfo(excelPath);
if (!newFile.Exists)
{
//不存在,创建
CreatEmptyExcel(excelPath);
newFile = new FileInfo(excelPath);
}
ExcelPackage package = new ExcelPackage(newFile);
worksheet = package.Workbook.Worksheets[sheetName];
if (worksheet == null)
{
//sheet不存在,创建
worksheet = package.Workbook.Worksheets.Add(sheetName);
}
ExcelSheetDict.Add(excelPath + sheetName, worksheet);
ExcelPackageDict.Add(excelPath + sheetName, package);
}
}
/// <summary>
/// 写入excel
/// </summary>
/// <param name="text">要写入的文本</param>
/// <param name="position">写入文本的位置,行序号和列序号</param>
/// <param name="excelPath">Excel的路径,包含excel名称</param>
/// <param name="sheetName">sheet名称,默认为sheet1</param>
/// <param name="isCreat">excel不存在时是否创建,默认创建</param>
/// <param name="isSave">写入完成时是否保存</param>
public static void WriteExcel(string text,int[] position, string excelPath, bool isSave = true, string sheetName = "sheet1", bool isCreat = true)
{
GetPackageAndSheet(excelPath, sheetName);
ExcelSheetDict[excelPath + sheetName].Cells[position[0], position[1]].Value = text;
if (isSave) ExcelPackageDict[excelPath + sheetName].Save();
}
测试代码:
int Count = 300000;
public void WriteTest()
{
//Excel置空,加速时间
ExportExcel.ClearExcel(ExportExcel.LangExcel);
int[] value = new int[2] { 1, 1 };
Log.Error("写入次数: " + Count + "次");
System.DateTime time = System.DateTime.Now;
Log.Error("写入开始时间: " + time.Hour + ":" + time.Minute + ":" + time.Second);
for (int i = 1; i < Count ; i++)
{
value[0] = i;
ExportExcel.WriteExcel(i.ToString(), value, ExportExcel.LangExcel, false);
}
time = System.DateTime.Now;
Log.Error("写入结束时间: " + time.Hour + ":" + time.Minute + ":" + time.Second);
ExportExcel.SavePackage(ExportExcel.LangExcel);
time = System.DateTime.Now;
Log.Error("保存结束时间: " + time.Hour + ":" + time.Minute + ":" + time.Second);
}
需要提醒的是,如果写入的Excel不是空的话,花费的时长会非常夸张,所以我的做法是创建新的Excel写入,如果不是新的Excel保存数据花费时间会很长。
上面是对写入的改写
public static Dictionary<string, DataSet> DataSetDict;
/// <summary>
/// ExcelDataReader方式读取数据,在读取包含非字符串格式的Excel(如数字等)会报错,但是读取 速度很快
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
public static string Read(string path, int[] position, bool isUpdaeDataSet = true)
{
if (DataSetDict == null)
{
DataSetDict = new Dictionary<string, DataSet>();
}
if (isUpdaeDataSet)
{
if (DataSetDict.ContainsKey(path)) DataSetDict.Remove(path);
}
if (!DataSetDict.ContainsKey(path))
{
FileStream stream = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read);
IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream);
DataSet result = excelReader.AsDataSet();
DataSetDict.Add(path, result);
}
object value;
string text;
try
{
value = DataSetDict[path].Tables[0].Rows[position[0]][position[1]];
}
catch (System.Exception)
{
text = string.Empty;
Log.Error("没那么多");
return text;
throw;
}
text = DataSetDict[path].Tables[0].Rows[position[0]][position[1]].ToString();
return text;
}
读取测试代码
/// <summary>
/// 读取测试,读取Count次
/// </summary>
public void ReadTestReader()
{
List<string> text = new List<string>();
int[] value = new int[2] { 0, 0 };
Log.Error("读取次数: " + Count + "次");
System.DateTime time = System.DateTime.Now;
Log.Error("读取开始时间: " + time.Hour + ":" + time.Minute + ":" + time.Second);
ExportExcel.Read(ExportExcel.LangExcel, value);
for (int i = 0; i < Count; i++)
{
value[0] = i;
text.Add(Read(ExportExcel.LangExcel, value,false));
}
time = System.DateTime.Now;
Log.Error("读取结束时间: " + time.Hour + ":" + time.Minute + ":" + time.Second);
}