Hiermit können Sie prüfen, ob eine Datei gesperrt ist:
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;
}
}
Aus Leistungsgründen empfehle ich Ihnen, den Inhalt der Datei im selben Arbeitsgang zu lesen. Hier sind einige Beispiele:
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;
}
Probieren Sie es selbst aus:
byte[] output1 = Helper.ReadFileBytes(@"c:\temp\test.txt");
string output2 = Helper.ReadFileTextWithEncoding(@"c:\temp\test.txt");
string output3 = Helper.ReadFileTextNoEncoding(@"c:\temp\test.txt");
35 Stimmen
Sie können dies testen, indem Sie alle offenen Handles auf dem System untersuchen. Da es sich bei Windows jedoch um ein Multitasking-Betriebssystem handelt, besteht die Möglichkeit, dass direkt nach der Ausführung des Codes, mit dem festgestellt werden soll, ob die Datei geöffnet ist, ein Prozesscode mit der Verwendung dieser Datei beginnt und zu dem Zeitpunkt, zu dem Sie versuchen, sie zu verwenden, ein Fehler auftritt. Es ist jedoch nicht verkehrt, zuerst zu prüfen, ob die Datei geöffnet ist; gehen Sie nur nicht davon aus, dass sie nicht verwendet wird, wenn Sie sie tatsächlich benötigen.
6 Stimmen
Aber gerade für dieses spezielle Problem würde ich empfehlen, die Dateihandles nicht zu untersuchen und nur eine bestimmte Anzahl von Versuchen durchzuführen, z. B. 3-5, bevor sie fehlschlagen.
0 Stimmen
Wie wird diese Bilddatei erstellt? Können Sie Ihr Programm anhalten/schlafen/pausieren, bis die Erzeugung abgeschlossen ist? Das ist bei weitem der bessere Weg, um die Situation zu bewältigen. Wenn nicht, dann glaube ich nicht, dass Sie eine Ausnahmebehandlung vermeiden können.
0 Stimmen
Ist nicht jede Verwendung von Ausnahmen eine Überprüfung einer Annahme, indem man etwas potenziell Gefährliches tut und dabei absichtlich die Möglichkeit eines Fehlschlags nicht ausschließt?
40 Stimmen
Ihre Philosophie hat ein schlechtes Verständnis von Ausnahmen. Die meisten Leute denken, Ausnahmen bedeuten heilige Scheiße-aus-dem-Doom-irgendetwas-ist-falsch-die-die-die. Wenn Ausnahme bedeutet.... Ausnahme. Es bedeutet, dass etwas Außergewöhnliches passiert ist, das Sie "behandeln" (oder berücksichtigen) müssen. Vielleicht wollen Sie den Datenzugriff immer wieder versuchen, vielleicht muss der Benutzer wissen, dass Sie keine Verbindung herstellen können. Was tun Sie dann? Sie behandeln die ConnectionFailedException und benachrichtigen den Benutzer, so dass er vielleicht nach einer Stunde aufhört, es zu versuchen, und bemerkt, dass das Kabel ausgesteckt ist.
0 Stimmen
Warum die Prüfung und Verarbeitung in verschiedenen Prozeduren? try {open file in FileShare.None; process file; close file} catch {filelocked) {///locked, we'll get it next time}
2 Stimmen
Lee Louviere hat eine berechtigte Abneigung dagegen, mit Ausnahmen zu arbeiten. Wenn man mit der filexists-Methode leicht herausfinden kann, ob eine Datei existiert, gibt es dann einen ähnlichen Befehl, um herauszufinden, ob die Datei, mit der man arbeiten möchte, in Gebrauch ist? Ich glaube, das ist die eigentliche Frage, die der Benutzer stellt.
1 Stimmen
@webs Manche Ausnahmen sind einfach eine Tatsache. Die Verwendung von File.Exists() ist gut, aber wie die Antwort sagt, ist es nicht immer möglich, sie zu vermeiden. Zum Beispiel könnte eine Datei zwischen dem Zeitpunkt, an dem Sie prüfen, ob sie existiert, und dem Zeitpunkt, an dem Sie sie tatsächlich öffnen, existieren. Diese unbestimmte Zeitspanne ist in den meisten Fällen gut genug, aber es gibt keine Garantien und daher sollte ein Exception-Handler den Aufruf zum Öffnen der Datei einschließen usw.
1 Stimmen
@webs Wenn Sie leicht filexists Methode verwenden können, um zu wissen, ob eine Datei vorhanden ist, was ähnlichen Befehl vorhanden ist, um zu wissen, ob die Datei, die Sie mit arbeiten möchten, in Gebrauch ist? Ich bin etwas spät dran, aber diese beiden Beispiele sind TOCTOU-Wanzen . Die Ergebnisse sind sofort ungültig. "Check-then-do" ist nutzlos - der "Check" kann nicht mit dem "Do" identisch sein, so dass der "Check" aus unterschiedlichen Gründen fehlschlagen oder erfolgreich sein kann, wenn der "Do" fehlschlagen würde. Wenn Sie eine Datei öffnen müssen DATEI ÖFFNEN . Nichts anderes kann Ihnen einen endgültigen Beweis dafür liefern, dass die Öffnung funktionieren wird.
2 Stimmen
Was ist, wenn ich nicht herausfinden möchte, ob ich überhaupt in eine Datei schreiben KANN, sondern ob ich lieber nicht schreiben sollte, obwohl ich es könnte, weil jemand anderes gerade an derselben Datei arbeitet?