web-dev-qa-db-fra.com

Caractères Unicode sur imprimante ZPL

J'ai la tâche de reconcevoir un système pour imprimer des étiquettes d'expédition, en utilisant un Zebra GK420T en réseau. J'ai pu lui envoyer des travaux d'impression ZPL parfaitement bien, mais je n'arrive pas à obtenir l'impression de caractères unicode, tels que des lettres cyrilliques. J'ai téléchargé la police lucida sans unicode sur l'imprimante à l'aide des pilotes Seagull Scientific et j'utilise le code ZPL suivant pour tester:

^XA
^LH100,150
^CWT,E:TT0003M_.FNT
^CFT,30,30
^CI28
^FT0,0^FDTesting 1 2 3^FS
^FT0,50^FDДо свидания^FS
^FT0,100^B3^FDAAA001^FS
^XZ

Il imprimera le "Test 1 2 3" et le code-barres, mais il laissera un espace vide au lieu des caractères cyrilliques. Suis-je en train de faire quelque chose de mal comme ne pas échapper de caractères ou quelque chose ou est-ce un problème avec l'imprimante?

Merci d'avance

EDIT: J'ai essayé d'utiliser la police unicode suisse Zebra et maintenant elle imprime les caractères russes comme des points d'interrogation. J'ai mis à jour le code ci-dessus pour le refléter.

19
Tom Brunoli

Je viens de découvrir que vous devez échapper les caractères ci-dessus ASCII en mettant d'abord ^FH avant tout ^FD champs pouvant contenir un caractère utf et vous devez préfixer le code hexadécimal utf-8 avec un trait de soulignement

_D0_94 sera imprimé comme Д. Mon code ZPL final est le suivant:

^XA
^LH100,150
^CWT,E:TT0003M_.FNT
^CFT,30,30
^CI28
^FT0,0^FH^FDTesting 1 2 3^FS
^FT0,50^FH^FD_D0_94_D0_BE _D1_81_D0_B2_D0_B8_D0_B4_D0_B0_D0_BD_D0_B8_D1_8F^FS
^FT0,100^B3^FDAAA001^FS
^XZ

Je vais juste devoir trouver un moyen de générer les séquences d'échappement, ce qui devrait être beaucoup plus facile!

18
Tom Brunoli

J'ai eu le même problème, vous devez ajouter un ^FH (Indicateur hexadécimal de champ) avant tout ^FD (Field Data) commande qui contient des caractères spéciaux, dans mon cas j'ai besoin de caractères espagnols donc j'ai dû utiliser ^CI28 (Changer la police/l'encodage international)

liste des codes HEX UTF 8

exemple: pour imprimer Alvaro Jesús Pérez Peñaranda nous devons convertir ces caractères spéciaux en code hexadécimal UTF 8 et ajouter un _ avant chaque code, voici le résultat: Alvaro Jes_c3_bas P_c3_a9rez Pe_c3_b1aranda

^XA

^CI28
^FO60,75
^ASN,36,20^FH^FDAlvaro Jes_c3_bas P_c3_a9rez Pe_c3_b1aranda^FS

^XZ
11
Christian Rojas

J'utilise une imprimante Zebra ZM400 et j'utilise la police TT0003M_.

cette police n'imprime pas kazakh cyrillic.

si vous voulez imprimer l'alphabet cryillique + cyrillique kazakh + latin, utilisez ARI000.FNT (police arial)

J'utilise la méthode suivante convertir char en code hexadécimal

J'espère que ça aide

