J'ai un dossier :
c : \test
J'essaie ce code :
File.Move(@"c:\test\SomeFile.txt", @"c:\test\Test");
Je reçois l'exception :
Le fichier existe déjà
Le répertoire de sortie existe bel et bien et le fichier d'entrée s'y trouve.
J'ai un dossier :
c : \test
J'essaie ce code :
File.Move(@"c:\test\SomeFile.txt", @"c:\test\Test");
Je reçois l'exception :
Le fichier existe déjà
Le répertoire de sortie existe bel et bien et le fichier d'entrée s'y trouve.
Ce dont vous avez besoin :
if (!File.Exists(@"c:\test\Test\SomeFile.txt")) {
File.Move(@"c:\test\SomeFile.txt", @"c:\test\Test\SomeFile.txt");
}
o
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");
Ce sera soit :
Edit : Je devrais clarifier ma réponse, même si elle est la plus votée ! Le second paramètre de File.Move devrait être le paramètre fichier de destination - no un dossier. Vous spécifiez le deuxième paramètre comme étant le dossier de destination, no le nom du fichier de destination - ce qui est ce que File.Move requiert. Donc, votre deuxième paramètre devrait être c:\test\Test\SomeFile.txt
.
Vous devez le déplacer vers un autre fichier (plutôt que vers un dossier), ce qui peut également être utilisé pour le renommer.
Bougez :
File.Move(@"c:\test\SomeFile.txt", @"c:\test\Test\SomeFile.txt");
Renommer :
File.Move(@"c:\test\SomeFile.txt", @"c:\test\SomeFile2.txt");
La raison pour laquelle il est dit "Le fichier existe déjà" dans votre exemple, c'est parce que C:\test\Test
essaie de créer un fichier Test
sans extension, mais ne peut le faire car un dossier existe déjà avec le même nom.
Personnellement, je préfère cette méthode. Cela écrase le fichier sur la destination, supprime le fichier source et empêche également la suppression du fichier source lorsque la copie échoue.
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
}
Cela convient pour les petits fichiers (et ne nécessite pas de déplacement atomique), mais pour les gros fichiers, ou les cas où vous devez être sûr de ne pas vous retrouver avec des doublons, c'est problématique.
Vous pouvez faire un P/Invoke pour MoveFileEx()
- passer 11 para flags
( MOVEFILE_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);
Ou, vous pouvez simplement appeler
Microsoft.VisualBasic.FileIO.FileSystem.MoveFile(existingFileName, newFileName, true);
après avoir ajouté Microsoft.VisualBasic comme référence.
Dans .NET Core 3.0 et les versions ultérieures, vous pouvez appeler Move(String, String, Boolean) en définissant le paramètre overwrite à true, ce qui remplacera le fichier s'il existe.
Source : Microsoft Docs
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.
2 votes
Si le fichier d'entrée se trouve déjà dans le répertoire de sortie, alors le fichier existe déjà, ce qui explique l'exception. Vous devez indiquer que vous voulez le fichier original écrasé par le nouveau.
11 votes
On dirait que l'erreur vous dit exactement ce qui ne va pas.
0 votes
@Josh Non. Il semble que Windows ait un comportement de système de fichiers non-POSIX qui rend impossible l'élaboration d'un modèle/routine de mise à jour de fichier transactionnel simple et portable.
0 votes
@binki POSIX n'est pas pertinent (vous faites référence à atomique ), NTFS hace prendre en charge les opérations transactionnelles réelles, comme le retour en arrière et la récupération du contenu du fichier original. Comme d'autres l'ont répondu, Win32 hace permettent de bouger en remplaçant. C'est File.Move de .NET qui ne fournit pas cette fonctionnalité. Vous pouvez obtenir à la fois Move with replace et les opérations transactionnelles avec des bibliothèques comme AlphaFS.
0 votes
@PanagiotisKanavos Les API de .net sont un reflet de l'API win32 mais excluent les choses utiles telles que
FileMoveEx()
. Par conséquent, .net ne dispose pas d'une couche FS de type POSIX. .net exposeFile.Replace()
mais en essayant d'implémenter un système POSIX-likerename()
en termes de résultats dans une condition de course. Si le cadre de travail exposait une méthode POSIX-likerename()
En effet, cela faciliterait la vie des gens et leur permettrait d'écrire un code plus pur (moins de P/Invoke).0 votes
Sauf personne ne semble dire que ce soit ou non
FileMoveEx()
conMOVEFILE_REPLACE_EXISTING
est atomique (bien que une personne du forum suggère que c'est probablement atomique sur le même volume source/destination pour NTFS. ).0 votes
@binki serait-il logique de dire que Java, Python ou R n'ont pas de couche FS de type POSIX ? C'est une caractéristique du système d'exploitation, pas une caractéristique du langage ou du runtime. Et les transactions, dans le sens pleinement distribué sont disponible auprès de TxF. Vous ne pouvez pas utiliser POSIX pour inscrire les opérations de fichiers et de bases de données dans la même transaction distribuée. POSIX n'a rien à voir avec quelle fonction de l'API Win32 est appelé par File.Move.
3 votes
@binki en tout cas le comportement est bien défini sur différents systèmes de fichiers peu importe ce que disent les discussions sur les forums. La raison pour laquelle File.Move n'appelle pas les méthodes Ex ou Transacted est que la FAT, qui ne peut être ignorée puisqu'elle est toujours utilisée par les cartes mémoire, n'est pas atomique et n'a pas se comportent de la même manière. Les renommages ne sont pas des opérations sur les métadonnées et nécessitent un mouvement réel des données. Et oubliez les transactions et le copy-on-write. Ce n'est pas une bonne décision.