Jump to content
Jefrey

ForceUTF8: forcedly convert strings to UTF-8 (without knowing its original encoding)

Recommended Posts

Non-important short long story: I was facing several troubles when working with a webservice made in PHP and an AutoIt client. The AutoIt client had to send some data to the PHP webservice, then it would get back part of the data (with additional data) back to AutoIt, then send through Json to another webservice and end up in a TV system (huff). As I was using mostly Inet* functions, working with charsets became complicated, as it had to encode, decode, encode... and the mess is done. On the other end I was receiving a completely buggy string with several problems in accentuated characters (note that I live in Brazil, we speak portuguese that contains a lot of accented chars - Ááãç...). I tried and tried mixing utf_encodes and decodes everywhere, in PHP and Javascript. Wouldn't it be easier if I could just force the string to be UTF-8 and screw everything else? So I found toUTF8() PHP function.

I've ported toUTF8() function (truly, the whole Encoding class) by Sebastián Grignoli to AutoIt. It offers useful functions to force a string to be in a specified charset in a really easy way.

From the readme file:

Quote

 

AutoIt3 lacks of support to string encoding conversion and it tends to be painful when working with webservices and on-line APIs.

This lib addresses this issue and provides a handy function called toUTF8().

You don't need to know what is the encoding of your script. It can be Latin1 (ISO-8859-1), Windows-1252 OR UTF-8, or even have a mix of them. toUTF8() will convert everything to UTF-8.

There is also another function available, called fixUTF8(), which will fix the double (or multiple) encoded UTF-8 string that looks garbled.

 

Usage

$utf8_string = toUTF8($utf8_or_latin1_or_mixed_string)

$latin1_string = toLatin1($utf8_or_latin1_or_mixed_string)

Also:

$utf8_string = fixUTF8($garbled_utf8_string)

