File.Moveが機能しない-ファイルはすでに存在します


86

私はフォルダを持っています:

c:\ test

私はこのコードを試しています:

File.Move(@"c:\test\SomeFile.txt", @"c:\test\Test");

例外が発生します:

ファイルが既に存在します

出力ディレクトリは確実に存在し、入力ファイルはそこにあります。


2
入力ファイルがすでに出力ディレクトリにある場合、そのファイルはすでに存在しているため、例外が説明されます。元のファイルを新しいファイルで上書きすることを指定する必要があります。
コーディグレイ

9
エラーが何が悪いのかを正確に伝えているように聞こえます。
Josh

@Joshいいえ。WindowsのファイルシステムがPOSIX以外の動作をしているため、単純なポータブルトランザクションファイルの更新パターン/ルーチンを理解できないようです。
binki 2016年

@binki POSIXは無関係です(アトミック操作を参照していますか?)。NTFS、rollback-and-get-the-original-file-content-backのように、実際のトランザクション操作をサポートします。他の人が答えたように、Win32replaceでの移動を許可します。機能を提供しない.NETのFile.Moveです。AlphaFSのようなライブラリを使用してMovewithreplaceとトランザクション操作の両方を取得できます
Panagiotis Kanavos 2018

2
いずれにせよ、@ binkiは、フォーラムの議論が何を言おうと、さまざまなファイルシステムで適切に定義されています。File.MoveはEXや繝ウ繧カ繧ッ繧キ繝ァ繝ウメソッドを呼び出していない理由は、それがまだメモリカードで使われていますので、無視できないFATは、ということではなく、アトミックとしません同じように振る舞います。名前の変更はメタデータ操作ではなく、実際のデータ移動が必要です。そして、トランザクションとコピーオンライトを忘れてください。素晴らしい決断ではありません
Panagiotis Kanavos 2018

回答:


62

(フォルダではなく)別のファイルに移動する必要があります。これを使用して名前を変更することもできます。

移動:

File.Move(@"c:\test\SomeFile.txt", @"c:\test\Test\SomeFile.txt");

名前の変更:

File.Move(@"c:\test\SomeFile.txt", @"c:\test\SomeFile2.txt");

例で「ファイルは既に存在します」と表示されているのは、拡張子のないC:\test\Testファイルを作成しようとしているTestが、同じ名前のフォルダーが既に存在しているため作成できないためです。


138

必要なものは次のとおりです。

if (!File.Exists(@"c:\test\Test\SomeFile.txt")) {
    File.Move(@"c:\test\SomeFile.txt", @"c:\test\Test\SomeFile.txt");
}

または

if (File.Exists(@"c:\test\Test\SomeFile.txt")) {
    File.Delete(@"c:\test\Test\SomeFile.txt");
}
File.Move(@"c:\test\SomeFile.txt", @"c:\test\Test\SomeFile.txt");

これは次のいずれかになります。

  • ファイルが宛先の場所に存在しない場合は、ファイルを正常に移動するか、または;
  • ファイルが宛先の場所に存在する場合は、ファイルを削除してからファイルを移動します。

編集:それが最も賛成ですが、私は私の答えを明確にする必要があります!File.Moveの2番目のパラメータは、あるべき宛先ファイル-ではないフォルダ。2番目のパラメーターを宛先ファイル名ではなく宛先フォルダーとして指定しています。これはFile.Moveに必要なものです。したがって、2番目のパラメータはc:\test\Test\SomeFile.txt


彼がチェックしていてファイルがそこにないので、確かにファイルがそこにないかどうかをチェックする必要はありません。例外は、ファイル名を別のフォルダーに移動しようとしたときに、宛先フォルダーにファイル名を追加しないことが原因で発生します。
Hadi Eskandari 2012年

3
アプリがマルチスレッドの場合(またはファイルで動作している他のプロセスがある場合)、「if(Exists)Delete」コードを使用しても同じ例外が発生する可能性があります。削除後に別のスレッド/プロセスがファイルを元に戻す可能性がある時間のスペースがまだあるので、移動を実行してから、とにかく例外を取得します。
覚えておく価値

11
この答えは、既存のファイルを上書きしようとした後にグーグルで検索するほとんどの人にまだ有効です。この窮地にあるほとんどの人は、OPのような構文/タイプoの問題を抱えていません。
WEFX 2013

1
@ v.oddou興味深いことに、ファイルが存在しない場合、File.Deleteは実際に正しく機能し、何もしません。代わりに、パス内のディレクトリのいずれかが存在しない場合は、DirectoryNotFoundExceptionが発生します。
ブランドン・バークレイ

