12
votes

Y a-t-il une bibliothèque C pour convertir des points de code Unicode en UTF-8?

Je dois passer du texte et écrire la sortie UTF-8 en fonction des motifs de caractères. Je pensais que ce sera facile si je peux travailler avec les points de code et l'obtenir converti en UTF-8. J'ai lu sur Unicode et UTF-8, mais je n'ai pas trouvé une bonne solution. Toute aide sera appréciée.


0 commentaires

4 Réponses :


1
votes

Quelle plate-forme? Sous Windows, vous pouvez utiliser widechartomultibyte (Cp_utf8, ...)

sans doute, le code de code source doit être codé dans UTF-16, ce qui signifie que vous devez pouvoir effectuer un tel encodage. Dans certains cas (paires de substituts), ce n'est pas trivial.

Ma compréhension est que vous avez du texte dans un code de code donné et que vous souhaitez le convertir en Unicode (UTF-16). Droite? Un multibytetowidechar (codépage, Sourcetext, ...) / widechartomultibyte (cp_utf8, utf16text, ...) aller-retour fera le tour.


1 commentaires

@chanux: Ensuite, vous pouvez utiliser iconv , comme décrit dans les autres réponses.



2
votes

0 commentaires

5
votes

iconv pourrait être utilisé i graphique.

uint16_t in = UNICODE_POINT_VALUE;
cd = iconv_open("utf-8", "ucs-2");


5 commentaires

Et si le point de code n'est pas dans le BMP? UCS-2 ne peut pas le représenter. Un wchar_t peut ne pas suffire à la plate-forme. C'est pourquoi je pense que l'hypothèse de l'OP sur la connaissance du point de code est fausse. Parce qu'alors, la question du codage utilisé pour le représenter est posée (UTF-32? UTF-16? Évidemment pas UTF-8)


Si __ stdc_iso_10646 __ est défini, wchar_t est une valeur de code de code Unicode. Notez que si wchar_t est 16 bits, cela implique que seul le BMP est pris en charge; UTF-16 n'est pas une possibilité.


Un WCHAR_T 16 bits peut être utilisé définitivement dans les chaînes codées UTF-16. Tout cela signifie que toute valeur de code de code de code à l'extérieur du BMP sera codée à l'aide de 2 WCHAR_T Caractères de substitution côte à côte dans la chaîne codée, c'est tout. L'API Windows fonctionne exactement sur ce type de données, et cela fonctionne très bien.


@RemyleBeau: L'API C pour WCHAR_T La conversion ne rend pas possible à une telle utilisation. Il n'y a aucun moyen pour MBRTOWC pour générer une paire de valeurs wchar_t à la suite de sa conversion. Il ne peut en générer qu'un seul. Je n'ai aucune idée de ce que Windows fait, mais cela ne peut pas fournir une version de travail de ces fonctions standard; Il doit utiliser une API spécifique à Windows et ignorer le fait que les fonctions standard ne fonctionnent pas ...


De nombreuses fonctions de l'API standard C déléguent aux fonctions de système d'exploitation en interne le cas échéant. Il n'a pas de sens que les vendeurs de compilateur de faire tout manuellement. Qui inclut les conversions de texte. Sous Windows, les conversions de texte sont gérées par l'API Win32 widechartomultibyte () et MultiByteTowidechar () Fonctions, qui fonctionnent tous deux sur UTF-16 codé wchar_t Données. Toutes les API activées par Unicode sous Windows sont basées sur UTF-16 et depuis plus d'une décennie.



38
votes

Conversion des points de code UNICODE sur UTF-8 est si trivial que l'appel à une bibliothèque prend probablement plus de code que de le faire vous-même: xxx

aussi, le faisant vous-même signifie que vous pouvez aussi Ajustez l'API au type de travail dont vous avez besoin (caractère à la fois? ou à longs chaînes?) Vous pouvez supprimer les cas d'erreur si vous connaissez que votre entrée est une valeur scalaire unicode valide.

Le Une autre direction est un bon bit plus difficile à obtenir correct. Je recommande une approche automate finie plutôt que les boucles de bit-arithmétique typiques qui décoent parfois des séquences non valides comme alias pour des caractères réels (ce qui est très dangereux et peut entraîner des problèmes de sécurité).

