c#文件分割问题
Issues with file splitting with c#
我一直在尝试制作一个程序,将较大的文本文件拆分成较小的部分,以便更易于使用。
我目前有两个问题,无法弄清楚发生了什么。
问题一:后台worker有时会触发多次。我似乎无法弄清楚它决定 运行 的原因或次数。它将 运行 拆分并在最终文件上似乎循环回到工作的开始并再次 运行 。它还会触发多个 do work 已完成的任务。使事情复杂化的是,如果我将拆分的文件数设置为不同的数字,我可以获得不同的后台工作人员似乎触发的次数,但它与文件数没有直接关联。有时相同数量的文件会导致后台工作程序只触发一次,有时会触发多次。
问题2:有时拆分不会创建所有文件。对于某些文件,如果我 运行 它会创建前两个文件,然后删除其余文件。似乎只有当我将数字设置为 3 个要拆分的文件时才会发生。如果我把行数加起来,它应该是正确的。所以我不确定那里发生了什么。
调用线程
private void StartSplit()
{
if (int.TryParse(NumberOfFilesTB.Text, out _numberOfFiles))
{
if (bg.IsBusy)
{
((MainWindow)Application.Current.MainWindow).SetStatus("Warning",
"Please only run one split process at a time.");
return;
}
((MainWindow)Application.Current.MainWindow).DisplayAlert(
"Split is running, you will receive an alert when it has finished. You may use other tools while the split is running.");
var args = new List<string> { _filepath, _includeHeaders.ToString(), _numberOfFiles.ToString() };
bg.DoWork += bg_DoWork;
bg.WorkerReportsProgress = true;
bg.ProgressChanged += ProgressChanged;
bg.RunWorkerCompleted += bg_RunWorkerCompleted;
bg.WorkerSupportsCancellation = true;
bg.RunWorkerAsync(args);
ProcessText.Text = "Running split process";
}
else
{
((MainWindow)Application.Current.MainWindow).SetStatus("Warning", "Please enter a number for number of files");
}
}
后台线程
private void bg_DoWork(object sender, DoWorkEventArgs e)
{
var args = e.Argument as List<string>;
string filepath = args[0];
string includeHeaders = args[1];
int numberOfFiles = Convert.ToInt32(args[2]);
int numberOfRows = _lineCount / numberOfFiles;
_tempath = Path.GetDirectoryName(_filepath);
Directory.CreateDirectory(_tempath+"\split");
if (includeHeaders == "True")
{
using (var reader = new StreamReader(File.OpenRead(filepath)))
{
_lines.Clear();
_header = reader.ReadLine();
_lines.Add(_header);
for (int i = 0; i < _lineCount; i++)
{
if (bg.CancellationPending)
{
e.Cancel = true;
break;
}
int percentage = (i + 1) * 100 / _lineCount;
bg.ReportProgress(percentage);
_lines.Add(reader.ReadLine());
if (i % numberOfRows == 0)
{
_counter++;
Debug.WriteLine(i);
if (i == 0)
{
//skip first iteration
_counter = 0;
continue;
}
_output = _tempath + "\" + "split\" + _fileNoExt + "_split-" + _counter + _fileExt;
_filesMade.Add(_output);
File.WriteAllLines(_output, _lines.ConvertAll(Convert.ToString));
_lines.Clear();
_lines.Add(_header);
}
}
}
}
else
{
using (var reader = new StreamReader(File.OpenRead(filepath)))
{
_lines.Clear();
_header = reader.ReadLine();
_lines.Add(_header);
for (int i = 0; i < _lineCount; i++)
{
if (bg.CancellationPending)
{
e.Cancel = true;
break;
}
int percentage = (i + 1) * 100 / _lineCount;
bg.ReportProgress(percentage);
_lines.Add(reader.ReadLine());
if (i % numberOfRows == 0)
{
_counter++;
if (i == 0)
{
//skip first iteration
_counter = 0;
continue;
}
string output = _tempath + "\" + "split\" + _fileNoExt + "_split-" + _counter + _fileExt;
_filesMade.Add(_output);
File.WriteAllLines(output, _lines.ConvertAll(Convert.ToString));
_lines.Clear();
}
}
}
}
}
运行 工人已完成
private void bg_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled)
{
StopSplit();
_filesMade.Clear();
ProcessText.Text = "Split cancelled";
return;
}
_filesMade.Clear();
ProcessText.Text = "Split has completed, click here to open the directory";
}
我打赌你的 BgW 是你 class...
的成员
在 Startsplit() 中,每次执行此函数时都会添加一个新的回调。
这就是它运行多次的原因。
晚饭后再回答。
吃完晚饭...
您的计数方法在多个方面存在缺陷:
1) 如果您丢失文件,我敢打赌这是最后一个。例如。 30 行,3 个文件:
i % numberOfRows
在 i=0, 10, 20 时为零,但 i 没有达到 30。
2)您缺少行,例如31行4个文件:
文件保存在 i=7、14、21、28。缺少第 29-31 行。
我建议你使用嵌套for循环,外层用于文件,内层用于行,并改进你的计算。并将所有列表和计数器放入函数中!
我希望你欣赏我的回答。我讨厌在平板电脑上打字。但也不想为此启动我的计算机...;-)
我一直在尝试制作一个程序,将较大的文本文件拆分成较小的部分,以便更易于使用。
我目前有两个问题,无法弄清楚发生了什么。
问题一:后台worker有时会触发多次。我似乎无法弄清楚它决定 运行 的原因或次数。它将 运行 拆分并在最终文件上似乎循环回到工作的开始并再次 运行 。它还会触发多个 do work 已完成的任务。使事情复杂化的是,如果我将拆分的文件数设置为不同的数字,我可以获得不同的后台工作人员似乎触发的次数,但它与文件数没有直接关联。有时相同数量的文件会导致后台工作程序只触发一次,有时会触发多次。
问题2:有时拆分不会创建所有文件。对于某些文件,如果我 运行 它会创建前两个文件,然后删除其余文件。似乎只有当我将数字设置为 3 个要拆分的文件时才会发生。如果我把行数加起来,它应该是正确的。所以我不确定那里发生了什么。
调用线程
private void StartSplit()
{
if (int.TryParse(NumberOfFilesTB.Text, out _numberOfFiles))
{
if (bg.IsBusy)
{
((MainWindow)Application.Current.MainWindow).SetStatus("Warning",
"Please only run one split process at a time.");
return;
}
((MainWindow)Application.Current.MainWindow).DisplayAlert(
"Split is running, you will receive an alert when it has finished. You may use other tools while the split is running.");
var args = new List<string> { _filepath, _includeHeaders.ToString(), _numberOfFiles.ToString() };
bg.DoWork += bg_DoWork;
bg.WorkerReportsProgress = true;
bg.ProgressChanged += ProgressChanged;
bg.RunWorkerCompleted += bg_RunWorkerCompleted;
bg.WorkerSupportsCancellation = true;
bg.RunWorkerAsync(args);
ProcessText.Text = "Running split process";
}
else
{
((MainWindow)Application.Current.MainWindow).SetStatus("Warning", "Please enter a number for number of files");
}
}
后台线程
private void bg_DoWork(object sender, DoWorkEventArgs e)
{
var args = e.Argument as List<string>;
string filepath = args[0];
string includeHeaders = args[1];
int numberOfFiles = Convert.ToInt32(args[2]);
int numberOfRows = _lineCount / numberOfFiles;
_tempath = Path.GetDirectoryName(_filepath);
Directory.CreateDirectory(_tempath+"\split");
if (includeHeaders == "True")
{
using (var reader = new StreamReader(File.OpenRead(filepath)))
{
_lines.Clear();
_header = reader.ReadLine();
_lines.Add(_header);
for (int i = 0; i < _lineCount; i++)
{
if (bg.CancellationPending)
{
e.Cancel = true;
break;
}
int percentage = (i + 1) * 100 / _lineCount;
bg.ReportProgress(percentage);
_lines.Add(reader.ReadLine());
if (i % numberOfRows == 0)
{
_counter++;
Debug.WriteLine(i);
if (i == 0)
{
//skip first iteration
_counter = 0;
continue;
}
_output = _tempath + "\" + "split\" + _fileNoExt + "_split-" + _counter + _fileExt;
_filesMade.Add(_output);
File.WriteAllLines(_output, _lines.ConvertAll(Convert.ToString));
_lines.Clear();
_lines.Add(_header);
}
}
}
}
else
{
using (var reader = new StreamReader(File.OpenRead(filepath)))
{
_lines.Clear();
_header = reader.ReadLine();
_lines.Add(_header);
for (int i = 0; i < _lineCount; i++)
{
if (bg.CancellationPending)
{
e.Cancel = true;
break;
}
int percentage = (i + 1) * 100 / _lineCount;
bg.ReportProgress(percentage);
_lines.Add(reader.ReadLine());
if (i % numberOfRows == 0)
{
_counter++;
if (i == 0)
{
//skip first iteration
_counter = 0;
continue;
}
string output = _tempath + "\" + "split\" + _fileNoExt + "_split-" + _counter + _fileExt;
_filesMade.Add(_output);
File.WriteAllLines(output, _lines.ConvertAll(Convert.ToString));
_lines.Clear();
}
}
}
}
}
运行 工人已完成
private void bg_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled)
{
StopSplit();
_filesMade.Clear();
ProcessText.Text = "Split cancelled";
return;
}
_filesMade.Clear();
ProcessText.Text = "Split has completed, click here to open the directory";
}
我打赌你的 BgW 是你 class...
的成员
在 Startsplit() 中,每次执行此函数时都会添加一个新的回调。
这就是它运行多次的原因。
晚饭后再回答。
吃完晚饭...
您的计数方法在多个方面存在缺陷:
1) 如果您丢失文件,我敢打赌这是最后一个。例如。 30 行,3 个文件:
i % numberOfRows
在 i=0, 10, 20 时为零,但 i 没有达到 30。
2)您缺少行,例如31行4个文件:
文件保存在 i=7、14、21、28。缺少第 29-31 行。
我建议你使用嵌套for循环,外层用于文件,内层用于行,并改进你的计算。并将所有列表和计数器放入函数中!
我希望你欣赏我的回答。我讨厌在平板电脑上打字。但也不想为此启动我的计算机...;-)