如何从文件中读取二进制格式的字符串?

How to read a binary formatted string from a file?

我想以一种无法(轻松)读取的方式将字符串存储在文件中。所以我使用这样的 BinaryFormatter:

using (FileStream fs = File.Create(sfDialog.FileName, 2048, FileOptions.None))
{
    BinaryFormatter bf = new BinaryFormatter();
    bf.Serialize(fs, Encoding.Unicode.GetBytes(this.BodyText));
}

其中 this.BodyText 是要保存的字符串。

现在我正在努力从文件中读回它。我尝试 BinaryReader 没有成功,所以我想,我必须使用 BinaryFormatter。我尝试了 Deserialize 方法,但它 returns 是一个无法转换为字符串的对象。此外 Convert.ToBase64String 不能用于对象。

有谁知道如何解决我的问题?

使用此函数进行加密和解密。

    string passPhrase = "Pasword";        // can be any string
    string saltValue = "sALtValue";        // can be any string
    string hashAlgorithm = "SHA1";             // can be "MD5"
    int passwordIterations = 7;                  // can be any number
    string initVector = "~1B2c3D4e5F6g7H8"; // must be 16 bytes
    int keySize = 256;                // can be 192 or 128

    private string Encrypt(string data)
    {
        byte[] bytes = Encoding.ASCII.GetBytes(this.initVector);
        byte[] rgbSalt = Encoding.ASCII.GetBytes(this.saltValue);
        byte[] buffer = Encoding.UTF8.GetBytes(data);
        byte[] rgbKey = new PasswordDeriveBytes(this.passPhrase, rgbSalt, this.hashAlgorithm, this.passwordIterations).GetBytes(this.keySize / 8);
        RijndaelManaged managed = new RijndaelManaged();
        managed.Mode = CipherMode.CBC;
        ICryptoTransform transform = managed.CreateEncryptor(rgbKey, bytes);
        MemoryStream stream = new MemoryStream();
        CryptoStream stream2 = new CryptoStream(stream, transform, CryptoStreamMode.Write);
        stream2.Write(buffer, 0, buffer.Length);
        stream2.FlushFinalBlock();
        byte[] inArray = stream.ToArray();
        stream.Close();
        stream2.Close();
        return Convert.ToBase64String(inArray);
    }

    private string Decrypt(string data)
    {
        byte[] bytes = Encoding.ASCII.GetBytes(this.initVector);
        byte[] rgbSalt = Encoding.ASCII.GetBytes(this.saltValue);
        byte[] buffer = Convert.FromBase64String(data);
        byte[] rgbKey = new PasswordDeriveBytes(this.passPhrase, rgbSalt, this.hashAlgorithm, this.passwordIterations).GetBytes(this.keySize / 8);
        RijndaelManaged managed = new RijndaelManaged();
        managed.Mode = CipherMode.CBC;
        ICryptoTransform transform = managed.CreateDecryptor(rgbKey, bytes);
        MemoryStream stream = new MemoryStream(buffer);
        CryptoStream stream2 = new CryptoStream(stream, transform, CryptoStreamMode.Read);
        byte[] buffer5 = new byte[buffer.Length];
        int count = stream2.Read(buffer5, 0, buffer5.Length);
        stream.Close();
        stream2.Close();
        return Encoding.UTF8.GetString(buffer5, 0, count);
    }

我同意其他人的意见,你应该使用一些适当的加密而不是这个。

但要回答您的实际问题: 您正在序列化一个字节数组。这就是反序列化时得到的结果。

因此,反序列化后,转换为 byte[] 并将此字节数组转换为字符串:

var s = Encoding.Unicode.GetString((byte[])deserializedValue);

如果您希望字符串不容易被读取,您应该使用适当的加密。

例如,您可以使用 DPAPI,它将使用您的 windows 凭据作为加密的密钥。 (more details about the pros/cons of that concept here)

或者您可以 read Josh Galloway's article 探索 3 种不同的方法,其中第三种看起来很有希望,即使我自己没有尝试过,但最酷的部分是它不需要您的加密数据在 .config 文件中。)

还有,关于原来的问题,别忘了既然你打过电话

Encoding.Unicode.GetBytes(this.BodyText)

反序列化时,您需要调用 Encoding 服务从字节数组中获取 Unicode 字符串:

Encoding.Unicode.GetString(myByteArray);

试试这个:

using (FileStream fs = File.Create(sfDialog.FileName, 2048, FileOptions.None))
{
    BinaryFormatter deserializer = new BinaryFormatter();
    deserializedObject = System.Text.Encoding.Unicode.GetString((byte[])deserializer.Deserialize(memoryStream));
}