我一直在玩VC#Express 2010中的加密和解密文件。
我见过的所有教程和文档都需要两个FileStream
来加密文件 - 一个用于读取未加密的版本,另一个用于加密。当我实际编写代码时,它不断抛出错误告诉我它无法打开文件,因为它是由输出文件流中的另一个进程打开的。
我假设那是因为文件是由输入文件流打开的。这意味着我必须指定不同的文件名?因此,即使操作成功,我现在将在目录中有原始的未加密文件和单独的加密版本?这不是没有意义吗?或者我在这里做错了什么?我的代码与此类似......
public string filename = "test.xml";
using (FileStream input = new FileStream(filename, FileMode.Open, FileAccess.Read))
using (FileStream output = new FileStram(filename, FileMode.Open, FileAccess.Write))
using (....all the crypto stream and transform stuff...)
{
...do the encryption....
}
答案 0 :(得分:3)
你是对的,但这并没有打败这一点。 (流)加密API旨在从Src加密到Dst。认为通过网络发送/接收时加密输出等。这使它们变得简单,就像它们应该的那样。
通过对Src和Dst使用相同的文件,您会使问题复杂化。这并非完全不可能,但像复制文件本身需要一些额外的关注。
一般来说,加密会增加文件大小。因此,对文件进行加密是不安全的。解密可能是,但我不会冒险。
您需要的是Temp文件和完成后的重命名操作。
答案 1 :(得分:1)
在您的示例中,您无法在同一文件上为输入和输出创建单独的文件流,但您可以创建一个可读写的句柄。 FileAccess枚举具有flags属性,因此您只需说var handle = new FileStream(filename, FileAccess.Read | FileAccess.Write);
明显的缺点是,如果加密未成功完成,您将丢失数据。
我建议为输出设置一个单独的文件,但至少如果您的程序意外中断,您将不会丢失数据。如果加密成功完成,则删除原始文件并使用原始文件名重命名加密文件。
答案 2 :(得分:0)
使用File.ReadAllBytes
。那些发布到加密器的字节必须有效。
答案 3 :(得分:0)
还有另一个参数,您可以指定是否允许其他进程读取或写入文件。
openFile
是一个表示文件名的字符串。
using (FileStream fileIn = new FileStream(openFile, FileMode.Open, FileAccess.Read, FileShare.Write))
using (FileStream fileOut = new FileStream(openFile, FileMode.Open, FileAccess.Write, FileShare.Open))
这样,您就可以读取和写入同一个文件。
while (myfileStream.Position < fileLength)
{
fileIn.Read(buffer, 0, 51200);
buffer = encrypt(buffer);
fileOut.Write(buffer, 0, 51200);
}
虽然这很简单,但您不必写入临时文件或必须移动/重命名等,这可能非常危险,因为如果加密由于某种原因突然中断,您将丢失数据!
此外,encrypt
函数是我实现的。可以使用AesCryptoServiceProvider
以及CryptoStream
:)