如何在delphi中实现对文件进行base64编码
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在delphi中实现对文件进行base64编码相关的知识,希望对你有一定的参考价值。
delphi 中有个EncdDecd类,这个是delphi自带的base64编码类,里面提供了编码和解码函数分别是:function EncodeString(const Input: string): string; //编码
function DecodeString(const Input: string): string; //解码 参考技术A Base64 = Class(TObject)
private
FOStream: TStream;
FIStream: TStream;
Public
输入流
Property IStream : TStream Read FIStream Write FIStream;
输出流
Property OStream : TStream Read FOStream Write FOStream;
编码
Function Encode : Boolean;
解码
Function Decode : Boolean;
End;
implementation
const
SBase64 : string = '23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz~#%&*+-';
UnBase64: array[0..255] of byte =
(128,128,128,128,128,128,128,128, 128,128,128,128,128,128,128,128, //0-15
128,128,128,128,128,128,128,128, 128,128,128,128,128,128,128,128, //16-31
128,128,128, 58,128, 59, 60,128, 128,128, 61, 62,128, 63,128,128, //32-47
128,128, 0, 1, 2, 3, 4, 5, 6, 7,128,128,128,128,128,128, //48-63
128, 8, 9, 10, 11, 12, 13, 14, 15,128, 16, 17, 18, 19, 20,128, //64-79
21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,128,128,128,128,128, //80-95
128, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,128, 43, 44, 45, //96-111
46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,128,128,128, 57,128, //112-127
128,128,128,128,128,128,128,128, 128,128,128,128,128,128,128,128, //128-143
128,128,128,128,128,128,128,128, 128,128,128,128,128,128,128,128, //128-143
128,128,128,128,128,128,128,128, 128,128,128,128,128,128,128,128, //144-159
128,128,128,128,128,128,128,128, 128,128,128,128,128,128,128,128, //160-175
128,128,128,128,128,128,128,128, 128,128,128,128,128,128,128,128, //176-191
128,128,128,128,128,128,128,128, 128,128,128,128,128,128,128,128, //192-207
128,128,128,128,128,128,128,128, 128,128,128,128,128,128,128,128, //208-223
128,128,128,128,128,128,128,128, 128,128,128,128,128,128,128,128, //224-239
128,128,128,128,128,128,128,128, 128,128,128,128,128,128,128,128); //240-255
TBase64
function TBase64.Decode: Boolean;
var
j, k: integer;
b: byte;
W, Tmp : Byte; //用于阅读流的临时变量
begin
Result := FALSE;
If (FIStream <> Nil) And (FOStream <> Nil) Then
Begin
初始化
IStream.Position := 0;
OStream.Position := 0;
b := 0;
j := 0;
K := 2;
while (IStream.Position < IStream.Size) And (IStream.Read(Tmp, 1) = 1) And (Char(Tmp) <> '.') Do
Begin
if j = 0 then
begin
b := UnBase64[Tmp];
k := 2;
end
else begin
W := UnBase64[Tmp] or ((b shl k) and $C0);
OStream.Write(W, 1);
inc(k,2);
end;
inc(j);
j := j and 3;
end;
End;
end;
function TBase64.Encode: Boolean;
var
SBuffer : Array [1..4] Of Byte;
j, k: integer;
b: byte;
Tmp : Byte; ### 用于阅读流的临时变量 ###
begin
Result := FALSE;
If (FIStream <> Nil) And (FOStream <> Nil) Then
Begin
初始化
IStream.Position := 0;
OStream.Position := 0;
b := 0;j := 2; k := 2;
while IStream.Position < IStream.Size do
begin
If IStream.Read(Tmp, 1) = 1 Then
Begin
b := b or ((Tmp and $C0) shr k);
inc(k, 2);
SBuffer[j] := Byte(SBase64[(Tmp And $3F) + 1]);
inc(j);
if j > 4 then
begin
SBuffer[1] := Byte(SBase64[b + 1]);
b := 0;
j := 2;
k := 2;
OStream.Write(SBuffer, 4);
End;
End;
End;
平整数据到 SBuffer
if j <> 2 then
begin
SBuffer[j] := Ord('.');
SBuffer[1] := Byte(SBase64[b + 1]);
OStream.Write(SBuffer, j);
end
else Begin
SBuffer[1] := Ord('.');
OStream.Write(SBuffer, 1);
end;
Result := TRUE;
end;
end;
//--------------------------------------------------------------
翻译成C++的:
class TBase64 : public TObject
private:
TSream FOStream;
TStream FIStream;
public:
//输入流
__property TStream IStream = read = FIStream , write = FIStream ;
//输出流
__property TStream OStream = read = FOStream , write = FOStream ;
//编码
bool Encode();
//解码
bool Decode();
;
const char * SBase64 = "23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz~#%&*+-";
const unsigned char UnBase64[256] =
128,128,128,128,128,128,128,128, 128,128,128,128,128,128,128,128, //0-15
128,128,128,128,128,128,128,128, 128,128,128,128,128,128,128,128, //16-31
128,128,128, 58,128, 59, 60,128, 128,128, 61, 62,128, 63,128,128, //32-47
128,128, 0, 1, 2, 3, 4, 5, 6, 7,128,128,128,128,128,128, //48-63
128, 8, 9, 10, 11, 12, 13, 14, 15,128, 16, 17, 18, 19, 20,128, //64-79
21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,128,128,128,128,128, //80-95
128, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,128, 43, 44, 45, //96-111
46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,128,128,128, 57,128, //112-127
128,128,128,128,128,128,128,128, 128,128,128,128,128,128,128,128, //128-143
128,128,128,128,128,128,128,128, 128,128,128,128,128,128,128,128, //128-143
128,128,128,128,128,128,128,128, 128,128,128,128,128,128,128,128, //144-159
128,128,128,128,128,128,128,128, 128,128,128,128,128,128,128,128, //160-175
128,128,128,128,128,128,128,128, 128,128,128,128,128,128,128,128, //176-191
128,128,128,128,128,128,128,128, 128,128,128,128,128,128,128,128, //192-207
128,128,128,128,128,128,128,128, 128,128,128,128,128,128,128,128, //208-223
128,128,128,128,128,128,128,128, 128,128,128,128,128,128,128,128, //224-239
128,128,128,128,128,128,128,128, 128,128,128,128,128,128,128,128; //240-255
如何在 C# 中实现 Base64 URL 安全编码?
【中文标题】如何在 C# 中实现 Base64 URL 安全编码?【英文标题】:How to achieve Base64 URL safe encoding in C#? 【发布时间】:2014-12-08 19:52:09 【问题描述】:我想在 C# 中实现 Base64 URL 安全编码。在 Java 中,我们有一个通用的 Codec
库,它为我提供了一个 URL 安全编码字符串。如何使用 C# 实现相同的目标?
byte[] toEncodeAsBytes = System.Text.ASCIIEncoding.ASCII.GetBytes("StringToEncode");
string returnValue = System.Convert.ToBase64String(toEncodeAsBytes);
上面的代码将其转换为 Base64,但它填充了==
。有没有办法实现 URL 安全编码?
【问题讨论】:
你不能在BASE64
中的字符串上使用Url.Encode
吗?
c#中哪个命名空间Url类存在?
看一下:msdn.microsoft.com/en-us/library/…你需要引用System.Web
组件。
它正在将 = 转换为 %3D。我不想要那个。
那么url safe
是什么意思? %3D
是网址安全的。
【参考方案1】:
在 url 中使用 简单地交换字母 是很常见的,因此不需要 % 编码; 65 个字符中只有 3 个有问题 - +
、/
和 =
。最常见的替换是-
代替+
和_
代替/
。至于填充:删除它(=
);您可以推断所需的填充量。在另一端:只需反转过程:
string returnValue = System.Convert.ToBase64String(toEncodeAsBytes)
.TrimEnd(padding).Replace('+', '-').Replace('/', '_');
与:
static readonly char[] padding = '=' ;
并反转:
string incoming = returnValue
.Replace('_', '/').Replace('-', '+');
switch(returnValue.Length % 4)
case 2: incoming += "=="; break;
case 3: incoming += "="; break;
byte[] bytes = Convert.FromBase64String(incoming);
string originalText = Encoding.ASCII.GetString(bytes);
然而,有趣的问题是:这与“通用编解码器库”使用的方法相同吗?首先要进行测试肯定是合理的——这是一种非常常见的方法。
【讨论】:
在通用编解码器中,他们使用 [0-9a-zA-Z_-] 字符作为 url 安全模式。 这在 wiki page for Base64 的 URL applications 下也有提及。 en.wikipedia.org/wiki/Base64 你也有这个功能 '***.com/questions/1886686/…' 为你做所有的辛苦工作。 为什么我们不需要:案例1:传入+=“===”;休息; ? @alexdafranca 因为它永远不会有 1 的长度 mod 4。3x8 位变成 4x6 位(每 6 位是所选字母表中 64 个字符之一),0x8 位被编码为 0x6 位没有填充,1x8 位被编码为带有==
填充的 2x6 位,2x8 被编码为带有=
填充的 3x6,3x8 被编码为没有填充的 4x6,然后它被对齐以便重复。没有任何东西被编码为 1x6 位,因此您永远不需要 ===
填充。【参考方案2】:
您可以使用命名空间 Microsoft.IdentityModel.Tokens
中的类 Base64UrlEncoder
。
const string StringToEncode = "He=llo+Wo/rld";
var encodedStr = Base64UrlEncoder.Encode(StringToEncode);
var decodedStr = Base64UrlEncoder.Decode(encodedStr);
if (decodedStr == StringToEncode)
Console.WriteLine("It works!");
else
Console.WriteLine("Dangit!");
【讨论】:
这比公认的答案要干净得多。有什么缺点吗? 请注意:Microsoft.IdentityModel.Tokens 是一个必须下载的 NuGet 包。 我假设这不是跨平台的。是这样吗?【参考方案3】:如果您使用的是 ASP.NET Core,另一种选择是使用 Microsoft.AspNetCore.WebUtilities.WebEncoders.Base64UrlEncode
。
如果您未使用 ASP.NET Core,the WebEncoders
source 可在 Apache 2.0 License 下使用。
【讨论】:
【参考方案4】:根据此处的答案以及一些性能改进,我们发布了一个非常易于使用的url-safe base64 implementation to NuGet,其源代码为available on GitHub(MIT 许可)。
使用很简单
var bytes = Encoding.UTF8.GetBytes("Foo");
var encoded = UrlBase64.Encode(bytes);
var decoded = UrlBase64.Decode(encoded);
【讨论】:
非常感谢。出于兴趣,您为什么选择"string".Replace
来代替 encode
方法,但使用手动替换 decode
的循环?
另一个返回类型 = 字符串的类:github.com/vndevpro/architecture-common/blob/master/…【参考方案5】:
要根据 RFC4648 获得 URL 安全的类似 base64 的编码,但不是“base64url”,请使用 System.Web.HttpServerUtility.UrlTokenEncode(bytes)
进行编码,并且
System.Web.HttpServerUtility.UrlTokenDecode(bytes)
解码。
【讨论】:
这不提供符合 RFC4648 标准的 URL 安全 Base64 编码。另见this Q&A。 谨慎使用。【参考方案6】:最简单的解决方案: (没有填充)
private static string Base64UrlEncode(string input)
var inputBytes = System.Text.Encoding.UTF8.GetBytes(input);
// Special "url-safe" base64 encode.
return Convert.ToBase64String(inputBytes)
.Replace('+', '-') // replace URL unsafe characters with safe ones
.Replace('/', '_') // replace URL unsafe characters with safe ones
.Replace("=", ""); // no padding
归功于:Tholle
【讨论】:
【参考方案7】: public string Decode(string str)
byte[] decbuff = Convert.FromBase64String(str.Replace(",", "=").Replace("-", "+").Replace("/", "_"));
return System.Text.Encoding.UTF8.GetString(decbuff);
public string Encode(string input)
byte[] encbuff = Encoding.UTF8.GetBytes(input ?? "");
return Convert.ToBase64String(encbuff).Replace("=", ",").Replace("+", "-").Replace("_", "/");
这是与 JavaScript 保持一致的方法!
【讨论】:
【参考方案8】:这是另一种解码 url-safe base64 的方法,它与 Marc 以相同的方式编码。我只是不明白为什么4-length%4
有效(确实如此)。
如下,只有origin的位长是6和8的公倍数,base64不加“=”到结果。
1 2 3 4 5 6 7 8|1 2 3 4 5 6 7 8|1 2 3 4 5 6 7 8
1 2 3 4 5 6|1 2 3 4 5 6|1 2 3 4 5 6|1 2 3 4 5 6
"==" "="
所以我们可以反过来做,如果结果的位长不能被8整除,它已经被追加了:
base64String = base64String.Replace("-", "+").Replace("_", "/");
var base64 = Encoding.ASCII.GetBytes(base64String);
var padding = base64.Length * 3 % 4;//(base64.Length*6 % 8)/2
if (padding != 0)
base64String = base64String.PadRight(base64String.Length + padding, '=');
return Convert.FromBase64String(base64String);
【讨论】:
【参考方案9】:在 UWP 中使用 Microsoft 加密引擎。
uint length = 32;
IBuffer buffer = CryptographicBuffer.GenerateRandom(length);
string base64Str = CryptographicBuffer.EncodeToBase64String(buffer)
// ensure url safe
.TrimEnd('=').Replace('+', '-').Replace('/', '_');
return base64Str;
【讨论】:
【参考方案10】:Karanvir Kang 的回答很好,我投了赞成票。但是,它确实在字符串的末尾留下了一个奇数字符(表示删除的填充字符的数量)。这是我的解决方案。
var bytesToEncode = System.Text.Encoding.UTF8.GetBytes("StringToEncode");
var bytesEncodedPadded = HttpServerUtility.UrlTokenEncode(bytesToEncode);
var objectIdBase64 = bytesEncodedPadded.Substring(0, bytesEncodedPadded.Length - 1);
【讨论】:
以上是关于如何在delphi中实现对文件进行base64编码的主要内容,如果未能解决你的问题,请参考以下文章
delphi 请问如何在SQL语句中实现对 Binary 类型的位运算?