gpt4 book ai didi

c# - 将大文本拆分为较小块的最快方法

转载 作者:太空狗 更新时间:2023-10-29 20:04:22 25 4
gpt4 key购买 nike

我已经使用下面的代码来拆分字符串,但是需要很多时间。

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;
}
}

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

最佳答案

首先,您应该定义块大小的含义。如果您的意思是具有固定数量 的块代码单元那么您的实际算法可能很慢,但它有效。如果这不是您想要的并且您实际上是指具有固定数量 的块字符 然后它坏了。我在这篇代码审查帖子中讨论了一个类似的问题:Split a string into chunks of the same length那么我将在这里只重复相关部分。

  • 您正在对 Char 进行分区但是 String是 UTF-16 编码的,那么您可能会在至少三种情况下产生损坏的字符串:
  • 一个字符用多个编码单元编码 .该字符的 Unicode 代码点被编码为两个 UTF-16 代码单元,每个代码单元可能会在两个不同的切片中结束(并且两个字符串都将无效)。
  • 一个字符由多个码位组成 .您正在处理由两个单独的 Unicode 代码点组成的字符(例如汉字 𠀑)。
  • 一个字符具有组合字符或修饰符 .这比您想象的更常见:例如,用于构建 à 的 Unicode 组合字符(如 U+0300 COMBINING GRAVE ACCENT)和 Unicode 修饰符(如 U+02BC MODIFIER LETTER APOSTROPHE)。
  • 编程语言和人类对字符的定义非常不同,例如在斯洛伐克语中 dž 是单个字符,但它由 2/3 Unicode 代码点组成,在这种情况下也是 2/3 UTF-16 代码单元"dž".Length > 1 .更多关于这个和其他文化问题的信息,请访问 How can I perform a Unicode aware character by character comparison? .
  • 存在连字。假设一个连字是一个代码点(并假设它被编码为一个代码单元),那么您会将其视为单个字形,但它代表两个字符。在这种情况下该怎么办?一般来说,字符的定义可能非常模糊,因为根据使用该词的学科,它具有不同的含义。您不能(可能)正确处理所有事情,但您应该设置一些约束和记录代码行为。

  • 一个提议的(和未经测试的)实现可能是这样的:
    public static IEnumerable<string> Split(this string value, int desiredLength)
    {
    var characters = StringInfo.GetTextElementEnumerator(value);
    while (characters.MoveNext())
    yield return String.Concat(Take(characters, desiredLength));
    }

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

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

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

    关于您的代码,请注意:
  • 你正在 build 一个巨大的ArrayList (?!) 保存结果。另请注意,以这种方式调整大小 ArrayList多次(即使给定输入大小和块大小,则其最终大小是已知的)。
  • strSegmentData多次重建,如果需要积累字符必须使用StringBuilder否则每个操作都会分配一个新字符串并复制旧值(它很慢,而且还给垃圾收集器增加了压力)。

  • 有更快的实现(请参阅链接的代码审查帖子,尤其是 Heslacher's implementation 以获得更快的版本),如果您不需要正确处理 Unicode(您是 确定 您只管理美国 ASCII 字符)然后还有一个漂亮的 readable implementation from Jon Skeet (请注意,在分析您的代码后,您仍然可以通过预先分配正确大小的输出列表来提高大文件的性能)。我不会在这里重复他们的代码,然后请引用链接的帖子。

    在您的具体 您不需要读取内存中的整个大文件 ,您可以一次读取/解析 n 个字符(不要太担心磁盘访问,I/O 是缓冲的)。它会稍微降低性能,但会大大提高内存使用率。或者,您可以逐行阅读(管理处理跨线块)。

    关于c# - 将大文本拆分为较小块的最快方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34430325/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com