Xan*_*ham 1 c# stream filestream streamreader fixed-width
我有一个文本文件,其中包含我要解析的固定长度表。但是,文件的开头是有关何时生成此表的一般信息(IE 时间、数据等)。
为了阅读此内容,我尝试创建一个FileStream,然后使用 . 读取该文件的第一部分StreamReader。我从文档的顶部解析出我需要的内容,然后当我完成时,将流的位置设置为结构化数据的第一行。
然后我将 a 附加TextFieldParser到流(使用固定长度表的适当设置),然后尝试读取该文件。在第一行,它失败了,在ErrorLine属性中,它列出了表第三行的后半部分。我浏览了一下,发现它位于第一行,但ErrorLine酒店却暗示情况并非如此。
调试时,我发现如果在StreamReader.ReadLine()将其附加TextFieldParser到流后尝试使用我的方法,前两行显示正常。然而,当我阅读第三行时,它返回一行,该行从第三行的前半部分开始(并在文本所在的位置停止ErrorLine)附加文档中稍后的部分内容。如果我在附加之前尝试此操作TextFieldParser,它会很好地读取所有 3 行。
我有一种感觉,这与我将 2 个读者绑定到同一个流有关。我不知道如何使用结构化部分和非结构化部分来阅读此内容,而不只是自己标记这些行。我可以做到这一点,但我假设我不是第一个想要以一种方式读取流的一部分,并以另一种方式读取流的后续部分的人。
为什么会这样跳过,如何读取不同格式的文本文件?
例子:
Date: 3/1/2013
Time: 3:00 PM
Sensor: Awesome Thing
Seconds X Y Value
0 5.1 2.8 55
30 4.9 2.5 33
60 5.0 5.3 44
Run Code Online (Sandbox Code Playgroud)
为这个简化示例定制的代码:
Boolean setupInfo = true;
DataTable result = new DataTable();
String[] fields;
Double[] dFields;
FileStream stream = File.Open(filePath,FileMode.Open);
StreamReader reader = new StreamReader(stream);
String tempLine;
for(int j = 1; j <= 7; j++)
{
result.Columns.Add(("Column" + j));
}
//Parse the unstructured part
while(setupInfo)
{
tempLine = reader.ReadLine();
if( tempLine.StartsWith("Date: "))
{
result.Rows.Add(tempLine);
}
else if (tempLine.StartsWith("Time: "))
{
result.Rows.Add(tempLine);
}
else if (tempLine.StartsWith("Seconds")
{
//break out of this loop because the
//next line to be read is the unstructured part
setupInfo = false;
}
}
//Parse the structured part
TextFieldParser parser = new TextFieldParser(stream);
parser.TextFieldType = FieldType.FixedWidth;
parser.HasFieldsEnclosedInQuotes = false;
parser.SetFieldWidths(10, 10, 10, 10);
while (!parser.EndOfData)
{
if (reader.Peek() == '*')
{
break;
}
else
{
fields = parser.ReadFields();
if (parseStrings(fields, out dFields))
{
result.Rows.Add(dFields);
}
}
}
return result;
Run Code Online (Sandbox Code Playgroud)
它跳过的原因是StreamReader从 读取数据块FileStream,而不是逐个字符读取。例如,StreamReader可能会从中读取 4 KB FileStream,然后根据需要解析出行以响应调用ReadLine()。因此,当您将 附加TextFieldParser到 时FileStream,它将从当前文件位置读取 - 即左侧的位置StreamReader。
解决方案应该非常简单:只需将其连接TextFieldParser到StreamReader:
TextFieldParser parser = new TextFieldParser(reader);
Run Code Online (Sandbox Code Playgroud)
参见TextFieldParser(TextReader 阅读器)