【问题标题】:Encrypting .txt File Erroring - Process Cannot Access File加密 .txt 文件错误 - 进程无法访问文件
【发布时间】:2017-09-01 10:01:08
【问题描述】:

我正在尝试加密在我的应用程序中创建的.txt 文件。

要创建此文件,我使用以下代码:

Dim fileExists As Boolean = File.Exists(directorypath & "dbpw.txt")
If File.Exists(directorypath & "dbpw.txt") = False Then
   Using sw As New StreamWriter(File.Open(directorypath & "dbpw.txt", FileMode.Create))
         IIf(fileExists, "", "")
         sw.Close()
   End Using
End If

然后,为了编写和加密文件,我使用以下代码,调用我从互联网上的示例中调整的子例程。

bytKey = CreateKey(txtCode.Text)
bytIV = CreateIV(txtCode.Text)

EncryptOrDecryptFile(directorypath & "dbpw.txt", directorypath & "dbpw.txt", bytKey, bytIV, CryptoAction.ActionEncrypt)

当代码到达最后一行时,调用EncryptOrDecrypt 子例程,抛出一个错误提示

进程无法访问文件“myDirectoryPath\dbpw.txt”,因为它正被另一个进程使用

我需要做什么才能发布文件?

我也尝试只使用File.CreateFile.Encrypt,但无论哪种方式都会引发相同的错误。

EncryptOrDecryptFile() 的代码

Public Sub EncryptOrDecryptFile(ByVal strInputFile As String, ByVal strOutputFile As String, ByVal bytKey() As Byte, ByVal bytIV() As Byte, ByVal Direction As CryptoAction)

    Try
        fsInput = New System.IO.FileStream(strInputFile, FileMode.Open, FileAccess.Read)
        fsOutput = New System.IO.FileStream(strOutputFile, FileMode.OpenOrCreate, FileAccess.Write)
        fsOutput.SetLength(0)
        ' Currently fails, file not being released for read/write once it's created.

        Dim bytBuffer(4096) As Byte
        Dim lngBytesProcessed As Long = 0
        Dim lngFileLength As Long = fsInput.Length
        Dim intBytesInCurrentBlock As Integer
        Dim csCryptoStream As CryptoStream

        Dim cspRijndael As New System.Security.Cryptography.RijndaelManaged

        Select Case Direction
            Case CryptoAction.ActionEncrypt
                csCryptoStream = New CryptoStream(fsOutput, _
                cspRijndael.CreateEncryptor(bytKey, bytIV), _
                CryptoStreamMode.Write)

            Case CryptoAction.ActionDecrypt
                csCryptoStream = New CryptoStream(fsOutput, _
                cspRijndael.CreateDecryptor(bytKey, bytIV), _
                CryptoStreamMode.Write)
        End Select

        While lngBytesProcessed < lngFileLength
            intBytesInCurrentBlock = fsInput.Read(bytBuffer, 0, 4096)

            csCryptoStream.Write(bytBuffer, 0, intBytesInCurrentBlock)

            lngBytesProcessed = lngBytesProcessed + _
                                    CLng(intBytesInCurrentBlock)
        End While

        csCryptoStream.Close()
        fsInput.Close()
        fsOutput.Close()

    Catch ex As Exception
        errorLog(ex)

    End Try
End Sub

【问题讨论】:

  • 调用sw.Close() 是多余的,因为您将它包装在Using/End Using 块中。至于您的问题,问题可能是基础流未关闭。而不是File.Open(),只需将文件名直接传递给StreamWriterUsing sw As New StreamWriter(directorypath &amp; "dbpw.txt")
  • @VisualVincent 我最初没有sw.Close(),我只是添加它以查看它是否解决了问题。我按照您的建议将代码更改为Using sw As New StreamWriter(directorypath &amp; "dbpw.txt", FileMode.Create),但仍然抛出相同的错误。
  • 与问题无关,但FileMode.Create 在该上下文中无效。只需删除它并保留文件名。如果文件不存在,StreamWriter 将创建该文件,如果存在则覆盖它。 -- 你是否在代码的其他地方使用/引用了这个文件?
  • 另外,我可以看看EncryptOrDecryptFile() 方法吗?可能是您尝试同时读取和写入同一个文件。
  • 我怀疑...您正在为同一个文件打开 fsInputfsOutput。一旦你打开了fsInput,它就会限制对文件的访问,这就是为什么你不能用写权限打开fsOutput。您必须为输出文件指定一个不同的名称保留一个开放的加密流,每次将数据写入文件时都会使用它。

标签: vb.net encryption file-access


【解决方案1】:

连同您传递的参数,在您的EncryptOrDecryptFile() 方法中,您试图将两个流(fsInputfsOutput)打开到同一个文件。一旦你打开了fsInput,它就拥有了对该文件的独占访问权限,使得fsOutput 无法打开它进行写入。

您唯一的选择是:

  • 重命名输入文件或输出文件,以便两个流打开两个不同的文件,或者:

  • 保持对文件打开“全局”加密流,每次您想向其写入数据时都会使用该加密流。

注意:以后有人可能会建议你用FileShare.Write打开fsInput,以便让其他进程打开文件进行写入,从而也允许fsOutput流也写给它。 - 不要那样做!

在您读取文件时允许其他进程写入文件可能会导致问题,即使它是您的fsOutput 流。这是因为您永远无法知道fsOutput 将写入多少数据。如果加密数据比原始数据长怎么办?这将导致它覆盖 fsInput 接下来要读取的内容,从而损坏文件。

【讨论】:

  • 嗨文森特,虽然这确实解决了我的问题,但它引发了另一个问题 - 我需要读取加密文件,然后将数据传递到 EncryptOrDecryptFile()。如何读取数据,将其存储到变量中,然后在 bytKeybytIV 中获取正确的值以用作参数?
  • @Harambe :读取数据是由EncryptOrDecryptFile() 完成的,这还不够吗?为什么需要将加密数据存储在变量中? -- 至于密钥和 IV,它们必须由您提供(通过硬编码或像现在这样在TextBox 中输入)。无法从加密数据中获取它们。
  • @Harambe :如果您想将加密数据读入一个变量,您可以通过File.ReadAllBytes() 获取它,但您必须修改EncryptOrDecryptFile() 以将字节数组作为输入,然后跳过fsInput 流。
  • 我需要将数据存储在一个变量中,因为加密的数据是用户设置的数据库密码。即在运行设置时,管理员必须选择密码,然后加密后存储在文件中。我需要解密密码并将其存储在连接字符串的变量中。类似EncryptOrDecryptFile(File.ReadAllBytes(directorypath &amp; "dbpw.txt"), directorypath &amp; "dbpw-temp.txt"...) 的东西会这样做吗?那我可以把密码存到临时文件里,读取,然后删除?
猜你喜欢
  • 1970-01-01
  • 2013-09-29
  • 1970-01-01
  • 1970-01-01
  • 2012-01-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多