【发布时间】: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 这就是想法,但我不确定它是否会比仅在内存方面进行拆分更优化。无论如何,我会尝试并告诉你,谢谢。