3

別のサーバーで奇妙な問題に直面しIOExceptionています。これが私の話です:

ファイルの変更についてフォルダーを監視するWinサーバー(C#)があります。また、FTPサーバー(WinSSHD)は同じフォルダーを指します。誰かがファイルをアップロードすると、WinServiceは書き込みが完了したかどうかをチェックします。ファイルがアップロードされた場合、WinServiceはFile.Moveメソッドを介してファイルの名前を変更します。

書き込み完了チェックはFile.Openメソッドで行われます。このような:

public static bool IsWriteComplete(string filePath)
{
    bool isWriteComplete;
    FileStream stream = null;
    try
    {
        stream = File.Open(filePath, FileMode.Open, FileAccess.Write, FileShare.ReadWrite|FileShare.Delete);
        isWriteComplete = true;
    }
    catch (IOException)
    {
        isWriteComplete = false;
    }
    catch (Exception ex)
    {
        isWriteComplete = false;
    }
    finally
    {
        if (stream != null) { stream.Close(); }
    }
    return isWriteComplete;
}

何らかの理由で、あるサーバーでは完全に機能し(Win2003SP2)、別のサーバーではまったく機能しません(Win2003SP1)。IsWriteCompleteメソッドはTrueを示し、WinServerはファイルを移動しようとし、後で終了しIOExceptionます。そのような問題に関する参考文献は見つかりませんでした。

問題を修正するために、に置き換えましFile.OpenFile.Move。前:

stream = File.Open(filePath, FileMode.Open, FileAccess.Write, FileShare.ReadWrite|FileShare.Delete);

後:

File.Move(filePath, filePath);

そして今では、2番目のサーバー(Win2003SP1)で動作し、最初のサーバー(Win2003SP2)では動作しません。

なぜそれがそのように機能するのか誰かが知っていますか?

4

4 に答える 4

4

File.Openを使用すると、FileShare.Noneを使用している場合でも、「競合状態」になります。ファイルを閉じた後、File.Moveを呼び出す前に、別のスレッド/プロセスがファイルに侵入してロック(開く)する可能性があります。この他のプロセスはFTPサーバーではないかもしれませんが、ウイルスチェッカーなど、あなたが気付いていないものである可能性があります。したがって、File.Openの代わりにFile.Moveを使用し、File.Moveが失敗した場合はIOExceptionをキャッチし、成功するまで再試行する必要があります。

于 2012-08-28T10:35:42.253 に答える
1

を使用FileShare.ReadWrite|FileShare.Deleteすると、ファイルを開いているときに、他のプロセスがファイルを読み取ったり、書き込んだり、削除したりできるようになります。反対側では、他の人もファイルにアクセスしながらファイルを開くことができます。したがって、FileShare.Noneファイルを排他的に開こうとします。これは、ファイルがFTPサーバーで使用されている限り失敗するはずです。

また、を使用FileAccess.ReadWriteして、ファイルへの完全なアクセス権があることを確認する必要があります。FTPサーバーがファイルをロックする方法がわかりません。おそらく、アップロードの処理中に他のプロセスがファイルを読み取りモードで開くことができ、書き込みモードを拒否する可能性があります。だから、FileAccess.ReadWriteより良いです。

MSDNリファレンス: http: //msdn.microsoft.com/en-us/library/system.io.fileshare.aspxおよびhttp://msdn.microsoft.com/en-us/library/system.io.fileaccess.aspx

あなたのコードについて:

catch (IOException)
{
    isWriteComplete = false;
}
catch (Exception ex)
{
    isWriteComplete = false;
}

キャッチする場合は、のキャッチブロックは必要IOExceptionありませんException...

于 2012-08-28T10:13:00.407 に答える
0

または、別の方法でチェックしてからメソッドを開くこともできます。

FileInfo fileInfo = new FileInfo(filePath);
bool isNormal = ((fileInfo.Attributes & FileAttributes.Normal) == FileAttributes.Normal);

//or 

bool isReadOnly = ((fileInfo.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly);

ファイルが利用可能かどうかを理解するために、どちらの方法でもメソッドを見つけることができます。そして、あなたはステータスに基づいて続けることができます。

他に何かお探しの場合はお知らせください。

于 2012-08-28T10:05:01.667 に答える
0

動作の根本的な原因を見つけました。別のFTPサービスがインストールされていました:Techia。何らかの理由で、Tectiaはファイルのアップロードに書き込みロックを設定していません。そのため、File.Open(filePath、FileAccess.Write)はIOExceptionをスローしません。

于 2012-08-29T10:26:47.623 に答える