fixUTF8() converts the string to UTF-8 repeatedly until make sure it has only UTF-8 valid chars (it's really UTF-8).

Example:

#include 'forceutf8.au3'
MsgBox(0, '', fixUTF8( 'ãé' ) )

Will output:

ãé

Note that it's just a port. If you look at both the source codes together (PHP and AutoIt), you'll see that they're exactly the same thing, but in different approaches (PHP arrays converted to Scripting.Dictionary objects, function renames, syntax porting, a few functions completely rewritten due to differences between PHP and AutoIt). Therefore, all credits goes to Sebastián Grignol.

It seems that it works only with latin/roman alphabet (used by English).

Downloads

Download ZIP from Github

Wanna help?

Fork me on Github

Edited by Jefrey

My stuff

Spoiler

My UDFs  _AuThread multithreading emulation for AutoIt · _ExtInputBox an inputbox with multiple inputs and more features · forceUTF8 fix strings encoding without knowing its original charset · JSONgen JSON generator · _TCPServer UDF multi-client and multi-task (run on background) event-based TCP server easy to do · _TCPClient_UDF multi-server and multi-task (runs on background) event-based TCP client easy to do · ParseURL and ParseStr functions ported from PHP · _CmdLine UDF easily parse command line parameters, keys or flags · AutoPHP Create documents (bills, incomes) from HTML by sending variables/arrays from AutoIt to PHP · (Un)Serialize Convert arrays and data into a storable string (PHP compatible) · RTTL Plays and exports to MP3 Nokia-format monophonic ringtones (for very old cellphones) · I18n library Simple and easy to use localization library · Scripting.Dictionary OOP and OOP-like approach · Buffer/stack limit arrays to N items by removing the last one once the limit is reached · NGBioAPI UDF to work with Nitgen fingerprint readers · Serial/Licensing system require license key based on unique machine ID from your users · HTTP a simple WinHTTP library that allows GET, POST and file uploads · Thread true AutoIt threads (under-dev) · RC4 RC4 encryption compatible with PHP and JS ·  storage.au3 localStorage and sessionStorage for AutoIt Classes _WKHtmlToX uses wkhtmlto* to convert HTML files and webpages into PDF or images (jpg, bmp, gif, png...) Snippets _Word_DocFindReplaceByLongText replace strings using Word UDF with strings longer than 255 characters (MSWord limit) rangeparser parser for printing-like pages interval (e.g.: "1,2,3-5") EnvParser parse strings/paths with environment variables and get full path Random stuff Super Mario beep sound your ears will hurt

 

Share this post


Link to post
Share on other sites

Sorry but there are a number of misconception in what you write.

7 hours ago, Jefrey said:

MsgBox(0, '', fixUTF8( 'ãé' ) )

The string shown is nowhere UTF8. It is the UTF16 representation of the series of Latin1 bytes that encode ãé in UTF8.

Also, this part is wrong:

"You don't need to know what is the encoding of your script. It can be Latin1 (ISO-8859-1), Windows-1252 OR UTF-8, or even have a mix of them. toUTF8() will convert everything to UTF-8."

Of course you definitely need to know the source encoding, else you're going to corrupt it while converting it to UTF8. Mixed codepages can't work.

Finally, that is plain wrong as well:

" AutoIt3 lacks of support to string encoding conversion "

Just use _WinAPI_MultiByteToWideChar[Ex] and _WinAPI_WideCharToMultiByte wisely.

Edited by jchd

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Share this post


Link to post
Share on other sites

Well so let me explain them...

Quote

Sorry but there are a number of misconception in what you write.

On 19/06/2016 at 3:56 PM, Jefrey said:

MsgBox(0, '', fixUTF8( 'ãé' ) )

The string shown is nowhere UTF8. It is the UTF16 representation of the series of Latin1 bytes that encode ãé in UTF8.

Also, this part is wrong:

"You don't need to know what is the encoding of your script. It can be Latin1 (ISO-8859-1), Windows-1252 OR UTF-8, or even have a mix of them. toUTF8() will convert everything to UTF-8."

Of course you definitely need to know the source encoding, else you're going to corrupt it while converting it to UTF8. Mixed codepages can't work.

The purpose of this script (and the original popular PHP 'forceUTF8' where it was translated from) is to fix mixed-encoded strings, forcedly (dictionary-based), to UTF-8. It's really not needed to know the source encoding, as it uses a kind of table with common encoding errors and convert them kinda manually (said, if it finds "é", converts it directly to é). As it uses a dictionary with common char encoding errors, the string still can be a mix between multiple charsets.

Take a look on the original project in PHP (not mine): https://github.com/neitanod/forceutf8 and here is the main file

Quote

Finally, that is plain wrong as well:

" AutoIt3 lacks of support to string encoding conversion "

Just use _WinAPI_MultiByteToWideChar[Ex] and _WinAPI_WideCharToMultiByte wisely

The problem with the winapi (not exactly the AU3 lib) is that the function names aren't so clear... Is there some function to detect string encoding as well?

 


My stuff

Spoiler

My UDFs  _AuThread multithreading emulation for AutoIt · _ExtInputBox an inputbox with multiple inputs and more features · forceUTF8 fix strings encoding without knowing its original charset · JSONgen JSON generator · _TCPServer UDF multi-client and multi-task (run on background) event-based TCP server easy to do · _TCPClient_UDF multi-server and multi-task (runs on background) event-based TCP client easy to do · ParseURL and ParseStr functions ported from PHP · _CmdLine UDF easily parse command line parameters, keys or flags · AutoPHP Create documents (bills, incomes) from HTML by sending variables/arrays from AutoIt to PHP · (Un)Serialize Convert arrays and data into a storable string (PHP compatible) · RTTL Plays and exports to MP3 Nokia-format monophonic ringtones (for very old cellphones) · I18n library Simple and easy to use localization library · Scripting.Dictionary OOP and OOP-like approach · Buffer/stack limit arrays to N items by removing the last one once the limit is reached · NGBioAPI UDF to work with Nitgen fingerprint readers · Serial/Licensing system require license key based on unique machine ID from your users · HTTP a simple WinHTTP library that allows GET, POST and file uploads · Thread true AutoIt threads (under-dev) · RC4 RC4 encryption compatible with PHP and JS ·  storage.au3 localStorage and sessionStorage for AutoIt Classes _WKHtmlToX uses wkhtmlto* to convert HTML files and webpages into PDF or images (jpg, bmp, gif, png...) Snippets _Word_DocFindReplaceByLongText replace strings using Word UDF with strings longer than 255 characters (MSWord limit) rangeparser parser for printing-like pages interval (e.g.: "1,2,3-5") EnvParser parse strings/paths with environment variables and get full path Random stuff Super Mario beep sound your ears will hurt

 

Share this post


Link to post
Share on other sites
Quote

The purpose of this script (and the original popular PHP 'forceUTF8' where it was translated from) is to fix mixed-encoded strings, forcedly (dictionary-based), to UTF-8. It's really not needed to know the source encoding, as it uses a kind of table with common encoding errors and convert them kinda manually (said, if it finds "é", converts it directly to é). As it uses a dictionary with common char encoding errors, the string still can be a mix between multiple charsets.

This is simply impossible to do reliably.

Just take the simple example of yours: 'é' which your scipt will convert to 'é'. Let's imagine for simplicity that you actually have the following UTF8 byte sequence C3 A9. As a sidenote realize that this two byte sequence is completely different from the AutoIt string 'é' wich is represented in memory as C3 00 A9 00. But let's leave that detail burried.

Now please explain how you would sort out C3 A9 being the UTF8 sequence for é from any of the following distinct interpretations:

the Big5 ideogram (Unicode codepoint U+77C7 represented as E7 9F 87 in UTF8) or
the Euc-JP ideogram 辿 (Unicode codepoint U+8FBF represented as E8 BE BF in UTF8 ) or
the Shift-JIS ideograms テゥ (Unicode codepoints U+FF83 U+FF69 represented as EF BE 83 EF BD A9 in UTF8 ) or
the Euc-Kr (Unicode codepoint U+CC55 represented as EC B1 95 in UTF8 ) or?
just the characters é in Latin1 ( (Unicode codepoints U+00C3 U+00A9 represented as C3 83 C2 A9 in UTF8 ) or
dozens and dozens of distinct character(s), encoded is codepage(s) you ignore, all of these being represented by the very same C3 A9 sequence?

Answer: you can't.

All the different interpretations, being different characters, have a completely distinct UTF8 encoding, so what you propose is just guesswork. Even with single-byte characters > 0x7F in some codepage, you don't know which they represent as you have no idea which codepage they come from. The "dictionary with common char encoding errors" is just a pitfall waiting to trap unsuspecting users.

You may interpret sequences of bytes as UTF8, but don't pretend you can reliably convert any sequence of characters in unknown encodings (mixed or not), that's just plain impossible.


This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Share this post


Link to post
Share on other sites
Quote

the Big5 ideogram  (Unicode codepoint U+77C7 represented as E7 9F 87 in UTF8) or
the Euc-JP ideogram 辿 (Unicode codepoint U+8FBF represented as E8 BE BF in UTF8 ) or
the Shift-JIS ideograms テゥ (Unicode codepoints U+FF83 U+FF69 represented as EF BE 83 EF BD A9 in UTF8 ) or
the Euc-Kr  (Unicode codepoint U+CC55 represented as EC B1 95 in UTF8 ) or?
just the characters Ã© in Latin1 ( (Unicode codepoints U+00C3 U+00A9 represented as C3 83 C2 A9 in UTF8 ) or
dozens and dozens of distinct character(s), encoded is codepage(s) you ignore, all of these being represented by the very same C3 A9 sequence?

So, in fact, as I said on the OP, the lib isn't my work. It's already a solid work by neitanoid@github and I just converted it to AutoIt3, but it's exactly the very same code.

Although it's not mine (and I don't want to be devil's lawyer), it seems that the focus of the original project aren't chars out of roman/latin alphabet. Thus, the problem mentioned on the quoted part above will never happen as these chars aren't on it.

Note that as I'm not the original author of the work (PHP) and it's not mentioned on the project page (and I never faced the mentioned problem as I'm based in Brazil and we also use roman alphabet), I didn't know about this possible "focus" of the project.

Quote

Just take the simple example of yours: 'é' which your scipt will convert to 'é'. Let's imagine for simplicity that you actually have the following UTF8 byte sequence C3 A9. As a sidenote realize that this two byte sequence is completely different from the AutoIt string 'é' wich is represented in memory as C3 00 A9 00. But let's leave that detail burried.

In my tests, this is more related to the .au3 file charset than to an AutoIt encoding.

Quote

The "dictionary with common char encoding errors" is just a pitfall waiting to trap unsuspecting users.

Users following the recomendation above (adding to the OP) have nothing to fear.

 

Also, I'd suggest you to fill an issue up with these problems found, although I think they will give the same answer: https://github.com/neitanod/forceutf8/issues/new


My stuff

Spoiler

My UDFs  _AuThread multithreading emulation for AutoIt · _ExtInputBox an inputbox with multiple inputs and more features · forceUTF8 fix strings encoding without knowing its original charset · JSONgen JSON generator · _TCPServer UDF multi-client and multi-task (run on background) event-based TCP server easy to do · _TCPClient_UDF multi-server and multi-task (runs on background) event-based TCP client easy to do · ParseURL and ParseStr functions ported from PHP · _CmdLine UDF easily parse command line parameters, keys or flags · AutoPHP Create documents (bills, incomes) from HTML by sending variables/arrays from AutoIt to PHP · (Un)Serialize Convert arrays and data into a storable string (PHP compatible) · RTTL Plays and exports to MP3 Nokia-format monophonic ringtones (for very old cellphones) · I18n library Simple and easy to use localization library · Scripting.Dictionary OOP and OOP-like approach · Buffer/stack limit arrays to N items by removing the last one once the limit is reached · NGBioAPI UDF to work with Nitgen fingerprint readers · Serial/Licensing system require license key based on unique machine ID from your users · HTTP a simple WinHTTP library that allows GET, POST and file uploads · Thread true AutoIt threads (under-dev) · RC4 RC4 encryption compatible with PHP and JS ·  storage.au3 localStorage and sessionStorage for AutoIt Classes _WKHtmlToX uses wkhtmlto* to convert HTML files and webpages into PDF or images (jpg, bmp, gif, png...) Snippets _Word_DocFindReplaceByLongText replace strings using Word UDF with strings longer than 255 characters (MSWord limit) rangeparser parser for printing-like pages interval (e.g.: "1,2,3-5") EnvParser parse strings/paths with environment variables and get full path Random stuff Super Mario beep sound your ears will hurt

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Similar Content

    • By UEZ
      Hi,
      here a little tool to create ISO files from default ISO 9660 (2048 bytes/sector) CD or DVD format (no audio cd and BD support yet!)

      Source is too huge for code box -> Look here to have a look to the source code
      Additional credits to:
      Ward for MD5 checksum / MemoryDLL routines
      Harald Vistnes for cd2iso used in v1 and v2
      Yashied for WinAPIEx.au3
      wolf9228 to play wave from memory
      AutoItObject Team
      Download (purely written with AutoIt): ISO Creator v1.16 build 2015-07-13 beta.7z (1110 downloads previously)
      Thanks to smashly for pointing me to right direction
      The development of v1 and v2 is discontinued!
      Download v1: ISO Creator v1.0.0 build 2011-08-03 beta v1.7z (195 downloads previously)
      Download v2 (everything is called directly from memory): ISO Creator v1.0.0 build 2011-08-03 beta v2.7z (117 downloads previously)
      Thanks to smartee for the DLL version (experimental) of cd2iso!
      v1 is using cd2iso.exe to create the ISO
      v2 is using cd2iso.dll which was created by smartee.
      For compiled v1, v2 and pure AutoIt versions only (x86) visit (ISO Creator Exe only): 4shared.com or MediaFire
      You can call ISO Creator.exe also with command line parameters: ISO Creator.exe -s [source cd/dvd drive] -d [filename] (-md5) (-aem) (-exit)
      -s and -d are mendatory if called from command line!
      Tested on Win7 x64.
      If you find any bug please report here!
      Many thanks to smartee and smashly for their efforts on this project!
      Br,
      UEZ
      Change Log:
       
       
    • By GillesMaisonneuve
      Good morning,
       
      I am trying to read a Unicode utf8 string from a perl subprocess via StdoutRead.
      I use an AUtoIt GUI and display result in an 'Edit' control (see my code below) using 'Courier New', a font that can handle Unicode characters.
      I was expecting a result looking like (CMD console):
      ++$ chcp 65001>NUL: & perl -Mutf8 -CS -e "use 5.018; binmode STDOUT,q(:utf8); say qq(\x{03A9})" & chcp 850>NUL: Ω Instead I get someting like this (see downward the screen copy):
      ++$ chcp 1250>NUL: & perl -Mutf8 -CS -e "use 5.018; binmode STDOUT,q(:utf8); say qq(\x{03A9})" & chcp 850>NUL: Ω Obviously while I was expecting to receive an utf8 char, it seems to have been converted to Windows ANSI codepage 1250 (Windows default for Western/Central Europe, right ?)
      What am I doing wrong? Is there someone who could guide me?
       
      Here is my code and my output in the GUI.
      Creating and configuring the Edit control:
      Local $Edit1 = GUICtrlCreateEdit( "", 20, 110, 780, 500, BitOr($GUI_SS_DEFAULT_EDIT,$ES_MULTILINE,$ES_READONLY) ) GUICtrlSetData($Edit1, "This field will contain text result from external Perl command") GUICtrlSetFont($Edit1, 10, $FW_THIN, $GUI_FONTNORMAL, "Courier New")  
      Executing Perl command (note: `-Mutf8` and `-CS` garantees that I work in utf8 and STDOUT accepts wide-characters):
      local $ExePath = 'perl.exe -Mutf8 -CS ' ;~ if perl in PATH, no need for full path C:\Perl\bin\perl.exe local $Params = '-e "use 5.018; use utf8; use charnames q(:full); binmode STDOUT,q(:utf8);' & _ 'say scalar localtime; say qq(\N{GREEK CAPITAL LETTER OMEGA})"' local $Cmd = $ExePath & ' ' & $Params Local $iPID = Run($Cmd, "", @SW_HIDE, BitOR($STDERR_CHILD, $STDOUT_CHILD))  
      Reading STDOUT and displaying it into the Edit control:
      While 1 $sOutput &= StdoutRead($iPID) If @error Then ; Exit the loop if the process closes or StdoutRead returns an error. ExitLoop EndIf WEnd If $sOutput <> '' Then GUICtrlSetData($Edit1, $sOutput) EndIf  
      And now, what I get on my GUI:
       

    • By Skysnake
      'F‌inal' ; <========= problem between F and i 'F‌inal' ; <========= problem between F and i 'Final' ; <========= Notepad ANSI, no problem
      F‌inal

      PostgreSQL complains about that red dot.  Notepad++ marks the first word.
      Notepad said it contains Unicode.  Saved as ANSI and put back. Red dot is gone.
       
      the Text is inserted manually into an AutoIt Input box.  Things get done to it, and it ends up in a SQL database.  The data seems fine, but when I start generating reports, all kinds of funny problems show up.
       
      If I can ID that character, I can remove it.
      Any ideas?
    • By nacerbaaziz
      Hi dear
      With this script you can print Unicode text in the CMD screen
      the script is  easy to use
      just you  write the text that contains Unicode in the first input
      and the script automatically reflect the code in the second input
       you can copy the text to the clipboard
      or you can try printing the text in the CMD window
      I apologize to everyone for colors and shape if not appropriate
      I'm a blind man and I do not see
      Thank you for your understanding
      Greetings to all of youCmdUtM.au3
    • By Chimp
      regex and iso escape sequences
      Hi, I would like to extract all ISO escape squences embedded in a string and separate them from the rest of the string, still keeping the information about their position, so that, for exemple, a string like this one (or even more complex):
      (the string could start with normal text or iso sequences)
       
      '\u001B[4mUnicorn\u001B[0m' should be 'transformed' in an array like this
      $a[0] = '\u001B[4m' ; first iso escape sequence $a[1] = 'Unicorn' ; normal text $a[2] = '\u001B[4m' ; second iso escape sequence ... and so on (note: the above escape sequence has 'control codes' marked as "\u001B' for the asc "esc" char for exemple and a similar notation is also used for other control chars, but in the real string to be parsed those control chars  are embedded  as a single byte with a value from 01 to 31). at this link (http://artscene.textfiles.com/ansi/) there are many example of real ANSI text files .
      searching on the web I've found some possible solutions that make use of regexp to achieve similar purpose, and above some others, the regexp pattern posted in the following link by kfir (https://stackoverflow.com/questions/14693701/how-can-i-remove-the-ansi-escape-sequences-from-a-string-in-python) seems to be able to catch a wider range of ISO escape sequences (not only color sequences), but my lack of skills on regexp, prevents me from evaluating and testing such patterns
      I would be very grateful if some regexp guru could come to my rescue...
      thanks everybody  for reading...
×
×
  • Create New...