c# - 处理和删除文件中的行,如果发送 CancellationToken 则停止
问题描述
我必须处理包含路径和状态信息的文件的行,并为该行/路径启动上传操作。在某些情况下上传可能失败,所以我必须保留该行,在其他情况下,可以在上传成功时删除该行。主要问题是,一切都在后台运行,用户可以随时关闭软件。在这种情况下,我设置了一个 Cancellation-token 并且文件操作完成。到现在为止,文件总是很小。所以我将所有仍然需要的行复制到一个新文件中并替换了旧文件。简化代码:
bool valid=false;
bool cancelled=false;
using (StreamWriter sw = new StreamWriter(filename_tmp, false))
{
try
{
using (StreamReader sr = new StreamReader(filename)) //alternative:
// foreach (string line in File.ReadLines(filename))
{
// process each line of file
while (sr.Peek() >= 0)
{
string line = sr.ReadLine();
rowCnt++;
//separate line into content:
string[] content = line.Split(delimiter);
if (canceltoken.IsCancellationRequested && (rowCnt > 3))
{
cancelled = true;
}
else
{
data_path = content[0];
//start upload:
valid = UploadData(data_path);
}
if( cancelled || valid==false)
{
sw.WriteLine("{0},{1},{2},{3}", data_path, uploadCnt,
DateTime.Now.ToString(), errorMsg);
}
}
}
}
}
File.Replace(filename_tmp, filename, filename_backup);
现在我们遇到文件可能变得非常大的情况,我担心将所有内容复制到新文件中会花费太长时间。用户当前收到一条消息,表明仍有进程在运行,软件将在之后关闭。1-5 秒后,软件关闭。现在需要更长的时间,我不希望用户使用任务管理器来终止进程。处理行并在之后删除它的最佳方法是什么?我对文件有完全的控制权,因为我写了它。所以我可以自己定义格式和作者(例如StreamWriter
vs. BinaryWriter
)。
我想到了两种可能的选择:
- 处理整个文件。为每一行设置一个状态标志(如 1=删除我,2=必须处理/保留)。处理完文件后,再次遍历行并复制所需的行。如果取消,请保留旧文件。
我很想做类似的事情:
var linesToKeep = File.ReadLines(fileName).Where(l => l.Contains("remove me") ==false);
File.WriteAllLines(tempFile, linesToKeep);
但这需要我写到同一行来更改状态。我不确定那是否有效。我可以使用 BinaryWriter 来覆盖“标志”,但是我不能使用上面的行并且需要再次遍历每一行。
- 使用 seek 从最后处理文件。如果我使用 a
BinaryWriter
我会确切地知道线条的长度,所以这不会是一个问题。在额外文件中写入需要再次处理的错误行。使用 .在最后处理的行“剪切”原始文件FileStream.SetLength
。这将产生 2 个文件(原始文件包含未处理的行,第二个文件包含需要再次处理的行)。但我还不知道如何处理额外的文件。下次我开始时我可以先处理这个,但后来我可能会得到越来越多的文件,这似乎是错误的。
我不知何故被困在这里,我不知道如何进一步进行。任何提示将不胜感激。
解决方案
我不会在取消后写入(或标记)所有未处理的行,而是反转问题:定义所有作业(每行一个),将其写入“队列”并在上传完成后将其删除。
要保留您的队列,您可以使用LiteDb。它是一个小巧方便的 NoSQL 文件数据库,因此您没有 OR Mapper 的开销。
逻辑可能如下所示:
- 使用您的内容和一些附加属性(URL,...)定义 UploadJob 类
- 将作业列表写入 LiteDB 集合。
- 迭代每个作业。
- 作业成功完成后,在 LiteDB 中删除此项目。
推荐阅读
- d3.js - 在 d3.js 中将对象拖放到 SVG 元素上
- haskell - ghc的代码覆盖率是如何实现的?它会抑制优化吗?
- kubernetes - 如何将 Kubernetes 变量插入 ConfigMap YAML 文件中的 JSON?
- python - 删除列并制作下一行?
- python - 如何使用opencv从图中删除另一个对象?
- r - R data.frame中多个变量的每小时平均值?
- java - Openshift 上的 Vault 服务器 - 连接被拒绝
- c++ - 如何使用imgui在OpenGL c++中制作一个按钮
- c# - 每个 CRUD .net Framework API 上的 401
- python - svglib - 将 SVG 转换为具有透明背景的 PNG?