Utilisez cette option pour vérifier si un fichier est verrouillé :
using System.IO;
using System.Runtime.InteropServices;
internal static class Helper
{
const int ERROR_SHARING_VIOLATION = 32;
const int ERROR_LOCK_VIOLATION = 33;
private static bool IsFileLocked(Exception exception)
{
int errorCode = Marshal.GetHRForException(exception) & ((1 << 16) - 1);
return errorCode == ERROR_SHARING_VIOLATION || errorCode == ERROR_LOCK_VIOLATION;
}
internal static bool CanReadFile(string filePath)
{
//Try-Catch so we dont crash the program and can check the exception
try {
//The "using" is important because FileStream implements IDisposable and
//"using" will avoid a heap exhaustion situation when too many handles
//are left undisposed.
using (FileStream fileStream = File.Open(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None)) {
if (fileStream != null) fileStream.Close(); //This line is me being overly cautious, fileStream will never be null unless an exception occurs... and I know the "using" does it but its helpful to be explicit - especially when we encounter errors - at least for me anyway!
}
}
catch (IOException ex) {
//THE FUNKY MAGIC - TO SEE IF THIS FILE REALLY IS LOCKED!!!
if (IsFileLocked(ex)) {
// do something, eg File.Copy or present the user with a MsgBox - I do not recommend Killing the process that is locking the file
return false;
}
}
finally
{ }
return true;
}
}
Pour des raisons de performance, je vous recommande de lire le contenu du fichier dans la même opération. Voici quelques exemples :
public static byte[] ReadFileBytes(string filePath)
{
byte[] buffer = null;
try
{
using (FileStream fileStream = File.Open(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
{
int length = (int)fileStream.Length; // get file length
buffer = new byte[length]; // create buffer
int count; // actual number of bytes read
int sum = 0; // total number of bytes read
// read until Read method returns 0 (end of the stream has been reached)
while ((count = fileStream.Read(buffer, sum, length - sum)) > 0)
sum += count; // sum is a buffer offset for next reading
fileStream.Close(); //This is not needed, just me being paranoid and explicitly releasing resources ASAP
}
}
catch (IOException ex)
{
//THE FUNKY MAGIC - TO SEE IF THIS FILE REALLY IS LOCKED!!!
if (IsFileLocked(ex))
{
// do something?
}
}
catch (Exception ex)
{
}
finally
{
}
return buffer;
}
public static string ReadFileTextWithEncoding(string filePath)
{
string fileContents = string.Empty;
byte[] buffer;
try
{
using (FileStream fileStream = File.Open(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
{
int length = (int)fileStream.Length; // get file length
buffer = new byte[length]; // create buffer
int count; // actual number of bytes read
int sum = 0; // total number of bytes read
// read until Read method returns 0 (end of the stream has been reached)
while ((count = fileStream.Read(buffer, sum, length - sum)) > 0)
{
sum += count; // sum is a buffer offset for next reading
}
fileStream.Close(); //Again - this is not needed, just me being paranoid and explicitly releasing resources ASAP
//Depending on the encoding you wish to use - I'll leave that up to you
fileContents = System.Text.Encoding.Default.GetString(buffer);
}
}
catch (IOException ex)
{
//THE FUNKY MAGIC - TO SEE IF THIS FILE REALLY IS LOCKED!!!
if (IsFileLocked(ex))
{
// do something?
}
}
catch (Exception ex)
{
}
finally
{ }
return fileContents;
}
public static string ReadFileTextNoEncoding(string filePath)
{
string fileContents = string.Empty;
byte[] buffer;
try
{
using (FileStream fileStream = File.Open(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
{
int length = (int)fileStream.Length; // get file length
buffer = new byte[length]; // create buffer
int count; // actual number of bytes read
int sum = 0; // total number of bytes read
// read until Read method returns 0 (end of the stream has been reached)
while ((count = fileStream.Read(buffer, sum, length - sum)) > 0)
{
sum += count; // sum is a buffer offset for next reading
}
fileStream.Close(); //Again - this is not needed, just me being paranoid and explicitly releasing resources ASAP
char[] chars = new char[buffer.Length / sizeof(char) + 1];
System.Buffer.BlockCopy(buffer, 0, chars, 0, buffer.Length);
fileContents = new string(chars);
}
}
catch (IOException ex)
{
//THE FUNKY MAGIC - TO SEE IF THIS FILE REALLY IS LOCKED!!!
if (IsFileLocked(ex))
{
// do something?
}
}
catch (Exception ex)
{
}
finally
{
}
return fileContents;
}
Essayez vous-même :
byte[] output1 = Helper.ReadFileBytes(@"c:\temp\test.txt");
string output2 = Helper.ReadFileTextWithEncoding(@"c:\temp\test.txt");
string output3 = Helper.ReadFileTextNoEncoding(@"c:\temp\test.txt");
33 votes
Très bien, vous pouvez le tester en examinant tous les handles ouverts sur le système. Cependant, comme Windows est un système d'exploitation multitâche, il est possible que, juste après avoir exécuté le code pour déterminer si le fichier est ouvert et que vous estimiez qu'il ne l'est pas, un code de processus commence à utiliser ce fichier, puis, au moment où vous essayez de l'utiliser, vous recevez une erreur. Mais il n'y a rien de mal à vérifier d'abord ; ne supposez pas qu'il n'est pas utilisé lorsque vous en avez réellement besoin.
4 votes
Mais juste pour ce problème spécifique, je recommanderais de ne pas examiner les poignées de fichiers et de juste essayer un nombre prédéfini de fois, disons 3-5 avant d'échouer.
0 votes
Comment ce fichier image est-il généré ? Pouvez-vous arrêter/se mettre en veille/pause votre programme jusqu'à ce que la génération soit terminée ? C'est de loin une meilleure façon de gérer la situation. Sinon, je ne pense pas que vous puissiez éviter d'utiliser le traitement des exceptions.
0 votes
L'utilisation des exceptions ne consiste-t-elle pas à vérifier une hypothèse en faisant quelque chose de potentiellement dangereux tout en n'excluant pas délibérément la possibilité d'un échec ?
36 votes
Votre philosophie a une mauvaise compréhension des exceptions. La plupart des gens pensent qu'exception veut dire "holy-crap-out-of-doom-something's-wrong-die-die-die". Quand exception signifie.... exception. Cela signifie que quelque chose d'exceptionnel s'est produit et que vous devez le "gérer" (ou en tenir compte). Peut-être voulez-vous continuer à réessayer pour accéder aux données, peut-être l'utilisateur doit-il savoir que vous ne pouvez pas obtenir de connexion. Que faites-vous ? Vous traitez l'exception ConnectionFailedException et vous en informez l'utilisateur. Peut-être arrêtera-t-il d'essayer après une heure et remarquera-t-il que le câble est débranché.
0 votes
Pourquoi avoir la vérification et le traitement dans des procédures différentes ? try {open file in FileShare.None ; process file ; close file} catch {filelocked) {//locked, we'll get it next time}
1 votes
Lee Louviere l'op a une aversion valide pour le travail avec des exceptions. Si vous pouvez facilement utiliser la méthode filexists pour savoir si un fichier existe, quelle commande similaire existe pour savoir si le fichier sur lequel vous voulez travailler est en cours d'utilisation ? En fait, je crois que c'est la question que l'op pose vraiment.
1 votes
@webs Certaines exceptions sont juste une réalité de la vie. Utiliser File.Exists() est une bonne chose, mais comme le dit la réponse, il n'est pas toujours possible de les éviter. Par exemple, un fichier peut exister entre le moment où vous vérifiez s'il existe et celui où vous l'ouvrez réellement. Cette période indéfinie est suffisante la plupart du temps, mais il n'y a pas de garanties et donc un gestionnaire d'exception doit envelopper l'appel pour l'ouvrir, etc.
1 votes
@webs Si vous pouvez facilement utiliser la méthode filexists pour savoir si un fichier existe, quelle commande similaire existe pour savoir si le fichier avec lequel vous voulez travailler est en cours d'utilisation ? C'est un peu tard, mais ces deux exemples sont bugs TOCTOU . Les résultats sont immédiatement invalides. "Check-then-do" est inutile - le "check" ne peut pas être identique au "do", donc le "check" peut échouer pour des raisons différentes ou réussir quand le "do" échouerait. Lorsque vous devez ouvrir un fichier OUVRIR LE DOSSIER . Rien d'autre ne peut vous donner la preuve définitive que l'ouverture fonctionnera.
1 votes
Que faire si je ne veux pas savoir si je PEUX écrire dans un fichier, mais si je préfère ne pas le faire bien que je le puisse, parce que quelqu'un d'autre est en train de travailler sur ce même fichier ?