juin
2008
En ce moment je travaille sur le format OpenXml pour réaliser en C++ un outil de mailing.
Le principe de base étant de remplacer des valeurs reconnaissables dans le fichier document.xml de Word par des données utilisateurs.
Pour cela j’utilise TinyXml pour parser le fichier et le modifier, le hic c’est que l’encodage des valeurs dans le fichier xml est au format UTF8 …
Après quelques recherches sur le net et ne voyant pas solutions acceptables pour codifier et dé codifier une chaine en UTF8, j’ai écris ces fonctions en me basant sur un article de Wikipédia.
Je vous livre le code qui fera partie de la Faq Visual C++ :
Notes:
-UTF-8 (UCS transformation format 8 bits) permet de coder de l’Unicode sous une suite de 4 octets maximum.
-Cette codification est par exemple utilisée dans le fichier document.xml au format OpenXml de Word 2007.
-Les caractères dont le code ASCII est supérieur à 127 sont codés sur plusieurs octets.
-Une chaine au format UTF8 peut être contenu dans une CString multi bytes .
-j’ai implémenté la codification sur 4 octets mais l’exemple de Wikipédia avec le « ? » ne semble pas correct dans ce cas puisque son code ASCII est égal à 63.
-ce code ne fonctionne pas directement avec Visual 6.0 à cause des CString: On ne dispose pas de CStringA et de CStringW…
{
CStringW input(str);
CStringA output;
for(int i=0; i < input.GetLength(); i++)
{
// 0xxxxxxx
if(input[i] < 0x80)
{
output+=input[i];
}
// C0 80
// 110xxxxx 10xxxxxx
else if((input[i] > 0x7F) && (input[i] < 0x800))
{
output+=static_cast<unsigned char>(0xC0 | (input[i] >> 6));
output+=static_cast<unsigned char>(0x80 | (input[i] & 0x3F));
}
// E0 80 80
// 1110xxxx 10xxxxxx 10xxxxxx
else if(input[i] < 0x8000)
{
output+=static_cast<unsigned char>(0xE0 | (input[i] >> 12));
output+=static_cast<unsigned char>(0x80 | (input[i] >> 6 & 0x3F));
output+=static_cast<unsigned char>(0x80 | (input[i] & 0x3F));
}
else
{ // F0 80 80 80
//11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
output+=static_cast<unsigned char>(0xF0 | (input[i] >> 12)>>6);
output+=static_cast<unsigned char>(0x80 | (input[i] >> 12 & 0x3F));
output+=static_cast<unsigned char>(0x80 | (input[i] >> 6 & 0x1F));
output+=static_cast<unsigned char>(0x80 | (input[i] & 0x3F));
}
}
return output;
}
CStringA UTF8DecodeString(const CStringA input)
{
CStringW output;
for(int i=0; i < input.GetLength();i++)
{
// F0 80 80 80
//11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
if((input[i] & 0xFE) == 0xFE)
{
output+= static_cast<wchar_t>(((input[i] & 7 )<< 18) | ((input[i+1] & 0x3F) << 12) | ((input[i+2] & 0x3F) << 6) | (input[i+3] & 0x3F));
i += 3;
}
else
// E0 80 80
// 1110xxxx 10xxxxxx 10xxxxxx
if((input[i] & 0xE0) == 0xE0)
{
output+= static_cast<wchar_t>(((input[i] & 0x0F) << 12) | ((input[i+1] & 0x3F) << 6) | (input[i+2] & 0x3F));
i += 2;
}
// C0 80
// 110xxxxx 10xxxxxx
else if((input[i] & 0xC0) == 0xC0)
{
output+= static_cast<wchar_t>(((input[i] & 0x1F) << 6) | (input[i+1] & 0x3F));
i ++;
}
// 0xxxxxxx
else if(input[i] < 0x80) output+=input[i];
}
return CStringA(output);
}
CStringA input,output;
input="é";
output=UTF8EncodeString(input);
TRACE("\n output é:%s",static_cast<const char *>(output));
output=UTF8DecodeString(output);
TRACE("\n output é:%s",static_cast<const char *>(output));
input="€";
output=UTF8EncodeString(input);
TRACE("\n output €:%s",static_cast<const char *>(output));
output=UTF8DecodeString(output);
TRACE("\n output é:%s",static_cast<const char *>(output));
Articles récents
Commentaires récents
Archives
- septembre 2010
- mai 2010
- avril 2010
- février 2010
- août 2009
- juin 2009
- mai 2009
- février 2009
- décembre 2008
- novembre 2008
- octobre 2008
- septembre 2008
- juillet 2008
- juin 2008
- mai 2008
- avril 2008
- mars 2008
- février 2008
- janvier 2008
- décembre 2007
- novembre 2007
- septembre 2007
- août 2007
- juillet 2007
- juin 2007
- mai 2007
- avril 2007
- mars 2007
- février 2007
- janvier 2007
- décembre 2006
- novembre 2006
- octobre 2006
- septembre 2006
- août 2006
- juillet 2006
- juin 2006
- mai 2006
- mars 2006
- février 2006