5

ネットワーク経由で大きなファイル (約 20 MB) をコピーする必要があります。通常、これは問題になりませんが、ファイルは、ファイルと同じボックスにあるアプリケーションによってかなり頻繁に (約 1 秒に 1 回) 書き込まれます。

したがって、ファイルはかなり頻繁に書き込まれるため、File.Copy呼び出しはかなり頻繁に失敗します。File.ReadAllLines毎回うまくいくように見えるが、永遠にかかるもの も試しました。

ネットワーク経由でファイルをコピーするための、より効率的で安全な方法はありますか?

PSファイルは、Log4Netを利用するプロセスによって書き込まれています。そして、誰かが疑問に思っている場合に備えて、執筆を行うプロセスは私の手に負えません.

4

7 に答える 7

1

ファイルを開くときにファイル共有フィールドを使用して、ファイルにアクセスしているときに他のプロセスがファイルにアクセスできるようにすることができます。残念ながら、プロセスがファイルをロックしているプロセスでない場合は、ファイルを解放する方法がなく、ファイルを解放することはできません。書き込みを行うコードを変更します。ファイル共有フィールドでr/wを許可することにより、コピー中に他のプロセスがファイルにアクセスできるようにすることができます。ファイルがロックされているかどうかを確認する小さな関数を記述し、コードを変更して、ロックされている間、ロックが解除されるまで確認を続けてからコピーすることができます。

于 2012-08-20T21:31:34.040 に答える
1

あなたはこうしてそれを扱うことを試みることができます:

string pathToFile = "path-to-your-file" ;
using ( Stream     s = File.Open( pathToFile , FileMode.Open , FileAccess.Read , FileShare.ReadWrite ) )
using ( TextReader r = new StreamReader( s ) )
{
    string fileContents = r.ReadToEnd() ;
    process( fileContents ) ;
}

ただし、ファイルに書き込んでいるプロセスが読み取り用にファイルを共有することを望まない場合は、SOLです。

でも 。。。あなたが言った:

PSファイルはLog4Netを利用するプロセスによって書き込まれています。そして、誰かが疑問に思っている場合に備えて、書き込みを行うプロセスは私の手に負えません。

アクセスしようとしているファイルは、FileAppenderRollingFileAppenderなどのLog4Net Appenderによって生成されていますか?

その場合、デフォルトのログモデルはですFileAppender.ExclusiveLock。これは、排他ロックを使用してファイルを開いたままにしますが、IIRCの場合は、読み取り用にファイルを共有します。

しかし、目的の結果を得る(ネットワーク経由でファイルを送信する)ためのさらに簡単な(なぜ車輪の再発明をするのか?)方法は、Log4Net構成を使用することです。役立つアペンダーをソースアプリケーションのLog4Net構成ファイルに追加できます。次のいずれかを使用できます。

  • RemotingAppenderは、「リモートシンクにイベントを配信するように設計されています。これは、RemotingAppender.IRemoteLoggingSinkインターフェイスを実装するオブジェクトです。.NETremotingを使用してイベントを配信します。イベントを配信するオブジェクトは、アペンダーのSinkプロパティを設定することで指定されます。」

  • TelnetAppenderは、「ソケット接続を受け入れ、ログメッセージをクライアントにストリーミングします。出力はTelnetに適した方法で提供されるため、TCP / IPソケットを介してログを監視できます。これにより、アプリケーションログの簡単なリモート監視が可能になります。デフォルトポートは23(telnetポート)です。」

いずれにせよ、インバウンドロギングメッセージを処理する単純なサービスを作成する必要があります。

効率に関する限り、log4net出力の場合は、最高水準点を追跡し、新しいものだけをコピーする必要があるように思われます。

  1. ソースファイルを開いて読み取ります
  2. ターゲットファイルを作成します
  3. ネットワークを介してファイルの終わりまでデータをコピーします
  4. ストリーム内の現在の位置を保存します
  5. 睡眠
  6. ソースファイルを開いて読み取ります
  7. 追加するターゲットファイルを開きます
  8. ストリーム内の記憶された位置をシークします(おそらくファイルの終わりではなくなります)
  9. ファイルの終わりまでネットワークを介してデータをコピーし、ターゲットファイルに追加します。
  10. 繰り返し、広告の吐き気、#4から

ちょっとした考え。

于 2012-08-20T22:49:36.383 に答える
0

ファイルに書き込むプログラムを変更できない場合、オプションは多少制限されます。考えられる可能性は次の2つです。

ファイルを排他的に開き、ループでコピーします。

using (var fin = File.Open(InputFilename, FileMode.Open, FileAccess.Read, FileShare.None))
{
    using (var fout = File.OpenWrite(OutputFilename))`
    {
        int bytesRead = 0;
        var buffer = new byte[65536];
        while ((bytesRead = fin.Read(buffer, 0, buffer.Length)) > 0)
        {
            fout.Write(buffer, 0, bytesRead);
        }
    }
}

読み取り用にファイルを開こうとしたときに、Log4Net が書き込み用にファイルを開いている場合にスローされる例外を処理するコードを記述する必要があります。そのコードは、少し待ってから再試行する必要があります。

ここでの潜在的な欠点は、Log4Net がファイルに書き込めない場合 (排他アクセス用に開かれているため)、例外をスローする可能性があることです。Log4Net が排他的アクセスのためにファイルを開くことを好まない場合は、...

ファイルの名前を変更するだけで、自由にコピーできます。名前を変更しようとしたときに Log4Net がファイルを開いている場合、コードは例外をスローします。再試行できます。名前を変更した後で Log4Net がファイルに書き込もうとすると、Log4Net はその名前で新しいファイルを作成します。

他のオプションは表示されません。

ところで、20 MB は実際には大きなファイルではありません。最新のネットワーク速度では、1 秒もかからずにコピーできるはずです。

于 2012-08-20T22:46:32.873 に答える
-1

最初にローカルでコピーを作成するのはどうですか?これは非常に高速で、その状態を保持し、次にコピーをアップロードし、最後にコピーを削除しますか?

于 2012-08-20T22:06:41.993 に答える