以下Delphi例程最初来自很久以前的CompuServe发布,用于加密我们数据库中的各种信息。下面是Delphi 2007和(感谢一些有关Unicode差异的SO帮助)Delphi XE版本。
我们一直在尝试将其转换为C#,并且已经接近了,但我们在某处遗漏了某些东西。不幸的是,我们的Delphi家伙(我)不知道C#,而C#家伙是Delphi的新手。 C#没有(似乎)具有AnsiString的概念,因此解决方案可能涉及字节或字符数组?
我们非常感谢将此转换为C#的任何帮助。
Delphi 2007版(ASCII)
function EncodeDecode(Str: string): string;
const
Hash: string = '^%12hDVjED1~~#29afdmSD`6ZvUY@hbkDBC3fn7Y7euF|R7934093*7a-|- Q`';
var
I: Integer;
begin
for I := 1 to Length (Str) do
Str[I] := chr (ord (Str[I]) xor not (ord (Hash[I mod Length (Hash) + 1])));
Result := Str;
end;
Delphi XE版本(Unicode)
function TfrmMain.EncodeDecode(Str: AnsiString): AnsiString;
const
Hash: string = '^%12hDVjED1~~#29afdmSD`6ZvUY@hbkDBC3fn7Y7euF|R7934093*7a-|- Q`';
var
I: Integer;
begin
Result := Str;
for I := 1 to Length (Result) do
Result[I] := AnsiChar (ord (Result[I]) xor not (Ord (Hash[I mod Length (Hash) + 1])));
end;
答案 0 :(得分:11)
我也不知道C#,所以这可能是严重的非惯用语。
static string EncodeDecode(string str)
{
byte[] hash = new byte[63] { 94, 37, 49, 50, 104, 68, 86, 106, 69, 68, 49, 126,
126, 35, 50, 57, 97, 102, 100, 109, 83, 68, 96, 54, 90, 118, 85, 89, 64,
104, 98, 107, 68, 66, 67, 51, 102, 110, 55, 89, 55, 101, 117, 70, 124, 82,
55, 57, 51, 52, 48, 57, 51, 42, 55, 97, 45, 124, 45, 32, 32, 81, 96 };
Encoding ANSI = Encoding.GetEncoding(1252);
byte[] input = ANSI.GetBytes(str);
byte[] output = new byte[input.Length];
for (int i = 0; i < input.Length; i++)
output[i] = (byte)(input[i] ^ ~hash[(i + 1) % hash.Length]);
return ANSI.GetString(output);
}
我假设您的ANSI字符串是使用Windows 1252编码的,但您碰巧使用不同的代码页对旧数据进行了编码,显而易见,如何更改它。
由于C#没有相当于Delphi的8位字符串类型,我个人非常想使用byte[]
而不是string
。
就这样做了:
static byte[] EncodeDecode(byte[] input)
{
byte[] hash = new byte[63] { 94, 37, 49, 50, 104, 68, 86, 106, 69, 68, 49, 126,
126, 35, 50, 57, 97, 102, 100, 109, 83, 68, 96, 54, 90, 118, 85, 89, 64,
104, 98, 107, 68, 66, 67, 51, 102, 110, 55, 89, 55, 101, 117, 70, 124, 82,
55, 57, 51, 52, 48, 57, 51, 42, 55, 97, 45, 124, 45, 32, 32, 81, 96 };
byte[] output = new byte[input.Length];
for (int i = 0; i < input.Length; i++)
output[i] = (byte)(input[i] ^ ~hash[(i + 1) % hash.Length]);
return output;
}
@Groo提出了一个很好的观点,即哈希可以更干净地初始化,列出这个:
byte[] hash = ANSI.GetBytes(@"^%12hDVjED1~~#29afdmSD`6ZvUY@hbkDBC3fn7Y7euF|R7934093*7a-|- Q`");
答案 1 :(得分:2)
String
是以UTF-16编码的字符序列,如this article by Jon Skeet中所述。实际上你根本不应该关注你,直到你决定将它序列化为二进制(即将其转换为字节数组)。在这种情况下,System.Text
命名空间中有一个名为Encoding
的类,它支持将String
编码为您想要的任何编码。
Delphi中的AnsiString
基本上是一个ASCII字符串(不,它实际上是一个ANSI字符串,就像名字所说的那样),其中每个字符都保证恰好有8位。这是一种相对“简单”的编码编码,因为它具有固定的大小,被广泛接受并与遗留系统兼容(但它不允许编码超过255个字符)。
换句话说,您的两个版本都处理相同类型的编码,但unicode版本现在明确将旧字符串定义为AnsiString
s。这意味着后一版本实际上不支持Unicode字符串,但需要使用新的Delphi版本更改类型。
@David在写这篇冗长的废话时所做的基本上就是我要编写的内容,除了我会使用Encoding.ASCII
编码代替( [编辑]并且会惨败由于ASCII仅使用较低的7位来编码字符,如下面的David所提到的)。 Windows-1252是最常被称为“ANSI”的编码(但是,如果你查看那篇Wiki文章,你会发现它,根据微软的说法,术语ANSI用于表示Windows代码页是一个历史参考,但现在仍然是一个在Windows社区中持续存在的误称。