【问题标题】:WPF C#: Splitting a long stringWPF C#:拆分长字符串
【发布时间】:2021-10-07 15:00:00
【问题描述】:

我一直在思考这个问题,但现在我设法向知道的人寻求帮助。我有一个代码,它应该从一个大文件(几个 Gbs)中逐行读取文本。每行可以是 500Mb 左右,因为它必须是一个视频,转换为与视频名称连接的 base64。在这里,我读取当前行并将视频名称与其内容分开(从 else 开始)。

        string[] fileline = GetFileLine(resPath, currentRow).Split(); //Here split causes SystemOutOfMemory
        try
        {
            string base64 = fileline[0].Replace(specSymbol, ' ');
            try
            {
                if (!IsVideo(ref base64) && !IsGif(ref base64))
                {
                    ShowPrimary();
                    imgFile.Source = BytesToBitmap(Convert.FromBase64String(base64));
                }
                else
                    btnLoadFile.Background = readyColor;
                if (fileline.Length > 1)
                    return fileline[1].Replace(specSymbol, ' ');
            }
            catch (Exception ex3) { MessageBox.Show("Next(4):" + ex3.Message); }
        }
        catch (Exception ex2) { MessageBox.Show("Next(3):" + ex2.Message); }

所以我的问题是:是否存在拆分长字符串的方法,或者我只需将名称存储在单独的文件中而不进行拆分?

UPD1:我使用@canton7 给我的建议编写了一个方法。我已经在非常小的文件(大约 100 个符号)上对其进行了测试,它运行良好,但我现在正在 25Mb 文件上对其进行测试,并且读取速度非常糟糕(例如一小时内 10Mb),即使读取非常大的文件并没有使程序崩溃,所以我认为我走对了。 我仍然想知道是否有更好的方法。如果您对现成的方法改进有一些建议 - 请在此处提供。

static string ReadFirstHalfAfter(string path, int skips = 0)
{
    int skipsDone = 0;
    int ri = 0;
    char[] buffer = new char[1];
    StreamReader reader = new StreamReader(path);
    while (reader.Peek() >= 0)//while reader is not at the end of file
    {
        reader.Read(buffer, ri, 1);//reading one element from the current position
        if (skipsDone < skips)//line skips not enough
        {
            if (buffer[buffer.Length - 1] == '\n')//current symbol is line end 
            { 
                skipsDone++;//line skip counted
                continue;
            }
        }
        else//enough line skips
        {
            if (buffer[buffer.Length - 1] == ' ') break; //if line separator - stop
            ExpandArray(ref buffer); //adding one more free element
            ri++; //switching element to read next
        }
        if (ri % 10000 == 0) Console.Write('.');
    }
    return new string(buffer).Trim(' ');
}

【问题讨论】:

  • 为什么不使用 StreamReader?这样,您可以逐个字符地读取每一行:首先是文件名(继续读取字符,直到找到空格),然后您可以读取单个字符并通过 FromBase64Transform 将它们流式传输,然后将每个结果字节直接写入另一个文件(或局部变量)
  • @canton7 谢谢建议,我明天试试。
  • 可能值得稍微清理一下这个问题,这样它会更简洁 - 这是一个很好的话题,但是有很多额外的绒毛分散了核心问题“我如何将长字符串分成C# 不会耗尽内存”。
  • "内存中 String 对象的最大大小为 2 GB,或大约 10 亿个字符。"你厌倦了使用 Substring 和 IndexOf 吗?对于那个大小的文件,我不建议一次读取 1 个字符,但恕我直言。
  • @Sorceri 这就是想法,但我不确定它是否会比仅在内存方面进行拆分更优化。无论如何,我会尝试并告诉你,谢谢。

标签: c# string split


【解决方案1】:

要将字符串分成两部分,您可以使用子字符串来节省内存,但如果您想节省更多内存 - 只有一种方法可以将行部分写入不同的行。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-08-09
    • 1970-01-01
    • 2016-06-13
    • 1970-01-01
    • 2017-06-16
    • 2011-02-13
    • 2011-11-25
    • 2021-05-08
    相关资源
    最近更新 更多