stringConverTextToHex(stringtext)
{
stringnewText="";
char[]charArray=text.ToCharArray();
foreach(charcincharArray)
{
switch(c)
{
case'й':
newText+="_D0_B9";
break;
case'Й':
newText+="_D0_99";
break;
case'ц':
newText+="_D1_86";
break;
case'Ц':
newText+="_D0_A6";
break;
case'у':
newText+="_D1_83";
break;
case'У':
newText+="_D0_A3";
break;
case'к':
newText+="_D0_BA";
break;
case'К':
newText+="_D0_9A";
break;
case'е':
newText+="_D0_B5";
break;
case'Е':
newText+="_D0_95";
break;
case'н':
newText+="_D0_BD";
break;
case'Н':
newText+="_D0_9D";
break;
case'г':
newText+="_D0_B3";
break;
case'Г':
newText+="_D0_93";
break;
case'ш':
newText+="_D1_88";
break;
case'Ш':
newText+="_D0_A8";
break;
case'щ':
newText+="_D1_89";
break;
case'Щ':
newText+="_D0_A9";
break;
case'з':
newText+="_D0_B7";
break;
case'З':
newText+="_D0_97";
break;
case'х':
newText+="_D1_85";
break;
case'Х':
newText+="_D0_A5";
break;
case'ъ':
newText+="_D1_8A";
break;
case'Ъ':
newText+="_D0_AA";
break;
case'ф':
newText+="_D1_84";
break;
case'Ф':
newText+="_D0_A4";
break;
case'ы':
newText+="_D1_8B";
break;
case'Ы':
newText+="_D0_AB";
break;
case'в':
newText+="_D0_B2";
break;
case'В':
newText+="_D0_92";
break;
case'а':
newText+="_D0_B0";
break;
case'А':
newText+="_D0_90";
break;
case'п':
newText+="_D0_BF";
break;
case'П':
newText+="_D0_9F";
break;
case'р':
newText+="_D1_80";
break;
case'Р':
newText+="_D0_A0";
break;
case'о':
newText+="_D0_BE";
break;
case'О':
newText+="_D0_9E";
break;
case'л':
newText+="_D0_BB";
break;
case'Л':
newText+="_D0_9B";
break;
case'д':
newText+="_D0_B4";
break;
case'Д':
newText+="_D0_94";
break;
case'ж':
newText+="_D0_B6";
break;
case'Ж':
newText+="_D0_96";
break;
case'э':
newText+="_D1_8D";
break;
case'Э':
newText+="_D0_AD";
break;
case'я':
newText+="_D1_8F";
break;
case'Я':
newText+="_D0_AF";
break;
case'ч':
newText+="_D1_87";
break;
case'Ч':
newText+="_D0_A7";
break;
case'с':
newText+="_D1_81";
break;
case'С':
newText+="_D0_A1";
break;
case'м':
newText+="_D0_BC";
break;
case'М':
newText+="_D0_9C";
break;
case'и':
newText+="_D0_B8";
break;
case'И':
newText+="_D0_98";
break;
case'т':
newText+="_D1_82";
break;
case'Т':
newText+="_D0_A2";
break;
case'ь':
newText+="_D1_8C";
break;
case'Ь':
newText+="_D0_AC";
break;
case'б':
newText+="_D0_B1";
break;
case'Б':
newText+="_D0_91";
break;
case'ю':
newText+="_D1_8E";
break;
case'Ю':
newText+="_D0_AE";
break;
case'ӑ':
newText+="_D3_91";
break;
case'Ӑ':
newText+="_D3_90";
break;
case'ӓ':
newText+="_D3_93";
break;
case'Ӓ':
newText+="_D3_92";
break;
case'ә':
newText+="_D3_99";
break;
case'Ә':
newText+="_D3_98";
break;
case'ӛ':
newText+="_D3_9B";
break;
case'Ӛ':
newText+="_D3_9A";
break;
case'ӕ':
newText+="_D3_95";
break;
case'Ӕ':
newText+="_D3_94";
break;
case'ґ':
newText+="_D2_91";
break;
case'Ґ':
newText+="_D2_90";
break;
case'ѓ':
newText+="_D1_93";
break;
case'Ѓ':
newText+="_D0_83";
break;
case'ғ':
newText+="_D2_93";
break;
case'Ғ':
newText+="_D2_92";
break;
case'ӷ':
newText+="_D3_B7";
break;
case'Ӷ':
newText+="_D3_B6";
break;
case'ҕ':
newText+="_D2_95";
break;
case'Ҕ':
newText+="_D2_94";
break;
case'ђ':
newText+="_D1_92";
break;
case'Ђ':
newText+="_D0_82";
break;
case'ѐ':
newText+="_D1_90";
break;
case'Ѐ':
newText+="_D0_80";
break;
case'ӗ':
newText+="_D3_97";
break;
case'Ӗ':
newText+="_D3_96";
break;
case'ҽ':
newText+="_D2_BD";
break;
case'Ҽ':
newText+="_D2_BC";
break;
case'ҿ':
newText+="_D2_BF";
break;
case'Ҿ':
newText+="_D2_BE";
break;
case'є':
newText+="_D1_94";
break;
case'Є':
newText+="_D0_84";
break;
case'ӂ':
newText+="_D3_82";
break;
case'Ӂ':
newText+="_D3_81";
break;
case'җ':
newText+="_D2_97";
break;
case'Җ':
newText+="_D2_96";
break;
case'ӝ':
newText+="_D3_9D";
break;
case'Ӝ':
newText+="_D3_9C";
break;
case'ҙ':
newText+="_D2_99";
break;
case'Ҙ':
newText+="_D2_98";
break;
case'ӟ':
newText+="_D3_9F";
break;
case'Ӟ':
newText+="_D3_9E";
break;
case'ӡ':
newText+="_D3_A1";
break;
case'Ӡ':
newText+="_D3_A0";
break;
case'ѕ':
newText+="_D1_95";
break;
case'Ѕ':
newText+="_D0_85";
break;
case'ѝ':
newText+="_D1_9D";
break;
case'Ѝ':
newText+="_D0_8D";
break;
case'ӥ':
newText+="_D3_A5";
break;
case'Ӥ':
newText+="_D3_A4";
break;
case'ӣ':
newText+="_D3_A3";
break;
case'Ӣ':
newText+="_D3_A2";
break;
case'і':
newText+="_D1_96";
break;
case'І':
newText+="_D0_86";
break;
case'ї':
newText+="_D1_97";
break;
case'Ї':
newText+="_D0_87";
break;
case'Ӏ':
newText+="_D3_80";
break;
case'ҋ':
newText+="_D2_8B";
break;
case'Ҋ':
newText+="_D2_8A";
break;
case'ј':
newText+="_D1_98";
break;
case'Ј':
newText+="_D0_88";
break;
case'қ':
newText+="_D2_9B";
break;
case'Қ':
newText+="_D2_9A";
break;
case'ҟ':
newText+="_D2_9F";
break;
case'Ҟ':
newText+="_D2_9E";
break;
case'ҡ':
newText+="_D2_A1";
break;
case'Ҡ':
newText+="_D2_A0";
break;
case'ӄ':
newText+="_D3_84";
break;
case'Ӄ':
newText+="_D3_83";
break;
case'ҝ':
newText+="_D2_9D";
break;
case'Ҝ':
newText+="_D2_9C";
break;
case'ӆ':
newText+="_D3_86";
break;
case'Ӆ':
newText+="_D3_85";
break;
case'љ':
newText+="_D1_99";
break;
case'Љ':
newText+="_D0_89";
break;
case'ӎ':
newText+="_D3_8E";
break;
case'Ӎ':
newText+="_D3_8D";
break;
case'ӊ':
newText+="_D3_8A";
break;
case'Ӊ':
newText+="_D3_89";
break;
case'ң':
newText+="_D2_A3";
break;
case'Ң':
newText+="_D2_A2";
break;
case'ӈ':
newText+="_D3_88";
break;
case'Ӈ':
newText+="_D3_87";
break;
case'ҥ':
newText+="_D2_A5";
break;
case'Ҥ':
newText+="_D2_A4";
break;
case'њ':
newText+="_D1_9A";
break;
case'Њ':
newText+="_D0_8A";
break;
case'ӧ':
newText+="_D3_A7";
break;
case'Ӧ':
newText+="_D3_A6";
break;
case'ө':
newText+="_D3_A9";
break;
case'Ө':
newText+="_D3_A8";
break;
case'ӫ':
newText+="_D3_AB";
break;
case'Ӫ':
newText+="_D3_AA";
break;
case'ҩ':
newText+="_D2_A9";
break;
case'Ҩ':
newText+="_D2_A8";
break;
case'ҧ':
newText+="_D2_A7";
break;
case'Ҧ':
newText+="_D2_A6";
break;
case'ҏ':
newText+="_D2_8F";
break;
case'Ҏ':
newText+="_D2_8E";
break;
case'ҫ':
newText+="_D2_AB";
break;
case'Ҫ':
newText+="_D2_AA";
break;
case'ҭ':
newText+="_D2_AD";
break;
case'Ҭ':
newText+="_D2_AC";
break;
case'ћ':
newText+="_D1_9B";
break;
case'Ћ':
newText+="_D0_8B";
break;
case'ќ':
newText+="_D1_9C";
break;
case'Ќ':
newText+="_D0_8C";
break;
case'ў':
newText+="_D1_9E";
break;
case'Ў':
newText+="_D0_8E";
break;
case'ӳ':
newText+="_D3_B3";
break;
case'Ӳ':
newText+="_D3_B2";
break;
case'ӱ':
newText+="_D3_B1";
break;
case'Ӱ':
newText+="_D3_B0";
break;
case'ӯ':
newText+="_D3_AF";
break;
case'Ӯ':
newText+="_D3_AE";
break;
case'ү':
newText+="_D2_AF";
break;
case'Ү':
newText+="_D2_AE";
break;
case'ұ':
newText+="_D2_B1";
break;
case'Ұ':
newText+="_D2_B0";
break;
case'ҳ':
newText+="_D2_B3";
break;
case'Ҳ':
newText+="_D2_B2";
break;
case'һ':
newText+="_D2_BB";
break;
case'Һ':
newText+="_D2_BA";
break;
case'ҵ':
newText+="_D2_B5";
break;
case'Ҵ':
newText+="_D2_B4";
break;
case'ӵ':
newText+="_D3_B5";
break;
case'Ӵ':
newText+="_D3_B4";
break;
case'ҷ':
newText+="_D2_B7";
break;
case'Ҷ':
newText+="_D2_B6";
break;
case'ӌ':
newText+="_D3_8C";
break;
case'Ӌ':
newText+="_D3_8B";
break;
case'ҹ':
newText+="_D2_B9";
break;
case'Ҹ':
newText+="_D2_B8";
break;
case'џ':
newText+="_D1_9F";
break;
case'Џ':
newText+="_D0_8F";
break;
case'ӹ':
newText+="_D3_B9";
break;
case'Ӹ':
newText+="_D3_B8";
break;
case'ҍ':
newText+="_D2_8D";
break;
case'Ҍ':
newText+="_D2_8C";
break;
case'ӭ':
newText+="_D3_AD";
break;
case'Ӭ':
newText+="_D3_AC";
break;
case'A':
newText+="_41";
break;
case'a':
newText+="_61";
break;
case'B':
newText+="_42";
break;
case'b':
newText+="_62";
break;
case'C':
newText+="_43";
break;
case'c':
newText+="_63";
break;
case'D':
newText+="_44";
break;
case'd':
newText+="_64";
break;
case'E':
newText+="_45";
break;
case'e':
newText+="_65";
break;
case'F':
newText+="_46";
break;
case'f':
newText+="_66";
break;
case'G':
newText+="_47";
break;
case'g':
newText+="_67";
break;
case'H':
newText+="_48";
break;
case'h':
newText+="_68";
break;
case'I':
newText+="_49";
break;
case'i':
newText+="_69";
break;
case'J':
newText+="_4A";
break;
case'j':
newText+="_6A";
break;
case'K':
newText+="_4B";
break;
case'k':
newText+="_6B";
break;
case'L':
newText+="_4C";
break;
case'l':
newText+="_6C";
break;
case'M':
newText+="_4D";
break;
case'm':
newText+="_6D";
break;
case'N':
newText+="_4E";
break;
case'n':
newText+="_6E";
break;
case'O':
newText+="_4F";
break;
case'o':
newText+="_6F";
break;
case'P':
newText+="_50";
break;
case'p':
newText+="_70";
break;
case'R':
newText+="_52";
break;
case'r':
newText+="_72";
break;
case'S':
newText+="_53";
break;
case's':
newText+="_73";
break;
case'T':
newText+="_54";
break;
case't':
newText+="_74";
break;
case'U':
newText+="_55";
break;
case'u':
newText+="_75";
break;
case'V':
newText+="_56";
break;
case'v':
newText+="_76";
break;
case'Y':
newText+="_59";
break;
case'y':
newText+="_79";
break;
case'Z':
newText+="_5A";
break;
case'z':
newText+="_7A";
break;
case'':
newText+="";
break;
default:
newText+=c;
break;
}
}
returnnewText;
}

