我已经使用下面的代码来拆分字符串,但是需要很多时间。
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 编码的,那么您可能会在至少三种情况下产生损坏的字符串:"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;
}
}
它没有针对速度进行优化(如您所见,我尝试使用枚举使代码保持简短和清晰),但是对于大文件,它的性能仍然比您的实现好(原因请参见下一段)。
关于您的代码,请注意:
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/