2
@JirkaHanika if(File.Exists)をwhile(File.Exists)に変更できます。
ブランドン・バークレイ

38

個人的にはこの方法が好きです。これにより、宛先のファイルが上書きされ、ソースファイルが削除され、コピーが失敗したときにソースファイルが削除されなくなります。

string source = @"c:\test\SomeFile.txt";
string destination = @"c:\test\test\SomeFile.txt";

try
{
    File.Copy(source, destination, true);
    File.Delete(source);
}
catch
{
    //some error handling
}

4
これは小さなファイル(およびアトミック移動の要件なし)には問題ありませんが、大きなファイル、または重複が発生しないことを確認する必要がある場合は、問題があります。
サティア川2017年

なぜあなたは好きですFile.Copy , File.Delete以上File.Move
John Pietrar 2017

6
File.Moveには上書きオプションがありません。
ミッチェル

1
ユースケースによっては、これが問題を引き起こす可能性があります。「移動」は、ファイルシステムウォッチャーの実際のイベントです。ファイルシステムイベントへのリストは、moveイベントではなくdeleteイベントとcreateイベントを取得します。これにより、基になるファイルシステムIDも変更されます。
AndrewRondeau18年

1
これは、大きなファイルのパフォーマンスが大幅に低下しませんか?ソースと宛先が同じ物理ボリューム上にある場合、理由もなく2番目のコピーを作成してから元のコピーを削除しますが、ソースと宛先が同じボリューム上にある場合、File.Move()は余分な作業を回避します。
BradWestness19年

18

P / Invokeを実行できますMoveFileEx()- ()の11を渡しますflagsMOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH

[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("kernel32.dll", SetLastError=true, CharSet=CharSet.Unicode)]
static extern bool MoveFileEx(string existingFileName, string newFileName, int flags);

または、電話することもできます

Microsoft.VisualBasic.FileIO.FileSystem.MoveFile(existingFileName, newFileName, true);

Microsoft.VisualBasicを参照として追加した後。


アプリがWindowsでのみ実行されている場合は、まったく問題ありません。これは、Som P / Invokeを試してみようとするほとんどの人にとっておそらく良い答えです。
トッド

9

ファイルが実際に存在し、それを置き換えたい場合は、以下のコードを使用してください。

string file = "c:\test\SomeFile.txt"
string moveTo = "c:\test\test\SomeFile.txt"

if (File.Exists(moveTo))
{
    File.Delete(moveTo);
}

File.Move(file, moveTo);

4

File.Moveのドキュメントによると「存在する場合は上書き」パラメータはありません。宛先フォルダを指定しようとしましたが、完全なファイル指定を指定する必要があります。

ドキュメントをもう一度読んで(「新しいファイル名を指定するオプションを提供する」)、宛先フォルダーの仕様にバックスラッシュを追加するうまくいくと思います。


また、ドキュメントに は、同じ名前のファイルをそのディレクトリに移動してファイルを置き換えようとすると、IOExceptionがスローされることに注意してください。そのためには、Move(String, String, Boolean)代わりに電話してください。しかし、それは間違いのようですか?
ケビンシャルンホルスト

@KevinScharnhorstこの回答は2011年でした。ドキュメントには、Move withOverwriteの.NetCore3.0サポートが含まれるようになりました。
トッド

4

1).Net Core 3.0以降のC#では、3番目のブールパラメーターがあります。

https://docs.microsoft.com/en-us/dotnet/api/system.io.file.move?view=netcore-3.1を参照してください

In .NET Core 3.0 and later versions, you can call Move(String, String, Boolean) setting the parameter overwrite to true, which will replace the file if it exists.

2).Netの他のすべてのバージョンについては、https://stackoverflow.com/a/42224803/887092がベストアンサーです。上書きでコピーしてから、ソースファイルを削除します。これはアトミック操作になるため、より優れています。(私はこれでMSドキュメントを更新しようとしました)



1

新しい場所にある既存のファイルを削除するオプションがないが、元の場所から移動して削除する必要がある場合は、次の名前変更のトリックが機能する可能性があります。

string newFileLocation = @"c:\test\Test\SomeFile.txt";

while (File.Exists(newFileLocation)) {
    newFileLocation = newFileLocation.Split('.')[0] + "_copy." + newFileLocation.Split('.')[1];
}
File.Move(@"c:\test\SomeFile.txt", newFileLocation);

これは、「。」のみを想定しています。ファイル名のは拡張子の前です。拡張子の前にファイルを2つに分割し、「_ copy」を添付します。間に。これにより、ファイルを移動できますが、ファイルがすでに存在するか、コピーのコピーがすでに存在する場合、またはコピーのコピーのコピーが存在する場合は、コピーが作成されます...;)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.