c'est l'exemple de code


^ SP ^ XA ^ PON ^ FS ^ FPH ^ FO102,63,0 ^ A @ N, 60,60, E: ARIOOO_.FNT ^ FH ^ FD_42_75_72_61_6B _D0_A8_D3_99 ^ FS ^ XZ


7

Le russe et de nombreux autres caractères peuvent être imprimés en utilisant la libre police unicode suisse Zebra . Il est déjà inclus dans la plupart des imprimantes en tant que TT0003M_ et prend en charge le romain, le cyrillique, l'Europe de l'Est, le turc, l'arabe et l'hébreu.


Pour imprimer des langues comme le japonais ou le chinois, qui ont des milliers de caractères, vous avez besoin d'une imprimante avec au moins 23 Mo de mémoire libre et d'un fichier de police TrueType que vous pouvez télécharger (ils l'appellent téléchargement).

Ce fichier peut être acheté auprès de Zebra (et ils disent que vous avez besoin de 64 Mo), mais j'ai également eu beaucoup de succès avec un très ancien fichier TTF trouvé sur mon système Windows 7 dans le dossier Fonts: ARIALUNI.TTF 1.01 (23.275.812 octets) , Arial Unicode MS . Il a été installé par une installation MS Office et n'est peut-être pas sous licence pour cette utilisation.

Très probablement, vous pouvez également utiliser d'autres fichiers TTF, mais je n'ai essayé que celui-ci.

Alors que l'impression ZPL sur cette imprimante Zebra fonctionnait sans pilote d'origine (uniquement du texte générique uniquement), pour l'installation de la police, le pilote était nécessaire. Si quelqu'un sait comment envoyer le fichier TTF à l'imprimante sans pilote, veuillez commenter.

J'ai installé les utilitaires de configuration Zebra, qui incluent un téléchargeur de polices. Cliquez sur nouveau, puis ajoutez la police (doit être installée sur le système) et ignorez le message indiquant que 226 caractères sont inclus. Ignorez également que si vous configurez une chaîne de test avec des caractères Unicode, elle ne s'affichera pas correctement. On vous demande si vous souhaitez télécharger maintenant et cela prend beaucoup de temps.

Vous pouvez vérifier l'installation en répertoriant le contenu du répertoire (page Web d'administration ou impression). Là, la police apparaît comme ARI000.TTF dans mon cas.


