文章目录
- 清理空格
- 段落拼接
- 去除空行
- 按键事件
 
txt阅读器系列:
- 需求分析和文件读写
- 目录提取类💎列表控件与目录💎快捷键翻页
- 字体控件绑定💎前景/背景颜色
- 书籍管理系统💎用树形图管理书籍
- 语音播放💎播放进度显示💎快进快退💎语速音量
- 文本清理的布局💎段落合并
清理空格
接下来实现清理空格、段落拼接、去处空行这三个功能,这里的清理空格表示去除首尾空格,为了实现这个功能,需要先将字符串分割为字符串列表,然后将列表中每个字符串的首尾空格去掉,一行代码就可以实现
var ch = "\r\n";
if (fmtCheckBoxes[0].IsChecked == true)
    doc = String.Join(ch,  doc.Split(ch)
                              .Select(L => L.Trim())
                              .ToArray());
段落拼接
然后考虑段落拼接,只需找到字符串中的所有换行的位置,如果这些换行符前面,并不是允许换行的终止符号,则删除这个地方的换行。而文字中经常出现的终止符号基本都是标点符号,故其代码可写为
private List<string> mergePara(List<string> sLst, string LF="\r\n")
{
    const string TERMINATOR = ",.!?,。!?”";
    int i = 0;
    while (i < sLst.Count - 1)
    {
        if (!TERMINATOR.Contains(sLst[i].Last()))
        {
            sLst[i] = sLst[i] + sLst[i + 1];
            sLst.RemoveAt(i + 1);
            continue;
        }
        i++;
    }
    return sLst;
}
其核心代码为while循环的第一个判断语句,若第i行的最后一个字符不属于终止符,则将第i+1行合并到第i行后,删除第i+1行,然后重复执行此项操作。否则的花,跳到下一行。
去除空行
最后考虑去除空行,这一条也比较简单,无非把多余一个的\r\n替换为\r\n即可,最直观的写法是
if (fmtCheckBoxes[2].IsChecked == true)
	while (doc.Contains("\r\n\r\n"))
		doc = doc.Replace("\r\n\r\n", "\r\n");
但这么些可能会在空格较多的情况下,执行更多次的循环,并不划算,故而可以展开来写
private List<string> deleteDoubleLine(List<string> sLst)
{
    int i = 0;
    while (i < sLst.Count - 1)
    {
        if (sLst[i] == "" & sLst[i+1]=="" )
        {
            sLst.RemoveAt(i + 1);
            continue;
        }
        i++;
    }
    return sLst;
}
其含义非常简单,与mergePara的逻辑基本是相同的,只不过在判断时,要求当前行和下一行都为空行,则删除下一行。
按键事件
这些功能都实现了之后,就可以写交互逻辑了,为文本清洗中的执行按钮添加btnFMT_Click事件,其内容为
private void btnFMT_Click(object sender, RoutedEventArgs e)
{
    var ch = "\r\n";
    List<string> sLst = doc.Split(ch).ToList();
    if (fmtCheckBoxes[0].IsChecked == true)
        sLst = sLst.Select(L => L.Trim()).ToList();
    if (fmtCheckBoxes[1].IsChecked == true)
        sLst = mergePara(sLst, ch);
    if (fmtCheckBoxes[2].IsChecked == true)
        sLst = deleteDoubleLine(sLst);
    doc = string.Join(ch, sLst);
}
结合txtReader的其他功能,这个业务流程中有两个bug,都和目录有关,其一是目录结尾并没有标点符号,也就是说,上面这些文本的清洗方式,会导致目录无法识别。所以需要对目录进行保护,在mergePara刚进入while循环时加上一个判断
if (catalog.Contains(sLst[i]))
{
    i++;
    continue;
}
其二则是重新生成目录时,在清空目录时会改变ListBox的SelectedIndex,从而触发事件,但此时doc文件已经发生了变化,所以会报错。故而更改btnCatalog_Click中的内容,在Clear前后取消并重新注册事件。
lvCatalog.SelectionChanged -= lvCatalog_SelectionChanged;
lvCatalog.Items.Clear();
lvCatalog.SelectionChanged += lvCatalog_SelectionChanged;
其最后效果如下




















