我正在开发一个C#程序,用于在使用SSIS包导入之前确定具有100,000多行的多个大文本文件中每行的行长度。我还将检查每一行上的其他值,以验证它们是否正确,以便使用SSIS将它们导入我的数据库。
例如,我期望行长度为3000个字符,然后CR为3001,LF为3002,总共3002个字符。
当使用ReadLine()时,它会读取CR或LF作为行尾,这样我就无法检查CR或LF字符。我只是在3000处检查线的长度以确定长度是否正确。我刚刚遇到一个问题,即文件在位置3001处有一个LF但是缺少CR。所以ReadLine()说它是3000 char女巫是正确的但它会在我的SSIS包中失败,因为它缺少一个CR。
我已经确认Read()将一次到达每个char 1,我可以确定每行是否有CR和LF但这似乎相当无效,当我遇到的某些文件有超过5,000,000+行时这似乎非常低效。我还需要将每个char添加到字符串中或使用ReadBlock()并将char数组转换为字符串,以便我可以检查该行中的其他值。
有没有人有一个有效的方法来检查CR和LF以及给定线路上的其他值的线路,而不会浪费不必要的资源并以相对及时的方式完成。
答案 0 :(得分:4)
已经验证Read()将一次到达每个char 1,我可以确定每行是否有CR和LF但这似乎相当无效
想一想。你认为ReadLine()
有一根魔杖而且不必阅读每一个字符吗?
只需创建自己的ReadMyLine()。有些东西必须读取字符,无论这是你的代码还是lib。 I / O将由Stream和Windows缓冲。
答案 1 :(得分:1)
我可能在这里遗漏了一些东西,但是如果每行中的数据总是精确到3000个字符(不包括CR和LF)?
为什么不使用string.Substring()
读取每一行,然后仅使用前3000个字符。这样您就不必担心字符串的终止方式。
即
using (StreamReader sr = new StreamReader("TestFile.txt"))
{
String line;
while ((line = sr.ReadLine()) != null)
{
// string data = line.subString(0,3000);
// edit, if data is sometimes < 3000 ....
string data = line.subString(0,line.length < 3000 ? line.length : 3000);
// do something with data
}
}
答案 2 :(得分:1)
你可以使用an override of StreamReader.Read OR an override of TextReader.Read接受3个参数 - 字符串缓冲区(在你的情况下是一个3002字符数组),startint索引(每次递增索引时你都会在循环中处理它3002),要读取的字符数(3002)。从读缓冲区,您可以检查CR和LF的条件评估的最后两个字符。
答案 3 :(得分:1)
我相信你会发现这个版本效率很高:
static bool CheckFile(string filename)
{
const int BUFFER_SIZE = 3002;
var Reader = new StreamReader(filename, Encoding.ASCII, false, BUFFER_SIZE);
var buffer = new char[BUFFER_SIZE];
int offset = 0;
int bytesRead = 0;
while((bytesRead = Reader.Read(buffer, offset, BUFFER_SIZE)) > 0)
{
if(bytesRead != BUFFER_SIZE
|| buffer[BUFFER_SIZE - 2] != '\r'
|| buffer[BUFFER_SIZE - 1] != '\n')
{
//the file does not conform
return false;
}
offset += bytesRead;
}
return true;
}
我对此持乐观态度的原因是,根据the docs,如果底层缓冲区的大小与用于读取的缓冲区匹配,则效率会提高。警告:此代码尚未经过测试或定时。
答案 4 :(得分:0)
我想我终于找到了准确得到我想要的代码,想法?我遇到的主要问题是我无法保证我的线路长度会纠正。另一方面,@ Paul Keister提到的方法会很有效,并且在我测试它的时候做了。谢谢你的帮助!
int asciiValue = 0;
while (asciiValue != -1)
{
Boolean endOfRow = false;
Boolean endOfRowValid = true;
string currentLine = "";
while (endOfRow == false)
{
asciiValue = file.Read();
if (asciiValue == 10 || asciiValue == 13)
{
int asciiValueTemp = file.Peek();
if (asciiValue == 13 && asciiValueTemp == 10)
{
endOfRow = true;
asciiValue = file.Read();
}
else
{
endOfRowValid = false;
endOfRow = true;
}
}
else if (asciiValue != -1)
currentLine += char.ConvertFromUtf32(asciiValue);
else
endOfRow = true;
}
编辑:我忘了提到这似乎和使用ReadLine()一样有效。我真的害怕这不会有效。看来我错了。