Pour imprimer, vous devez envoyer le texte ZPL en UTF-8. Vous pouvez copier cet exemple dans le bloc-notes et sélectionner UTF-8 dans la boîte de dialogue d'enregistrement:

^XA
^LH100,150
^CWT,E:ARI000.FNT
^CFT,30,30
^CI28
^FT0,0^FH^FDyour unicode characters here^FS
^XZ

Ensuite, pour les tests, vous pouvez utiliser une simple commande de copie pour l'envoyer à l'imprimante:

En cas d'USB, vous devez d'abord partager cette imprimante sur le réseau.

Alors Net Use lpt1: \\localhost\sharename et copy file.txt lpt1

Nous avons testé avec de nombreux symboles japonais et chinois courants et cela fonctionne très bien avec une haute qualité, sur une imprimante ZT230 avec un flash de 32 Mo.

5
maf-soft

Votre "До свидания" était probablement en cp1251. Encodez-le en UTF-8 réel et réessayez. Les espaces vides sont un bon indicateur que vous avez un problème d'encodage.

Vérifié avec le firmware v56.17.112 et ^ A @ N , E: TT0003M_.FNT

3
Alexeyy Alexeyy

si vous voulez imprimer des lettres cyrilliques russes en utilisant :TT0003M_.FNT, vous devez enregistrer les commandes dans un fichier avec l'encodage UTF-8!

