1

解析しようとしている固定長のテーブルを含むテキストファイルがあります。ただし、ファイルの先頭は、このテーブルがいつ生成されたかに関する一般的な情報(IE時間、データなど)です。

これを読むために、私はを作成しようとしましたFileStream。次に、このファイルの最初の部分を。で読みますStreamReader。ドキュメントの上部から必要なものを解析し、完了したら、ストリームの位置を構造化データの最初の行に設定します。

次に、をストリームに添付しTextFieldParser(固定長テーブルに適切な設定を使用して)、ファイルの読み取りを試みます。最初の行では失敗し、ErrorLineプロパティでは、テーブルの3番目の行の後半がリストされます。私はそれをステップスルーし、それは最初の行にありましたが、ErrorLineプロパティはそうではないことを示唆しています。

デバッグ時に、ストリームにStreamReader.ReadLine()アタッチした後でメソッドを使用しようとするTextFieldParserと、最初の2行が正常に表示されることがわかりました。ただし、3行目を読むと、3行目の前半から始まり(テキストErrorLineが含まれる場所で停止する)、ドキュメントのかなり後の部分が追加された行が返されます。をアタッチする前にこれを試してみると、TextFieldParser3行すべてが正常に読み取られます。

これは、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

この簡略化された例に合わせて調整されたコード:

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;
4

3 に答える 3

5

スキップする理由は、が文字ごとに読み取るStreamReaderのではなく、からデータのブロックを読み取るためです。FileStreamたとえば、はStreamReaderから4キロバイトを読み取りFileStream、必要に応じて行を解析してReadLine()呼び出しに応答する場合があります。したがって、をにアタッチするTextFieldParserFileStream、現在のファイル位置(StreamReader左のファイル位置)から読み取られます。

解決策は非常に単純である必要があります。:に接続するだけTextFieldParserですStreamReader

TextFieldParser parser = new TextFieldParser(reader);

TextFieldParser(TextReaderリーダー)を参照してください

于 2013-03-01T23:31:07.340 に答える
2

一般的に言って、ほとんどのストリームは消費しています。つまり、一度読み取られると、使用できなくなります。Streamから派生し、イベントを発生させたり、他のストリームに再公開したりする中間クラスを作成することで、複数のストリームに分岐できます。

于 2013-03-01T23:07:16.430 に答える
0

あなたの場合、あなたは必要ありませんStreamReader。最良の選択は、代わりにFile.ReadLinesメソッドを使用してファイルの内容を確認することです。必要なものがすべて見つかるまで、ファイルの内容全体をロードするのではなく、行だけをロードします。

foreach (string line in File.ReadLines(filePath))
{
    if( line.StartsWith("Date:  "))
    {
        result.Rows.Add(line);
    }
    else if (line.StartsWith("Time:  "))
    {
        result.Rows.Add(line);
    }
    else if (line.StartsWith("Seconds"))
    {
       break;
    }
}

編集

LINQを使用すると、さらに簡単に実行できます。

var d = from line in File.ReadLines(filePath) where line.Contains("Date:  ") select line;
result.Rows.Add(d);
于 2013-03-01T23:28:12.063 に答える