我正在使用带有一些特殊字符的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',因为附件会被破坏。
提前致谢。
放松
答案 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);
}
}