C# 如何读取大文件并按“拆分”\r\n“;
我有一个大于200MB的大文件。该文件是来自外部方的CSV文件,但遗憾的是,我不能逐行读取该文件,因为C# 如何读取大文件并按“拆分”\r\n“;,c#,.net,C#,.net,我有一个大于200MB的大文件。该文件是来自外部方的CSV文件,但遗憾的是,我不能逐行读取该文件,因为\r\n用于定义新行 目前,我正在使用这种方法阅读所有行: var file = File.ReadAllText(filePath, Encoding.Default); var lines = Regex.Split(file, @"\r\n"); for (int i = 0; i < lines.Length; i++) { string line = lines[i];
\r\n
用于定义新行
目前,我正在使用这种方法阅读所有行:
var file = File.ReadAllText(filePath, Encoding.Default);
var lines = Regex.Split(file, @"\r\n");
for (int i = 0; i < lines.Length; i++)
{
string line = lines[i];
...
}
您可以使用它返回IEnumerable
,而不是将整个文件加载到内存中
foreach(var line in File.ReadLines(@filePath, Encoding.Default)
.Where(l => !String.IsNullOrEmpty(l)))
{
}
使用它会很容易
using (StreamReader sr = new StreamReader(path))
{
foreach(string line = GetLine(sr))
{
//
}
}
IEnumerable<string> GetLine(StreamReader sr)
{
while (!sr.EndOfStream)
yield return new string(GetLineChars(sr).ToArray());
}
IEnumerable<char> GetLineChars(StreamReader sr)
{
if (sr.EndOfStream)
yield break;
var c1 = sr.Read();
if (c1 == '\\')
{
var c2 = sr.Read();
if (c2 == 'r')
{
var c3 = sr.Read();
if (c3 == '\\')
{
var c4 = sr.Read();
if (c4 == 'n')
{
yield break;
}
else
{
yield return (char)c1;
yield return (char)c2;
yield return (char)c3;
yield return (char)c4;
}
}
else
{
yield return (char)c1;
yield return (char)c2;
yield return (char)c3;
}
}
else
{
yield return (char)c1;
yield return (char)c2;
}
}
else
yield return (char)c1;
}
使用(StreamReader sr=新的StreamReader(路径))
{
foreach(字符串行=GetLine(sr))
{
//
}
}
IEnumerable GetLine(StreamReader sr)
{
而(!sr.EndOfStream)
返回新字符串(GetLineChars(sr).ToArray());
}
IEnumerable GetLineChars(StreamReader sr)
{
if(sr.EndOfStream)
屈服断裂;
var c1=sr.Read();
如果(c1='\\')
{
var c2=sr.Read();
如果(c2=='r')
{
var c3=sr.Read();
如果(c3=='\\')
{
var c4=sr.Read();
如果(c4='n')
{
屈服断裂;
}
其他的
{
收益率(char)c1;
收益率(char)c2;
收益率(char)c3;
产率返回(半焦)c4;
}
}
其他的
{
收益率(char)c1;
收益率(char)c2;
收益率(char)c3;
}
}
其他的
{
收益率(char)c1;
收益率(char)c2;
}
}
其他的
收益率(char)c1;
}
使用StreamReader逐行读取文件:
using (StreamReader sr = new StreamReader(filePath))
{
while (true)
{
string line = sr.ReadLine();
if (line == null)
break;
}
}
怎么样
StreamReader sr = new StreamReader(path);
while (!sr.EndOfStream)
{
string line = sr.ReadLine();
}
使用流读取器方法意味着整个文件不会加载到内存中。这是我的午休时间:)
foreach(var line in File.ReadLines(@filePath, Encoding.Default)
.Where(l => !String.IsNullOrEmpty(l)))
{
}
将MAXREAD
设置为内存中所需的数据量,例如使用foreach
,因为我正在使用yield return
。使用代码的风险由您自己承担,我已经在较小的数据集上尝试过:)
您的用法可能类似于:
foreach (var row in StreamReader(FileName).SplitByChar(new char[] {'\r','\n'}))
{
// Do something awesome! :)
}
扩展方法如下:
public static class FileStreamExtensions
{
public static IEnumerable<string> SplitByChar(this StreamReader stream, char[] splitter)
{
int MAXREAD = 1024 * 1024;
var chars = new List<char>(MAXREAD);
var bytes = new char[MAXREAD];
var lastStop = 0;
var read = 0;
while (!stream.EndOfStream)
{
read = stream.Read(bytes, 0, MAXREAD);
lastStop = 0;
for (int i = 0; i < read; i++)
{
if (bytes[i] == splitter[0])
{
var assume = true;
for (int p = 1; p < splitter.Length; p++)
{
assume &= splitter[p] == bytes[i + p];
}
if (assume)
{
chars.AddRange(bytes.Skip(lastStop).Take(i - lastStop));
var res = new String(chars.ToArray());
chars.Clear();
yield return res;
i += splitter.Length - 1;
lastStop = i + 1;
}
}
}
chars.AddRange(bytes.Skip(lastStop));
}
chars.AddRange(bytes.Skip(lastStop).Take(read - lastStop));
yield return new String(chars.ToArray());
}
}
公共静态类FileStreamExtensions
{
公共静态IEnumerable SplitByChar(此StreamReader流,char[]拆分器)
{
int MAXREAD=1024*1024;
var chars=新列表(MAXREAD);
var bytes=新字符[MAXREAD];
var lastStop=0;
var read=0;
而(!stream.EndOfStream)
{
read=stream.read(字节,0,MAXREAD);
lastStop=0;
for(int i=0;i
仅检查空值。我们可以在中间有空行。@ DennisMadsen可以跳过空行。它不是关于空行的,它是关于输入格式中的行不是由文件中的新行结束的,而是首先在“\r\n”被看到时。@丹尼斯马森,我不能理解您。代码>\r\n实际上是指新行。你能把你的几行发到像pastebin这样的地方吗。试试这个(var chars=Environment.NewLine.ToCharArray();
)@L.B他所在的环境可能不是windows,据我所知,重置Environment.NewLine的唯一方法是使用反射。你知道更好的方法吗?@flindeberg不需要重新设置NewLine。File.ReadLines将正确读取它,即使换行符仅为\r
我明白了,那么看看这个线程,我将尝试diEmAll的方法。。。正如许多人以前指出的那样,\r\n
是windows环境的默认换行符。您使用的不是windows吗?@DennisMadsen试图回答您的问题,但您的要求很奇怪:)+1用于回答问题。不知道为什么不被接受。也许是因为它不太通用?(我来这里是为了寻找一种将regex find/replace应用于大型文本文件的有效方法,因此这似乎对我的帮助并不比ReadAllText更大。)