当前位置:  开发笔记 > 编程语言 > 正文

将大文本分成较小块的最快方法

如何解决《将大文本分成较小块的最快方法》经验,为你挑选了1个好方法。

我使用下面的代码来分割字符串,但这需要很多时间.

using (StreamReader srSegmentData = new StreamReader(fileNamePath))
{
    string strSegmentData = "";
    string line = srSegmentData.ReadToEnd();
    int startPos = 0;

    ArrayList alSegments = new ArrayList();
    while (startPos < line.Length && (line.Length - startPos) >= segmentSize)
    {
        strSegmentData = strSegmentData + line.Substring(startPos, segmentSize) + Environment.NewLine;
        alSegments.Add(line.Substring(startPos, segmentSize) + Environment.NewLine);
        startPos = startPos + segmentSize;
    }
}

请建议我另一种方法将字符串拆分为固定大小的较小块



1> Adriano Repe..:

首先,您应该定义块大小的含义.如果您的意思是具有固定数量的代码单元的块,那么您的实际算法可能会很慢,但它可以工作.如果它不是你想要的,你实际上是指具有固定数量字符的块,那么它就会被打破.我在这篇Code Review帖子中讨论了类似的问题:将一个字符串拆分成相同长度的块然后我将在这里仅重复相关部分.

您正在进行分区Char但是String是UTF-16编码,那么您可能会产生损坏的字符串,至少有三种情况:

    一个字符使用多个代码单元进行编码.该字符的Unicode代码点被编码为两个UTF-16代码单元,每个代码单元最终可能位于两个不同的片中(并且两个字符串都将无效).

    一个字符由多个代码点组成.您正在处理由两个单独的Unicode代码点(例如Han字符)创建的字符.

    一个字符组合了字符或修饰符.这比您想象的更常见:例如Unicode组合字符,如U + 0300 COMBINING GRAVE ACCENT用于构建 à和Unicode 修饰符,如U + 02BC MODIFIER LETTER APOSTROPHE.

编程语言和人类的字符定义是完全不同的,例如在斯洛伐克语中是单个字符,但它是由2/3 Unicode代码点构成的,在这种情况下也是2/3 UTF-16代码单元"dž".Length > 1.更多关于这和其他文化问题上我怎么能执行由字符比较一个Unicode字符知道?.

存在连接.假设一个连字是一个代码点(并且还假设它被编码为一个代码单元),那么您将它视为单个字形,但它代表两个字符.在这种情况下该怎么办?一般来说,字符的定义可能相当模糊,因为根据使用该单词的学科,它具有不同的含义.您不能(可能)正确处理所有内容,但您应该设置一些约束和文档代码行为.

一个提议(和未经测试)的实现可能是这样的:

public static IEnumerable Split(this string value, int desiredLength)
{
    var characters = StringInfo.GetTextElementEnumerator(value);
    while (characters.MoveNext())
        yield return String.Concat(Take(characters, desiredLength));
}

private static IEnumerable Take(TextElementEnumerator enumerator, int count)
{
    for (int i = 0; i < count; ++i)
    {
        yield return (string)enumerator.Current;

        if (!enumerator.MoveNext())
            yield break;
    }
}

它没有针对速度进行优化(正如您所看到的那样,我尝试使用枚举来保持代码简短和清晰)但是,对于大文件,它仍然比您的实现更好(请参阅下一段的原因).

关于您的代码注意:

你正在建立一个巨大的ArrayList(?!)来保持结果.另请注意,通过这种方式可以ArrayList多次调整大小(即使给定输入大小和块大小,也可以知道其最终大小).

strSegmentData重建多次,如果你需要累积必须使用的字符,StringBuilder否则每个操作都会分配一个新字符串并复制旧值(它很慢,它也给垃圾收集器增加了压力).

有更快的实现(请参阅链接的Code Review帖子,尤其是Heslacher的更快版本的实现),如果您不需要正确处理Unicode(您确定只管理US ASCII字符),那么还有一个非常易读的实现来自Jon Skeet(请注意,在对代码进行分析之后,您仍可以提高其预分配正确大小输出列表的大文件的性能).我不在这里重复他们的代码然后请参考链接的帖子.

根据您的具体情况,您不需要在内存中读取整个大文件,您可以在时间读取/解析n个字符(不要过于担心磁盘访问,I/O是缓冲的).它会略微降低性能,但会大大提高内存使用率.或者,您可以逐行阅读(管理处理跨行块).

推荐阅读
手机用户2402851155
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有