Jump to content

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


Jefrey
 Share

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 GUICtrlStaticMarquee static text scrolling Random stuff Super Mario beep sound your ears will hurt

 

Link to comment
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)

Link to comment
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 GUICtrlStaticMarquee static text scrolling Random stuff Super Mario beep sound your ears will hurt

 

Link to comment
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)

Link to comment
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 GUICtrlStaticMarquee static text scrolling Random stuff Super Mario beep sound your ears will hurt

 

Link to comment
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
 Share

×
×
  • Create New...