^XA
^LH100,150
^CWT,E:TT0003M_.FNT
^CFT,30,30
^CI28
^FT0,0^FH^FDTesting 1 2 3^FS
^FT0,30^FH^FDДо свидания^FS
^FT0,100^B3^FDAAA001^FS
^XZ

Ensuite, en utilisant la ligne de commande, vous pouvez l'envoyer au port d'imprimante. Un exemple: copiez C:\Users\xxx\Desktop\test_ru.txt com1

J'espère que cela aidera...

2
Andrius

Dans les dernières versions du micrologiciel (depuis la v x.16.x), vous pouvez utiliser ^ CI33 pour le texte codé de la page de codes Windows-1251 (et d'autres pages de codes) sans ^ FH. Voir manuel

1
pablomedok

Comme d'autres l'ont noté, assurez-vous d'utiliser ^CI28 (Changer la police/l'encodage international) et ^FH (Indicateur hexadécimal de champ) et échappez tous les caractères utf8 non ascii avec un trait de soulignement et leur valeur hexadécimale.

Cependant, une autre réponse comprenait du code pour formater la chaîne utf8 à l'aide d'un gigantesque bloc de boîtier de commutation. Voici la méthode que j'utilise pour l'encodage en utf8, il devrait être capable de formater n'importe quel tableau d'octets utf8 valide.