même si vous finissez pas Aller avec une bibliothèque, je pense que vous devriez soit essayer d'écrire vous-même en premier ou au moins sérieusement étudier la spécification UTF-8 avant d'aller plus loin. Beaucoup de mauvais design peut provoquer du traitement UTF-8 comme une boîte noire lorsque tout le point est que ce n'est pas une boîte noire mais a été créée pour avoir des propriétés très puissantes, et trop de programmeurs neufs sur UTF-8 ne parviennent pas à le voir jusqu'à ce que ce soit. Ils ont travaillé avec elle beaucoup elles-mêmes.


12 commentaires

@PHILIPP: Ecrire plus de code pour envelopper une bibliothèque pour correspondre à vos besoins d'interface et à travailler autour de ses bugs mieux? Si vous souhaitez parcourir le code de la bibliothèque existant qui décode UTF-8, vous constaterez que la grande majorité est fausse de manière au moins subtile et au moins 30% a de graves bogues critiques de sécurité. (Ces estimations proviennent d'une recherche de code Google que j'ai fait un moment de retour.) De plus, la mise en œuvre de GNU de iconv est une commande de grandeur trop lente pour les conversions de caractère à la fois, bien que cela fonctionne bien (quoique avec une non-conformité intentionnelle) pour des conversions en vrac.


Mon tir à une version plus avancée: Mercurial.intuxication.org/ HG / CSTUFF / RAW-File / TIP / UTF8_CÉNAGE EC


Le rejet de non-caractères peut être utile pour votre application, mais il ne fait pas partie de la spécification UTF-8 et en général incorrect. UTF est des cartes individuelles entre séquences d'unités de code (octets ou mots plus grands) et «valeurs scalaires unicode». Les valeurs scalaires UNICODE sont exactement les entiers 0-0XD7FF et 0XE000-0X10ffff. Tout cela est défini dans la norme Unicode que vous devriez lire avant d'essayer de mettre en œuvre quelque chose de votre choix.


@R ..: merci pour l'information; Le code est adapté des trucs que j'ai écrites il y a quelque temps et qui n'a jamais fonctionné que sur des personnages (c'est-à-dire des caractères non-caractères, des substituts de substitution, ainsi que des caractères de contrôle ASCII), de sorte que les détails n'étaient pas aussi présents qu'ils auraient dû être; Cependant, je ne suis pas convaincu si cela vaut la peine d'ajouter une autre couche de validation


+1 pour éviter les appels libéraux pour des trucs aussi triviaux. Les gens oublient trop souvent le coût des appels de bibliothèque dynamiques (souvent, c'est un appel d'appel + indirect ou un appel lointain absolu). Si l'appel est pour quelque chose de lourd comme printf aucun problème, c'est négligeable mais pour une conversion de caractère Unicode, c'est énorme.


@R ..: Veuillez expliquer ce qu'est B et quel est c ! Quelle variable représente le point de code?. À quelle valeur B est initialisé?


@ user2284570: C est le code de code (entrée) et B est un pointeur sur le tampon de sortie (octets).


@R ..: Je suppose C int32 et B char *? Quoi qu'il en soit, vous devriez le refléter en vous modifiant. En fait, je veux générer une table HTML annonce des valeurs Unicode. Conversion avec des analgésiques ralentissés par code échappé et rendez le fichier HTML plus grand. Ainsi, utiliser directement codé ᴜᴛꜰ-8 est meilleur.


@R ..: attendez ... votre code est faux! ᴜᴛꜰ-8 est toujours grand Endian et ce code n'est pas neutre de Endian. Cela ne fonctionnerait que sur des machines de Big-Endian, alors que la plupart d'entre elles sont petites-Endian.


@ user2284570: UTF-8 est un flux d'octets. Il n'a pas d'endiangité. L'endianité n'existe que si vous inspectiez ou modifiez la représentation des types.


@R ..: Mais par exemple, disons 192 + c / 64 est égal à 11010000. N'écrivez-vous pas une petite machine Endian écrit 00001011 dans le fichier de sortie?


@ user2284570: Non. Un fichier est une séquence d'octets et non une séquence de bits. L'endansement est l'ordre d'octet. C'est une conséquence du fait que vous traitez d'octets, pas de bits. Certains grands vendeurs de la CPU Endian Nichent les bits d'un octet en arrière dans leurs documents techniques, mais c'est purement une bizarrerie de notation et n'a rien à voir avec l'échange de données. Sur les ports série, il y a bien sûr un ordre d'ordre, mais c'est défini par le matériel, pas l'endansion de la CPU.