并发读取和写入Excel文件

时间:2019-01-17 08:19:57

标签: c# .net file epplus epplus-4

是否可以只对一个进程执行WRITE操作,而对一个Excel文件执行许多读操作?我为此使用ExcelPackage(EPPlus)。

为了演示,我编写了两个控制台应用程序,一个用于迭代编写,另一个用于读取。同时运行它们会在任何一方导致故障。

// simply write to a column
var fileLocation = "D:\\Book.xlsx";
FileInfo fi = new FileInfo(fileLocation);

int i = 1;
while (1 == 1)  //ALERT: an infinite loop!
{
    using (ExcelPackage excelPackage = new ExcelPackage(fi))
    {
        ExcelWorksheet worksheet = excelPackage.Workbook.Worksheets["Sheet1"];
        var row = worksheet.Row(2);

        worksheet.Cells[$"A{i}"].Value = "Test " + i.ToString();
        excelPackage.Save();
        i++;
    }
}

阅读

//simply populate a list reading excel
var fileLocation = "D:\\Book.xlsx";
FileInfo fi = new FileInfo(fileLocation);
List<string> list = new List<string>();
ExcelWorksheet worksheet = null;
int i = 1;
while (1 == 1)  //ALERT: an infinite loop!
{
    using (ExcelPackage excelPackage = new ExcelPackage(fi))
    {
        worksheet = excelPackage.Workbook.Worksheets["Sheet1"];
        if (worksheet.Cells[i, 1].Value != null)
        {
            list.Add(worksheet.Cells[i, 1].Value.ToString());
        }
    }

    list.Clear();
}

2 个答案:

答案 0 :(得分:5)

我通过使WRITE程序在写入和读取之前锁定文件来稍作更改,从而在发生故障时恢复了弹性:

写:尝试尝试之前,使用FileStream并将其锁定。这样可以防止WRITE失败

读取:添加了实现try / catch块的重试机制

修改后的代码:

boy.png

阅读

// simply write to a column
var fileLocation = "D:\\Book.xlsx";
FileInfo fi = new FileInfo(fileLocation);

int i = 1;
while (1 == 1)  //ALERT: an infinite loop!
{

    using (ExcelPackage excelPackage = new ExcelPackage(fi))
    {
        ExcelWorksheet worksheet = excelPackage.Workbook.Worksheets["Sheet1"];
        worksheet.Cells[$"A{i}"].Value = "Test " + i.ToString();

        using (var fs = new FileStream(fileLocation, FileMode.Open, FileAccess.ReadWrite, FileShare.Read))
        {
            fs.Lock(0, fs.Length);
            excelPackage.SaveAs(fs);
            try
            {
                fs.Unlock(0, fs.Length); // this raises an exception if fs unlocked already by itself
            }
            catch (IOException ex) when (ex.Message.ToLower().StartsWith("the segment is already unlocked.",
                StringComparison.InvariantCultureIgnoreCase))
            {
                // NOP; just ignore if already unlocked
            }
        }
        i++;
    }
}

在实际应用的代码中,如果第一次读取尝试失败,我将READ'S WHILE的限制设置为3,以重试两次。在我看来,这已经绰绰有余了(因为WRITEs很短;每次添加一行),并且该应用程序运行了一个多月。

答案 1 :(得分:1)

读取文件时,不能同时锁定同一文件,因为它被锁定。您可以将整个文件读到内存中,然后可以对其进行处理,处理后可以将其写回。