无法通过C#控制台应用程序中的System.IO.File删除某些文件
我正在加密一些文本文件。如果文件已被加密,则工作正常,但有时我在尝试删除原始未加密文件时会出现以下错误: System.IO.IOException: 进程无法访问文件“MyFile.TXT”,因为另一个进程正在使用该文件。位于System.IO.\uu Error.WinIOError(Int32 System.IO.File.Delete(字符串)处的错误代码、字符串maybeFullPath) 路径)中的FileEncryption.Program.DeleteFile(字符串sInputFilename) FileEncryption\Program.cs:第159行 这似乎发生在大型文本文件上。(50MB+)但并非总是如此 知道我可能做错了什么吗? 处理txt文件文件夹的方法:无法通过C#控制台应用程序中的System.IO.File删除某些文件,c#,console-application,system.io.file,C#,Console Application,System.io.file,我正在加密一些文本文件。如果文件已被加密,则工作正常,但有时我在尝试删除原始未加密文件时会出现以下错误: System.IO.IOException: 进程无法访问文件“MyFile.TXT”,因为另一个进程正在使用该文件。位于System.IO.\uu Error.WinIOError(Int32 System.IO.File.Delete(字符串)处的错误代码、字符串maybeFullPath) 路径)中的FileEncryption.Program.DeleteFile(字符串sInput
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);
}
}
删除文件的方法
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
之前发生异常,则流将保持打开状态。使用Using
语句可以简化此操作,但您也可以将Close
放在finally
块中,如果流不为null,则关闭流
下面是一个使用和的示例:
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);
}
}
}
}
您应该考虑使用< <代码> > <代码> >所有实现“代码> IDISPOLITION/CODE >的对象。这将确保使用
块在结束时关闭和处置它们:
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;
}
要读取的数据量很大,但该文件已被另一个进程锁定。也就是说,你打开一个文本文件,然后尝试删除,当它打开时,它会抛出一个错误。是的,这是很多阅读。但是信息太多而不是不够。我觉得我在加密文件后正在“关闭”它。我以前在某个特定的AV产品中遇到过类似的文件访问问题。在这种情况下,我通过添加一些重试逻辑和睡眠来解决这个问题。您可以使用和IDispose来实现,然后实现所述逻辑。@Greg关于我应该使用的部分。在Eekhmmm之前,我也从未使用过iDispose,我尝试在try/catch中添加finally来关闭fsInput、fsEnctyped和cryptoStream。它将关闭,但删除程序无法访问已关闭的文件。您能给我一个如何调用BeginFileProcessing
的示例吗?我将自己尝试运行代码,看看是否可以发现任何东西。BeginFileProcessing只是在主方法中调用的。我运行了一些测试,终于找到了一些东西。似乎正如我预期的那样,代码会抛出异常(OutOfMemoryException
),而在EncryptFile
函数中,文件流不会关闭,然后删除会崩溃。我对您的原始代码和建议的代码运行了测试,建议的代码将正确删除文件,即使出现异常。请参阅我的编辑,这将解决您的问题。我很惊讶没有人注意到你把所有的字节读到一个缓冲区,然后在下面的一行再次读所有的字节。