如何在C#中覆盖转储文件中的特定字节

时间:2014-07-09 09:39:35

标签: c# encoding utf-8 binary mysqldump

我正在使用带有一些特殊字符的mysql转储(“Ä,ä,Ö,ö,Ü,ü,ß”)。我必须将此转储重新导入最新的mysql版本。由于编码,这会使特殊字符崩溃。转储不使用UTF-8编码。

在此转储中,还有一些二进制附件不应被覆盖。否则附件将被破坏。

我必须用UTF-8可读的字节覆盖每个特殊字符。

我目前正在尝试这种方式(这会将ANSIü改为UTF-8可读ü):

newByteArray[y] = 195;
if (bytesFromLine[i] == 252)
{
   newByteArray[y + 1] = 188;
}

newByteArray[y + 2] = bytesFromLine[y + 1];
  

252在Encoding.Default中显示'ü'。 195 188在Encoding.UTF8中显示'ü'。

现在我需要帮助在此转储文件中搜索此特定字符,并使用正确的字节覆盖此字节。我不能用'195 188'替换所有'252',因为附件会被破坏。

提前致谢。

放松

1 个答案:

答案 0 :(得分:1)

  

免责声明:这可能会破坏您的数据。处理此问题的最佳方法是从源数据库中获取正确的mysqldump。只有当您没有该选项并且遇到可能已损坏的转储文件时,才应使用此解决方案。

假设转储文件中的所有字符串都用引号(使用单引号')并且可以转义为\'

INSERT INTO `some_table` VALUES (123, 'this is a string', ...

不太清楚如何表示二进制数据。这可能需要更多检查,您需要检查转储文件,看看这些假设是否正确。

const char quote = '\'';
const char escape = '\\';

using (var dumpOut = new FileStream("dump_out.txt", FileMode.Create, FileAccess.Write))
using (var dumpIn = new FileStream("dump_in.txt", FileMode.Open, FileAccess.Read))
{
    bool inquotes = false;
    byte previousByte = 0;
    var stringBytes = new List<byte>();
    while (true)
    {
        int readByte = dumpIn.ReadByte();
        if (readByte == -1) break;

        var b = (byte) readByte;

        if (b == quote && previousByte != escape)
        {
            if (inquotes) // closing quote
            {
                var buffer = stringBytes.ToArray();
                stringBytes.Clear();

                byte[] converted = Encoding.Convert(Encoding.Default, Encoding.UTF8, buffer);

                dumpOut.Write(converted, 0, converted.Length);
                dumpOut.WriteByte(b);
            }
            else // opening quote
            {
                dumpOut.WriteByte(b);
            }

            inquotes = !inquotes;
            continue;
        }

        previousByte = b;

        if (inquotes)
            stringBytes.Add(b);
        else
            dumpOut.WriteByte(b);
    }
}