3

まず、私はC#にあまり精通していないことを明確にしておきたいと思います。その中で、私が.Net 3.5を使用してC#で作業しているプロジェクトでは、レコードタイプに基づいて複数の固定幅形式を含むファイルを読み取ってエクスポートするクラスを構築しています。

現在、ファイルの各行の最初の文字位置で示される、特定の行形式を示す5種類のレコードがあります。私が抱えている問題は、タイプが互いに異なることです。

Record type 1 has 5 columns, signifies beginning of the file

Record type 3 has 10 columns, signifies beginning of a batch
Record type 5 has 69 columns, signifies a transaction
Record type 7 has 12 columns, signifies end of the batch, summarizes
(these 3 repeat throughout the file to contain each batch)

Record type 9 has 8 columns, signifies end of the file, summarizes

これらの種類の固定幅ファイル用の優れたライブラリはありますか?私は、ファイル全体を1つの仕様としてロードしたいが、それができないいくつかの良いものを見てきました。

これらのファイルのうち約250が月末に読み取られ、合計ファイルサイズは平均で約300メガバイトです。このプロジェクトでは、効率が非常に重要です。

データに関する知識に基づいて、オブジェクトがどのように見えるかを「考える」クラス階層を構築しました...

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Extract_Processing
{
    class Extract
    {
        private string mFilePath;
        private string mFileName;
        private FileHeader mFileHeader;
        private FileTrailer mFileTrailer;
        private List<Batch> mBatches;       // A file can have many batches

        public Extract(string filePath)
        { /* Using file path some static method from another class would be called to parse in the file somehow */ }

        public string ToString()
        { /* Iterates all objects down the heiarchy to return the file in string format */ }

        public void ToFile()
        { /* Calls some method in the file parse static class to export the file back to storage somewhere */ }
    }

    class FileHeader
    { /* ... contains data types for all fields in this format, ToString etc */ }

    class Batch
    {
        private string mBatchNumber;                // Should this be pulled out of the batch header to make LINQ querying simpler for this data set?
        private BatchHeader mBatchHeader;
        private BatchTrailer mBatchTrailer;
        private List<Transaction> mTransactions;    // A batch can have multiple transactions

        public string ToString()
        { /* Iterates through batches to return what the entire batch would look like in string format */ }
    }

    class BatchHeader
    { /* ... contains data types for all fields in this format, ToString etc */ }

    class Transaction
    { /* ... contains data types for all fields in this format, ToString etc */ }

    class BatchTrailer
    { /* ... contains data types for all fields in this format, ToString etc */ }

    class FileTrailer
    { /* ... contains data types for all fields in this format, ToString etc */ }

}

私は多くのコンストラクターや他のメソッドを省略しましたが、アイデアはかなりしっかりしているはずだと思います。私は、C#について知識がなく、実行時間が最優先事項である、私が再び検討している方法に対するアイデアと批評を探しています。

いくつかの批評以外の最大の質問は、このファイルをどのように持ち込むべきかということです。FSOメソッドを使用してVBAなどの他の言語で多くのファイルを取り込み、ファイルを読み取るためのMicrosoft Access ImportSpec(5回、仕様ごとに1つ...非効率的でした!)、で「カーソル」オブジェクトを作成しましたvisual foxpro(これはFAAAAAAASTでしたが、5回実行する必要がありました)が、C#で隠された宝石を探しています。

私の小説を読んでくれてありがとう、あなたがそれを理解するのに問題があるかどうか私に知らせてください。私は週末にこのデザインを調べて、購入するかどうかを確認し、この方法で実装するための努力をしたいと思っています。

4

3 に答える 3

4

FileHelpersは素晴らしいです。まだ活発に開発されていないように見えるという点でいくつかの欠点があり、プロパティを使用させる代わりに、フィールドにパブリック変数を使用するようになります。しかし、そうでなければ良い。

これらのファイルで何をしていますか?それらをSQLServerにロードしていますか?もしそうなら、そしてあなたが速くてシンプルなものを探しているなら、私はこのようなデザインをお勧めします:

  1. 5つのレコードタイプのそれぞれに対応するステージングテーブルをデータベースに作成します。問題をファイル自体にさかのぼって追跡できるように、LineNumber列とFileName列も追加することを検討してください。
  2. ファイルを1行ずつ読み取り、ビジネスオブジェクトに解析するか、テーブルに対応するADO.NETDataTableオブジェクトに直接解析します。
  3. ビジネスオブジェクトを使用した場合は、データ変換またはビジネスルールを適用してから、テーブルに対応するDataTableオブジェクトにデータを配置します。
  4. 各DataTableが適切なBatchSize(たとえば1000レコード)に達したら、SqlBulkCopyオブジェクトを使用してデータをステージングテーブルに送ります。各SqlBulkCopy操作の後で、DataTableをクリアして、処理を続行します。
  5. ビジネスオブジェクトを使用したくない場合は、SQLServerで最終的なデータ操作を行います。

おそらく、500行未満のC#ですべてを達成できるでしょう。

于 2010-07-03T15:17:35.147 に答える
2

いくつかの批評以外の最大の質問は、このファイルをどのように持ち込むべきかということです。

ファイルIOに適したライブラリはわかりませんが、読み取りは非常に簡単です。

64kBバッファを使用してStreamReaderクラスをインスタンス化し、ディスクIO操作を制限します(私の見積もりでは、月末のファイルあたり平均1500トランザクションです)。

これで、ファイルをストリーミングできます
。1)各行の先頭でを使用してRead、レコードのタイプを判別します。
2)ReadLineメソッドとメソッドを使用しString.Splitて列の値を取得します。
3)列の値を使用してオブジェクトを作成します。

また

ストリームからのデータを手動でバッファリングし、IndexOf+SubStringパフォーマンスを向上させることができます(正しく実行された場合)。

また、行が列ではなく、バイナリ形式のプリミティブデータ型である場合は、BinaryReaderクラスを使用して、オブジェクトを読み取るための非常に簡単でパフォーマンスの高い方法を使用できます。

于 2010-07-03T18:42:53.403 に答える
1

私が持っている批判の1つは、ToStringを正しく実装していないということです。

    public string ToString()

する必要があります:

    public override string ToString()
于 2010-07-03T14:54:10.403 に答える