Pour obtenir le tableau d'octets à partir d'une chaîne, utilisez Encoding.UTF8.GetBytes(content).

// From the wikipedia page on utf8 encoding - https://en.wikipedia.org/wiki/UTF-8
    private const int _Last1ByteCodePointByte1 = 0x7F;
    private const int _First2ByteCodePointByte1 = 0xC0;
    private const int _Last2ByteCodePointByte1 = 0xDF;
    private const int _Last3ByteCodePointByte1 = 0xEF;
    private const int _Last4ByteCodePointByte1 = 0xF7;
    private const int _FirstMultiByteCodePointByte2 = 0x80;
    private const int _LastMultiByteCodePointByte2 = 0xBF;
    private const char _ZplMultiByteEscapeCharacter = '_';

/// <summary>
/// Encodes a sequence of utf8 bytes for printing with the ZPL language, this means escaping multi-byte characters with an underscore ('_') followed by the hex code
/// for each byte in the multi-byte characters.
/// </summary>
/// <param name="utf8Bytes">The bytes that make up the entire string, including bytes that need to be encoded and bytes that can be printed as-is.</param>
/// <returns>A string for printing with the ZPL language. Ie all multi-byte characters escaped with an underscore ('_') followed by the hex code for each byte.</returns>
/// <throws><see cref="ArgumentException"/> when <paramref name="utf8Bytes"/> isn't a valid utf8 encoding of a string.</throws>
/// <remarks>
/// Plan is to figure out how many bytes this character (code point) takes up, and if it's a 1 byte character, just use the character, but otherwise since it's a multi-byte 
/// character then use an underscore ('_') followed by the hex encoded byte and each other byte in this code point will also be encoded. If we start the loop but have bytes 
/// remaining in the current code point we know to hex encode this byte and continue.
/// </remarks>
private static string EncodeUtf8BytesForZPLIIPrinting(byte[] utf8Bytes)
{
    var contentWithMultiByteCharsEscaped = new List<char>();

    var multiByteCodePoint = new List<char>();
    var remainingBytesInCurrentCodePoint = 0;
    string errorMessage = null;

    foreach (byte utf8Byte in utf8Bytes)
    {
        if (remainingBytesInCurrentCodePoint > 0)
        {
            if (utf8Byte < _FirstMultiByteCodePointByte2 || utf8Byte > _LastMultiByteCodePointByte2)
            {
                errorMessage = $"The byte {utf8Byte.ToString("X2")} is not a valid as the second or later byte of a multi-byte utf8 character (codepoint).";
                break;
            }

            multiByteCodePoint.Add(_ZplMultiByteEscapeCharacter);
            AddHexValuesToListFromByte(multiByteCodePoint, utf8Byte);
            remainingBytesInCurrentCodePoint--;
            continue; // continue since we've dealt with this byte and don't want to flow on.
        }

        if (multiByteCodePoint.Any())
        {
            foreach (char c in multiByteCodePoint) contentWithMultiByteCharsEscaped.Add(c);
            multiByteCodePoint.Clear();
            // flow on to loop to see what to do with the current byte.
        }

        if (utf8Byte <= _Last1ByteCodePointByte1)
        {
            // 1 byte - no escaping
            contentWithMultiByteCharsEscaped.Add((char)utf8Byte);
        }
        else if (utf8Byte >= _First2ByteCodePointByte1 && utf8Byte <= _Last2ByteCodePointByte1)
        {
            // 2 bytes
            multiByteCodePoint.Add(_ZplMultiByteEscapeCharacter);
            AddHexValuesToListFromByte(multiByteCodePoint, utf8Byte);
            remainingBytesInCurrentCodePoint = 1;
        }
        else if (utf8Byte <= _Last3ByteCodePointByte1)
        {
            // 3 bytes
            multiByteCodePoint.Add(_ZplMultiByteEscapeCharacter);
            AddHexValuesToListFromByte(multiByteCodePoint, utf8Byte);
            remainingBytesInCurrentCodePoint = 2;
        }
        else if (utf8Byte <= _Last4ByteCodePointByte1)
        {
            // 4 bytes
            multiByteCodePoint.Add(_ZplMultiByteEscapeCharacter);
            AddHexValuesToListFromByte(multiByteCodePoint, utf8Byte);
            remainingBytesInCurrentCodePoint = 3;
        }
        else
        {
            errorMessage = $"The byte {utf8Byte.ToString("X2")} is not a valid as the first byte of a utf8 character.";
            break;
        }
    }

    // if the last char was multiByte add it now.
    if (multiByteCodePoint.Any())
    {
        foreach (var c in multiByteCodePoint) contentWithMultiByteCharsEscaped.Add(c);
        multiByteCodePoint.Clear();
    }

    if (remainingBytesInCurrentCodePoint != 0 && errorMessage == null)
    {
        errorMessage = $"The last character didn't have enough bytes to finish the codepoint. It was a multi-byte character that needed {remainingBytesInCurrentCodePoint}" + 
            $" more byte{(remainingBytesInCurrentCodePoint == 1 ? null : "s")}.";
    }

    if (errorMessage != null)
    {
        throw new ArgumentException($"The byte array was not a valid byte array for a utf8 string: {errorMessage}", nameof(utf8Bytes));
    }

    return new string(contentWithMultiByteCharsEscaped.ToArray());


    void AddHexValuesToListFromByte(List<char> list, byte @byte)
    {
        // A byte is <= 255 so will always fit in a 2-digit hex number, hence the 2 in "X2". The X means hex.
        foreach (char c in @byte.ToString("X2"))
        {
            list.Add(c);
        }
    }
}
1
Dysnomian

