【问题标题】:How to read a binary formatted string from a file?如何从文件中读取二进制格式的字符串?
【发布时间】:2015-10-05 12:36:21
【问题描述】:

我想以某种方式将字符串存储在文件中,使其无法(轻松)读取。所以我使用这样的 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 方法,但它返回一个不能转换为字符串的对象。 Convert.ToBase64String 也不能用于对象。

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

【问题讨论】:

  • 如果您希望字符串不易阅读,您应该考虑适当的加密。
  • 我建议你将你的字符串转换成 byte[] 并异或它的元素有一些价值。
  • 如果你不想让它容易阅读,为什么不加密呢?
  • 您需要在保存文件中包含字符串的长度或结束字符。您节省了 2048 个字节,但是当您读取字符串时,您的字符串可能只有 54 个字符,因此您不知道字符串的结尾在哪里。

标签: c# serialization binaryformatter


【解决方案1】:

我同意其他人的观点,你应该使用一些适当的加密来代替这个。

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

所以,反序列化后,强制转换为byte[],并将这个字节数组转换为字符串:

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

【讨论】:

  • 接受的答案,因为它实际上完美地回答了我的问题。当然,所有使用解密的建议都相当可观,并且可能比使用二进制格式更优雅,但由于数据并不是真正的秘密——实际上我只是想隐藏它是纯 HTML 的事实——我会选择这个。
【解决方案2】:

使用此功能进行加密和解密。

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

【讨论】:

    【解决方案3】:

    如果您希望字符串不易阅读,则应使用适当的加密。

    例如,您可以使用 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);
    

    【讨论】:

      【解决方案4】:

      试试这个:

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

      【讨论】:

        猜你喜欢
        • 2020-10-30
        • 2014-06-18
        • 2012-09-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多