美好的一天。可能有些人知道在Delphi和C#中为下一行获得相同结果的真实方法。
var
aStrStream: TStringStream;
aStr: string;
begin
aStr := 'Test';
aStrStream := TStringStream.Create('');
aStrStream.Write(aStr, SizeOf(Length(aStr)));
aStrStream.Position := 0;
aStr := DIMime.MimeEncodeStringNoCRLF(aStrStream.DataString);
aStrStream.Free;
//Got yJFVAA==
end;
和
Encoding dest = Encoding.ASCII;
Encoding src = Encoding.Unicode;
byte[] srcBytes = src.GetBytes("Test");
byte[] destBytes = Encoding.Convert(src, dest, srcBytes);
Console.WriteLine(Convert.ToBase64String(destBytes));
//Got VGVzdA==
更新1:
感谢大家的详细解答。但情况接下来。我有一个程序的src代码,它为soksifikator生成一个based64字符串。我尝试将其转换为C#。这个程序有很多这样的行:
aLen := Length(aObj.RuleProxyName); //aObj.RuleProxyName - string
aStrStream.Write(aLen, SizeOf(aLen));
if aLen > 0 then
aStrStream.Write(aObj.RuleProxyName[1], aLen);
这就是为什么我不能使用aStrStream.WriteString
的原因。
答案 0 :(得分:2)
<强>更新强>
我认为C#代码是目标的原因是Delphi代码显然是错误的。但正如我所讨论的,C#代码也很奇怪。现在,似乎原始问题中的两个代码摘录都是假的。尝试让C#与您发布的Delphi代码相匹配是没有意义的,因为Delphi代码都是错误的。
你真正需要做的是弄清楚真正的Delphi代码(而不是模拟代码)正在做什么。
让我们来看看:
aLen := Length(aObj.RuleProxyName); //aObj.RuleProxyName - string
aStrStream.Write(aLen, SizeOf(aLen));
if aLen > 0 then
aStrStream.Write(aObj.RuleProxyName[1], aLen);
将一个4字节的小端整数字符串长度写入流,然后用ANSI编码的文本跟随它。 Delphi代码使用TStringStream
,但这是滥用该类。该类用于存储文本,但显然它包含二进制和ANSI编码文本的混合。这段代码应该使用内存流或类似代码。
在C#中,上面的摘录将翻译为:
string str = "Test";
MemoryStream stream = new MemoryStream();
BinaryWriter writer = new BinaryWriter(stream);
writer.Write(str.Length);
writer.Write(Encoding.Default.GetBytes(str));
下一个问题是DIMime.MimeEncodeStringNoCRLF
的作用。我们无法知道,因为它不是标准类。正如我在原始答案中所说,你应该警惕任何尝试base64编码文本而不是二进制输入的代码。
所以,为了取得进展,你会想要了解DIMime.MimeEncodeStringNoCRLF
实际上做了些什么。鉴于这似乎是一个Unicode之前的Delphi,它几乎肯定会将输入字符串视为字节数组并编码,在这种情况下,您可以使用Convert.ToBase64String(stream.ToArray())
完成上述摘录。
原始回答
Delphi代码有点混乱。例如,SizeOf(Length(aStr))
毫无意义。但无论如何,您不应该使用Write
而应使用WriteString
。
但即便如此,你在文本和二进制之间变得非常混乱。您将所有问题都转换为ASCII,然后执行aStrStream.DataString
只需将其转换回UTF-16即可。然后将其提供给MimeEncodeStringNoCRLF
。你也可以写一下MimeEncodeStringNoCRLF('Test')
,我认为这会以同样的方式失败。
我重新开始编写完全与C#版本相同的代码。我会避免TStringStream
并利用Delphi的TEncoding
类设计为尽可能接近.net Encoding
类的事实。所以你真的可以对这段代码进行字面翻译。
{$APPTYPE CONSOLE}
uses
System.SysUtils,
System.NetEncoding;
procedure Main;
var
dest, src: TEncoding;
srcBytes, destBytes: TBytes;
begin
dest := TEncoding.ASCII;
src := TEncoding.Unicode;
srcBytes := src.GetBytes('Test');
destBytes := TEncoding.Convert(src, dest, srcBytes);
Writeln(TNetEncoding.Base64.EncodeBytesToString(destBytes));
end;
begin
Main;
Readln;
end.
<强>输出强>
VGVzdA==
如果您没有可用的NetEncoding
单元(它是在XE7中添加的),您可以使用任何其他字节数组到您手头的base64编码器。
我不得不说我对你使用DIMime.MimeEncodeStringNoCRLF
持怀疑态度,因为它将文本转换为base64。这将需要将文本隐式编码为二进制表示。而隐式编码至关重要,不应以这种方式隐藏起来。这就是我的意思,说你在文本和二进制之间混淆了。请记住,base64将二进制编码为文本。并将文本解码为二进制。但MimeEncodeStringNoCRLF
将文本转换为文本,这意味着隐式文本编码。
我个人的规则是你绝不应该使用隐式文本编码进行这样的转换。如果从文本开始,首先使用明确选择的编码转换为二进制。然后使用base64编码该二进制文件。
最后,我想知道为什么代码会从文本转换为ASCII然后转换为UTF-16。这似乎是一个相当奇怪的决定。 C#代码真的在做你需要做的事吗?