无法通过C#console app中的System.IO.File删除某些文件

时间:2015-03-20 16:36:05

标签: c# console-application system.io.file

我正在加密一些文本文件。它工作正常,文件被加密,但有时在尝试删除原始未加密文件时出现此错误:

  

System.IO.IOException:   该进程无法访问该文件' MyFile.TXT'因为它正被另一个进程使用。在System.IO .__ Error.WinIOError(Int32   System.IO.File.Delete(String。中的errorCode,String maybeFullPath)   path)在FileEncryption.Program.DeleteFile(String sInputFilename)中   FileEncryption \ Program.cs:第159行

这似乎发生在大型文本文件上。 (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);
    }
}

3 个答案:

答案 0 :(得分:1)

这可能是由于您在调用EncryptFile后未关闭文件造成的。在原始代码中,如果您在EncryptFile中遇到异常,则在调用Close之前发生异常时,流将保持打开状态。使用Using语句会使这更容易,但您也可以将Close放在finally块中,如果它们不为空,则关闭流。

以下是使用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);
            }
        }
    }
}

答案 1 :(得分:0)

您应该考虑对实现using的所有对象使用IDisposable语句。这将确保它们被关闭并放置在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);
            }
        }
    }
}

答案 2 :(得分:-1)

这不是答案,但可能有所帮助;检查文件是否被锁定的简单方法:

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;
}