Vous pouvez remplacer le caractère supérieur à un octet par une chaîne hexadécimale UTF-8 par un trait de soulignement comme "ћ => _D1_9B". Exemple de code ci-dessous;

 var zpl_code = "^XA" +
        "^LH100,150" +
        "^CWT,E:TT0003M_.FNT" +
        "^CFT,30,30" +
        "^CI28" +
        "^FT0,0^FDTesting 1 2 3^FS" +
        "^FT0,50^FDДо свидания^FS" +
        "^FT0,100^B3^FDAAA001^FS" +
        "^XZ";
        var unicodeCharacterList = zpl_code.Distinct()
            .Select(c => c.ToString())
            .Select(c => new { key = c, UTF8Bytes = Encoding.UTF8.GetBytes(c) })
            .Where(c => c.UTF8Bytes.Length > 1);

        foreach (var character in unicodeCharacterList)
        {
            var characterHexCode = string.Join("", character.UTF8Bytes.Select(c => "_" + BitConverter.ToString(new byte[] { c }).ToLower()).ToArray());

            zpl_code = zpl_code.Replace(character.key, characterHexCode);
        }

Ce code définit la variable zpl_code sur la sortie inférieure

^XA
^LH100,150
^CWT,E:TT0003M_.FNT
^CFT,30,30
^CI28
^FT0,0^FDTesting 1 2 3^FS
^FT0,50^FD_d0_94_d0_be _d1_81_d0_b2_d0_b8_d0_b4_d0_b0_d0_bd_d0_b8_d1_8f^FS
^FT0,100^B3^FDAAA001^FS
^XZ
1

Lorsque nous utilisons CP1251 comme codage système, cela provoque des symboles vides dans les étiquettes, si nous écrivons cyrillique en code ZPL. Les utilisateurs du CP1251 peuvent d'abord forcer la conversion de "До свидания" en UTF-8 et obtenir:

Р ”Рѕ СЃРІРёРґР ° РЅРёСЏ

Remplacez До свидания dans le code ZPL par ces symboles étranges et obtenez "До свидания" sur l'étiquette. Cela fonctionne avec tt0003m_.fnt avec ^ CI28, mais à mon humble avis, il est préférable d'utiliser des codes hexadécimaux à la place.

0
Igor Sheludko