{"id":476,"date":"2016-09-11T01:55:48","date_gmt":"2016-09-10T23:55:48","guid":{"rendered":"http:\/\/blog.kassebaum.eu\/?p=476"},"modified":"2016-09-12T11:46:39","modified_gmt":"2016-09-12T09:46:39","slug":"encodestring","status":"publish","type":"post","link":"https:\/\/www.kassebaum.eu\/blog\/2016\/09\/11\/encodestring\/","title":{"rendered":"EncodeString"},"content":{"rendered":"<p>This week I had to migrate an application from Delphi XE3 to Delphi Berlin and this application uses a <a href=\"https:\/\/en.wikipedia.org\/wiki\/Base64\" target=\"_blank\">Base64 encoding<\/a>.<\/p>\n<p>Normally Base64 encoding is not difficult stuff and Delphi XE3 simply offers the function EncodeString in the unit Soap.EncdDecd.<\/p>\n<p>Since Delphi Berlin has the same function I thought that I didn&#8217;t have to change a single line of code. But the first thing I realized is that the function is nearly deprecated. This means that it already has a deprecated comment: \/\/ deprecated &#8216;Use TNetEncoding.Base64.Encode&#8217;.<\/p>\n<p>Such a comment means that the function will become deprecated with one of the next Delphi releases.<\/p>\n<p>A short look at the implementation shows the reason:<\/p>\n<pre class=\"\">function EncodeString(const Input: string): string;\r\nbegin\r\n\u00a0 Result := TNetEncoding.Base64.Encode(Input);\r\nend;<\/pre>\n<p class=\"\">I should call TNetEncoding.Base64.Encode directly instead of using the old function EncodeString.<\/p>\n<p class=\"\">But then I realized that the two Delphi versions show different results.<\/p>\n<p class=\"\">Let&#8217;s have a look at a small example with some German umlauts:<\/p>\n<pre class=\"\">procedure TForm1.Button1Click(Sender: TObject);\r\nbegin\r\n\u00a0 ShowMessage(EncodeString('\u00c4\u00e4\u00d6\u00f6\u00dc\u00fc\u00df'));\r\nend;<\/pre>\n<p>Delphi XE3 shows &#8216;xOTW9tz83w==&#8217; whereas Delphi Berlin shows &#8216;w4TDpMOWw7bDnMO8w58=&#8217;.<\/p>\n<p>So bad luck, I had to have a deeper look at the code. Let&#8217;s start with Delphi XE3:<\/p>\n<pre class=\"\">function EncodeString(const Input: string): string;\r\nvar\r\n\u00a0 InStr, OutStr: TStringStream;\r\nbegin\r\n\u00a0 InStr := TStringStream.Create(Input);\r\n\u00a0 try\r\n\u00a0\u00a0\u00a0 OutStr := TStringStream.Create('');\r\n\u00a0\u00a0\u00a0 try\r\n\u00a0\u00a0\u00a0\u00a0\u00a0 EncodeStream(InStr, OutStr);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0 Result := OutStr.DataString;\r\n\u00a0\u00a0\u00a0 finally\r\n\u00a0\u00a0\u00a0\u00a0\u00a0 OutStr.Free;\r\n\u00a0\u00a0\u00a0 end;\r\n\u00a0 finally\r\n\u00a0\u00a0\u00a0 InStr.Free;\r\n\u00a0 end;\r\nend;\r\n ...\r\n constructor TStringStream.Create(const AString: string);\r\n begin\r\n \u00a0 Create(AString, TEncoding.Default, False);\r\n end;<\/pre>\n<p>This means that the string is first converted into bytes with the help of the default encoding which is under Windows an ANSI encoding. After that the bytes are encoded.<\/p>\n<p>Let&#8217;s have a look at the Delphi Berlin implementation:<\/p>\n<pre class=\"\">function TNetEncoding.Encode(const Input: string): string;\r\nbegin\r\n\u00a0 Result := DoEncode(Input);\r\nend;\r\n...\r\nfunction TBase64Encoding.DoEncode(const Input: string): string;\r\nbegin\r\n\u00a0 Result := DoEncodeBytesToString(TEncoding.UTF8.GetBytes(Input));\r\nend;<\/pre>\n<p>Delphi Berlin always converts the string into UTF-8 bytes and then encodes the bytes. This means that the implementation of EncodeString in Delphi Berlin differs to the implementation in XE3.<\/p>\n<p>To fix this issue let&#8217;s try the following implementation in Delphi Berlin:<\/p>\n<pre class=\"\">procedure TForm1.Button1Click(Sender: TObject);\r\nvar\r\n\u00a0 lBytes: TBytes;\r\nbegin\r\n\u00a0 lBytes := TEncoding.Default.GetBytes('\u00c4\u00e4\u00d6\u00f6\u00dc\u00fc\u00df');\r\n\u00a0 lBytes := TNetEncoding.Base64.Encode(lBytes);\r\n\u00a0 ShowMessage(TEncoding.Default.GetString(lBytes));\r\nend;<\/pre>\n<p>I first convert the string into bytes with the help of the default encoding. Then I encode the bytes with the new Base64 class and at the end I have to convert the bytes back to a string.<\/p>\n<p>I will contact Embarcadero\/Idera and ask them if I should write a quality portal case.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This week I had to migrate an application from Delphi XE3 to Delphi Berlin and this application uses a Base64 encoding. Normally Base64 encoding is not difficult stuff and Delphi XE3 simply offers the function EncodeString in the unit Soap.EncdDecd. &hellip; <a href=\"https:\/\/www.kassebaum.eu\/blog\/2016\/09\/11\/encodestring\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[20,31,12,32,34,13,21,23,27,3,1],"tags":[],"class_list":["post-476","post","type-post","status-publish","format-standard","hentry","category-c-builder","category-delphi","category-firemonkey","category-rad-studio-10-seattle","category-rad-studio-10-1-berlin","category-rad-studio-xe5","category-rad-studio-xe6","category-rad-studio-xe7","category-rad-studio-xe8","category-tipsandtricks","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/www.kassebaum.eu\/blog\/wp-json\/wp\/v2\/posts\/476","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.kassebaum.eu\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.kassebaum.eu\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.kassebaum.eu\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.kassebaum.eu\/blog\/wp-json\/wp\/v2\/comments?post=476"}],"version-history":[{"count":10,"href":"https:\/\/www.kassebaum.eu\/blog\/wp-json\/wp\/v2\/posts\/476\/revisions"}],"predecessor-version":[{"id":486,"href":"https:\/\/www.kassebaum.eu\/blog\/wp-json\/wp\/v2\/posts\/476\/revisions\/486"}],"wp:attachment":[{"href":"https:\/\/www.kassebaum.eu\/blog\/wp-json\/wp\/v2\/media?parent=476"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.kassebaum.eu\/blog\/wp-json\/wp\/v2\/categories?post=476"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.kassebaum.eu\/blog\/wp-json\/wp\/v2\/tags?post=476"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}