[英]Unable to delete some files via System.IO.File in C# console app
我正在加密一些文本文件。 加密文件時效果很好,但是,有時我在嘗試刪除原始未加密文件時收到此錯誤:
System.IO.IOException: 該進程無法訪問文件'MyFile.TXT',因為它正在被另一個進程使用。 在FileEncryption \\ Program.cs:第159行的System.IO.File.Delete(字符串路徑)在System.IO .__ Error.WinIOError(Int32 errorCode,字符串mayFullPath)在FileEncryption.Program.DeleteFile(String sInputFilename)
這似乎在大型文本文件上發生。 (50MB +),但並非總是如此。
知道我做錯了什么嗎?
處理txt文件文件夾的方法:
private static void BeginFileProcessing(string sSecretKey_)
{
DirectoryInfo di = new DirectoryInfo(_sourcePath);
FileInfo[] files = di.GetFiles(_fileType);
try
{
foreach (FileInfo file in files)
{
string thisFileExt = Path.GetExtension(file.Name);
string thisFileName = Path.GetFileNameWithoutExtension(file.Name);
string encFileName = String.Format("{0}-enc{1}", thisFileName, thisFileExt);
if (_TestingOnly)
{
Console.Write("Source: " + file.Name + " " +
" Encrypted File: " + encFileName + "\n");
}
EncryptFile(file.FullName, _targetPath + encFileName, sSecretKey_);
if (_DeleteOriginal)
{
Console.WriteLine("Deleteing file: " + file.FullName);
DeleteFile(file.FullName);
}
}
}
catch (Exception ex)
{
LogWriter(string.Format("\nError Decrypting file: {0}", ex), true);
}
}
加密文件的方法
private static void EncryptFile(string sInputFilename,
string sOutputFilename, string sKey)
{
FileStream fsInput =
new FileStream(sInputFilename, FileMode.Open, FileAccess.Read);
FileStream fsEncrypted =
new FileStream(sOutputFilename, FileMode.Create, FileAccess.Write);
DESCryptoServiceProvider DES = new DESCryptoServiceProvider();
DES.Key = ASCIIEncoding.ASCII.GetBytes(sKey);
DES.IV = ASCIIEncoding.ASCII.GetBytes(sKey);
ICryptoTransform desencrypt = DES.CreateEncryptor();
CryptoStream cryptostream =
new CryptoStream(fsEncrypted, desencrypt, CryptoStreamMode.Write);
try
{
byte[] bytearrayinput = System.IO.File.ReadAllBytes(sInputFilename);
fsInput.Read(bytearrayinput, 0, bytearrayinput.Length);
cryptostream.Write(bytearrayinput, 0, bytearrayinput.Length);
cryptostream.Close();
fsInput.Close();
fsEncrypted.Close();
}
catch (Exception ex)
{
string error = "";
foreach (DictionaryEntry pair in ex.Data)
{
error += pair.Key + " = " + pair.Value + "\n";
Console.WriteLine(error);
}
LogWriter(error, true);
}
}
刪除文件的方法
private static void DeleteFile(string sInputFilename)
{
try
{
if (_TestingOnly)
{
Console.WriteLine("TESTING ONLY! File: " + sInputFilename + " would have been deleted.");
}
else
{
File.Delete(sInputFilename);
}
}
catch (Exception ex)
{
Console.Write(ex.ToString());
LogWriter(ex.ToString(), true);
}
}
這可能是由於調用EncryptFile
之后沒有關閉文件引起的。 在原始代碼中,如果您在EncryptFile
遇到異常,則如果異常發生在調用Close
之前,流將保持打開狀態。 使用Using
語句使此操作更容易,但是您也可以將Close
放在finally
塊中,如果流不為null,則關閉流。
這是使用Using
的示例:
private static void EncryptFile(string sInputFilename,
string sOutputFilename, string sKey)
{
using(FileStream fsInput = new FileStream(sInputFilename, FileMode.Open, FileAccess.Read),
FileStream fsEncrypted = new FileStream(sOutputFilename, FileMode.Create, FileAccess.Write))
{
DESCryptoServiceProvider DES = new DESCryptoServiceProvider();
DES.Key = ASCIIEncoding.ASCII.GetBytes(sKey);
DES.IV = ASCIIEncoding.ASCII.GetBytes(sKey);
ICryptoTransform desencrypt = DES.CreateEncryptor();
using(CryptoStream cryptostream =
new CryptoStream(fsEncrypted, desencrypt, CryptoStreamMode.Write))
{
try
{
byte[] bytearrayinput = System.IO.File.ReadAllBytes(sInputFilename);
fsInput.Read(bytearrayinput, 0, bytearrayinput.Length);
cryptostream.Write(bytearrayinput, 0, bytearrayinput.Length);
}
catch (Exception ex)
{
string error = "";
foreach (DictionaryEntry pair in ex.Data)
{
error += pair.Key + " = " + pair.Value + "\n";
Console.WriteLine(error);
}
LogWriter(error, true);
}
}
}
}
編輯
我建議的代碼將解決文件流保持打開狀態的問題。 但是,問題的根源在於,如果文件很大,系統在讀取文件時會拋出OutOfMemoryException
。 原始代碼將讀取所有字節,然后再次將字節讀取到同一緩沖區中,這既浪費內存,又浪費時間。 以下是更正的版本:
private static void EncryptFile(string sInputFilename,
string sOutputFilename, string sKey)
{
using(FileStream fsInput = new FileStream(sInputFilename, FileMode.Open, FileAccess.Read),
fsEncrypted = new FileStream(sOutputFilename, FileMode.Create, FileAccess.Write))
{
DESCryptoServiceProvider DES = new DESCryptoServiceProvider();
DES.Key = ASCIIEncoding.ASCII.GetBytes(sKey);
DES.IV = ASCIIEncoding.ASCII.GetBytes(sKey);
ICryptoTransform desencrypt = DES.CreateEncryptor();
using(CryptoStream cryptostream =
new CryptoStream(fsEncrypted, desencrypt, CryptoStreamMode.Write))
{
byte[] buffer = new byte[2048];
int readCount = 0;
try
{
while ((readCount = fsInput.Read(buffer, 0, 2048)) > 0)
{
cryptostream.Write(buffer, 0, readCount);
}
}
catch (Exception ex)
{
string error = "";
foreach (DictionaryEntry pair in ex.Data)
{
error += pair.Key + " = " + pair.Value + "\n";
Console.WriteLine(error);
}
LogWriter(error, true);
}
}
}
}
您應該考慮對所有實現IDisposable
對象使用using
語句。 這將確保它們被關閉並放置在using
塊的末尾:
private static void EncryptFile(string sInputFilename, string sOutputFilename,
string sKey)
{
using (var fsInput = new FileStream(sInputFilename, FileMode.Open,
FileAccess.Read))
using (var fsEncrypted = new FileStream(sOutputFilename, FileMode.Create,
FileAccess.Write))
using (var desCryptoProvider = new DESCryptoServiceProvider())
{
desCryptoProvider.Key = Encoding.ASCII.GetBytes(sKey);
desCryptoProvider.IV = Encoding.ASCII.GetBytes(sKey);
using (var encryptor = desCryptoProvider.CreateEncryptor())
using (var cryptoStream = new CryptoStream(fsEncrypted, encryptor,
CryptoStreamMode.Write))
{
try
{
var bytearrayinput = File.ReadAllBytes(sInputFilename);
fsInput.Read(bytearrayinput, 0, bytearrayinput.Length);
cryptoStream.Write(bytearrayinput, 0, bytearrayinput.Length);
}
catch (Exception ex)
{
var errors = new StringBuilder();
foreach (var pair in ex.Data)
{
errors.AppendLine(string.Format("{0} = {1}", pair.Key, pair.Value));
}
Console.WriteLine(errors.ToString());
LogWriter(errors.ToString(), true);
}
}
}
}
這不是一個確切的答案,但可能會有所幫助。 一種檢查文件是否已鎖定的簡單方法:
bool IsFileAvailable(string fileName)
{
FileStream stream = null;
try
{
FileInfo fileInfo = new FileInfo(fileName);
stream = fileInfo.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None);
}
catch (IOException)
{
// File is not present, or locked by another process
return false;
}
finally
{
if (stream != null)
stream.Close();
}
// File is present and not locked
return true;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.