33

私はどうやら悪いコーディングの習慣を身につけてしまったようです。これが私が書いてきたコードの例です:

using(StreamReader sr = new StreamReader(File.Open("somefile.txt", FileMode.Open)))
{
    //read file
}
File.Move("somefile.txt", "somefile.bak"); //can't move, get exception that I the file is open

using句が明示的に呼び出さClose()Dispose()StreamReaderFileStream閉じられると考えました。

私が抱えていた問題を解決できる唯一の方法は、上記のブロックを次のように変更することでした。

using(FileStream fs = File.Open("somefile.txt", FileMode.Open))
{
  using(StreamReader sr = new StreamReader(fs))
  {
    //read file
  }
}

File.Move("somefile.txt", "somefile.bak"); // can move file with no errors

StreamReader最初のブロックで破棄して を閉じ、基になる も閉じる必要がありFileStreamますか? それとも、私は間違っていましたか?

編集

実際に問題のあるコード ブロックを投稿して、この問題の根底に到達できるかどうかを確認することにしました。私は今ちょうど興味があります。

句に問題があると思ったusingので、すべてを展開しましたが、それでも毎回コピーできません。このメソッド呼び出しでファイルを作成するので、ファイルのハンドルを開いているものは他にないと思います。Path.Combineまた、呼び出しから返された文字列が正しいことも確認しました。

private static void GenerateFiles(List<Credit> credits)
{
    Account i;
    string creditFile = Path.Combine(Settings.CreditLocalPath, DateTime.Now.ToString("MMddyy-hhmmss") + ".credits");

    StreamWriter creditsFile = new StreamWriter(File.Open(creditFile, FileMode.Create));

    creditsFile.WriteLine("code\inc");

    foreach (Credit c in credits)
    {
        if (DataAccessLayer.AccountExists(i))
        {
            string tpsAuth = DataAccessLayer.GetAuthCode(i.Pin);
            creditsFile.WriteLine(String.Format("{0}{1}\t{2:0.00}", i.AuthCode, i.Pin, c.CreditAmount));
        }
        else
        {
            c.Error = true;
            c.ErrorMessage = "NO ACCOUNT";
        }

        DataAccessLayer.AddCredit(c);

    }

    creditsFile.Close();
    creditsFile.Dispose();

    string dest =  Path.Combine(Settings.CreditArchivePath, Path.GetFileName(creditFile));
    File.Move(creditFile,dest);
    //File.Delete(errorFile);
}
4

5 に答える 5

41

はい、StreamReader.Dispose基になるストリームを閉じます (ストリームを作成するすべてのパブリックな方法に対して)。ただし、より良い代替手段があります。

using (TextReader reader = File.OpenText("file.txt"))
{
}

これには、基になるストリームを開き、Windows に順次アクセスするというヒントを与えるという追加の利点があります。

これは、最初のバージョンが機能することを示すテストアプリです。それが特定の何かの証拠だと言うつもりはありませんが、あなたにとってどれだけうまく機能するか知りたいです.

using System;
using System.IO;

class Program
{
    public static void Main(string[] args)
    {
        for (int i=0; i < 1000; i++)
        {
            using(StreamReader sr = new StreamReader
                  (File.Open("somefile.txt", FileMode.Open)))
            {
                Console.WriteLine(sr.ReadLine());
            }
            File.Move("somefile.txt", "somefile.bak");
            File.Move("somefile.bak", "somefile.txt");
        }
    }
}

それが機能する場合、それは読書中に行うことと関係があることを示唆しています...

そして、編集した質問コードの短縮版を次に示します。これも、ネットワーク共有でも問題なく動作します。FileMode.Createに変更したことに注意してくださいFileMode.CreateNew-そうでなければ、古いファイルのハンドルを持つアプリがまだあった可能性があります。これはうまくいきますか?

using System;
using System.IO;

public class Test
{    
    static void Main()
    {
        StreamWriter creditsFile = new StreamWriter(File.Open("test.txt", 
                                          FileMode.CreateNew));

        creditsFile.WriteLine("code\\inc");

        creditsFile.Close();
        creditsFile.Dispose();

        File.Move("test.txt", "test2.txt");
    }
}
于 2009-04-01T21:06:42.770 に答える
12

注 - using ブロックは、独自のブロックにネストする必要はありません。次のように、連続していてもかまいません。

using(FileStream fs = File.Open("somefile.txt", FileMode.Open))
using(StreamReader sr = new StreamReader(fs))
{
    //read file
}

この場合の破棄の順序は、ネストされたブロックと同じです (つまり、この場合、StreamReader は依然として FileStream の前に破棄されます)。

于 2009-04-01T21:40:11.970 に答える
0

これはコーディングの問題ではないように思われるので、システム管理者の帽子をかぶっていくつかの提案をします。

  1. 作成時にファイルをスキャンするクライアントまたはサーバー上のウイルス スキャナー。
  2. Windows日和見ロックには、ネットワーク共有を台無しにする癖があります。フラットファイルデータベースを使用する複数の読み取り/書き込みクライアントで主に問題になっていることを思い出しますが、キャッシュは確かに問題を説明できます.
  3. Windowsファイル オープン キャッシュ。これが Win2K でも問題になるかどうかはわかりませんが、FileMon が教えてくれます。

編集:サーバーマシンからの行為でそれをキャッチできる場合、Sysinternalのハンドルは何が開いているかを教えてくれます。

于 2009-04-03T00:00:56.500 に答える
0

他の何かが somefile.txt をロックしている可能性はありますか?

ローカル (ファイルへの) コマンドラインからの簡単なチェック

net files

他にロックがある場合は、いくつかの手がかりが得られる可能性があります。

または、 FileMonのようなものを入手して、さらに詳細を取得し、アプリが適切にリリースされていることを確認することもできます。

于 2009-04-01T21:41:29.830 に答える