c ++ - Er der fare for at arbejde internt i UTF-8 og derefter kun konvertere til UTF-16, når det er nødvendigt i Windows?

Indlæg af Hanne Mølgaard Plasc

Problem



Visual studio forsøger at insistere på at bruge tchars, som når de kompileres med UNICODE-indstillingen, ender i det væsentlige med at bruge de brede versioner af Windows og andre API'er.


Er der så fare for at bruge UTF-8 internt i applikationen (som gør brug af C ++ STL lettere og muliggør også mere læsbar krydsplatformkode) og derefter kun konvertere til UTF-16, når du skal bruge nogen af ​​OS API'erne ?


Jeg beder specifikt om at udvikle til mere end et OS - Windows, der ikke bruger UTF-8 og andre som Mac, det gør det.

Bedste reference


Som andre har sagt, er der ingen fare for at bruge UTF-8 internt, og derefter konvertere, når du skal ringe til Windows-funktioner.


Men vær opmærksom på, at omkostningerne ved konvertering hver gang kan blive uforholdsmæssigt dyre, hvis du viser meget tekst. (Husk, at du ikke har konverteringen, men du kan også have omkostningerne ved at allokere og frigøre buffere at holde de midlertidige konverterede strenge.)


Jeg skal også påpege, at der er indbygget bredtekst støtte indbygget i STL, så der er virkelig ingen grund til at gøre dette. (Std :: wstring, et al.)


Derudover er det kun engelsk, der arbejder med UTF-8, men hvis du planlægger at understøtte osteuropæisk, arabisk eller asiatisk tegnsæt, kan dine opbevaringskrav til tekst vise sig at være større end de for UTF-16 (på grund af flere tegn kræver tre eller fire kodepunkter, der skal opbevares). Igen vil det nok kun være et problem, hvis du beskæftiger dig med store mængder tekst, men det er noget at overveje - dobbelt så, hvis du vil overføre denne tekst over en netværksforbindelse til enhver tid.

Andre referencer 1


Da UTF-8 og UTF-16 kun er to måder at kode nummerer på (som så fortolkes som såkaldte kodepunkter eller glyfer), er der intet galt med at konvertere frem og tilbage: ingen information går tabt. Så nej, der er ingen fare for at konvertere (så længe konverteringen er korrekt, selvfølgelig).

Andre referencer 2


Hvis du har et operativsystem, der bruger wid (er) tegn i dets API, og du skriver et program, der kræver internationalisering, er det helt dumt at bruge char og UTF-8 som en intern repræsentation i dit program. Du ' genbruge UTF-8 baglæns. UTF-8 er til at smugle Unicode via operativsystemets grænseflader og lagrings- og dataudvekslingsformater, der ikke direkte kan håndtere brede tegn.

Andre referencer 3


Jeg antager, at dit projekt ikke handler om tekstbehandling, manipulation eller transformation: For tekstbehandling er det langt lettere at vælge en og kun en kodning, det samme på alle platforme, og derefter foretage konverteringen, hvis det er nødvendigt, når du bruger den native API .


Men hvis dit projekt ikke er centreret omkring tekstbehandling/manipulation/transformation, er begrænsningen til UTF-8 på alle platforme ikke den enkleste løsning.


Undgå at bruge char på Windows



Hvis du arbejder med char typen på Windows-udvikling, vil alle WinAPI bruge char.


Problemet er, at typen char på Windows bruges til 'historiske' applikationer, hvilket betyder før-unicode-applikation.


Hver char tekst fortolkes som en ikke-Unicode-tekst, hvis kodning/charset er valgt af Windows-brugeren, ikke du udvikleren .


Betydning: Hvis du mener at du arbejder med UTF-8, skal du sende den UTF-8 char -teksten til WinAPI til output på GUI (og TextBox osv.) Og derefter udføre din kode på en Windows-opsætning på arabisk (for eksempel), så vil du se din smukke UTF-8 kartekst vil blive behandlet korrekt af WinAPI, fordi WinAPI på den Windows mener, at alle char skal fortolkes som Windows-1256 kodning. [24]


Hvis du arbejder med char på Windows, forkaster du Unicode medmindre hvert opkald til WinAPI går gennem en oversættelse (normalt via en ramme som GTK + , QT osv., Men det kan være dine egne wrapperfunktioner).


Optimering er roten til alle onde, men så synes jeg at være helt ubrugelig pessimisering at konvertere alle dine UTF-8 tekster fra og til UTF-16 hver gang du diskuterer med Windows.


Alternativ: Hvorfor bruger du ikke TCHAR på alle platforme?



Hvad du skal gøre, er at arbejde med TCHAR, give et overskrift svarende til tchar.h til Linux/MacOS/Hvad endda (omklare makroerne osv. I den oprindelige tchar.h header) en tchar.h - lignende overskrift for de Standardbibliotek objekter, du vil bruge. For eksempel går min egen tstring.hpp som:


// tstring.hpp
#include <string>
#include <sstream>
#include <fstream>
#include <iostream>

#ifdef \_MSC\_VER
#include <tchar.h>
#include <windows.h>
#else
#ifdef \_\_GNUC\_\_
#include <MyProject/tchar\_linux.h>
#endif // \_\_GNUC\_\_
#endif


namespace std
{

#ifdef \_MSC\_VER

   // On Windows, the exact type of TCHAR depends on the UNICODE and
   // \_UNICODE macros. So the following is useful to complete the
   // tchar.h headers with the C++ Standard Library's symbols.

   #ifdef UNICODE

      typedef              wstring        tstring ;
      // etc.
      static wostream &    tcout          = wcout ;

   #else // #ifdef UNICODE

      typedef              string         tstring ;
      // etc.
      static ostream &     tcout          = cout ;

   #endif // #ifdef UNICODE

#else // #ifdef \_MSC\_VER

    #ifdef \_\_GNUC\_\_

    // On Linux, char is expected to be UTF-8 encoded, so the
    // following simply maps the txxxxx type into the xxxxx
    // type, forwaking the wxxxxx altogether.
    // Of course, your mileage will vary, but the basic idea is
    // there.

    typedef                string         tstring ;
    // etc.
    static ostream &       tcout          = cout ;

    #endif // \_\_GNUC\_\_

#endif // #ifdef \_MSC\_VER

} // namespace std


Discplaimer: Jeg ved, det er ondt at erklære ting i std, men jeg havde andre ting at gøre end at være pedantisk om det pågældende emne.


Brug af disse overskrifter kan du bruge C ++ Standard Library kombineret med TCHAR anlægget, det vil sige bruge std::tstring, som vil blive udarbejdet som std::wstring på Windows (forudsat at du kompilerer definerer [[UNICODE og \_UNICODE definerer) og som std::string på de andre char -baserede operativsystemer, du vil støtte.


Således kan du bruge platformens indbyggede tegntype uden omkostninger.


Så længe du er agnostisk med din TCHAR karaktertype, vil der ikke være noget problem.


Og i de tilfælde, du virkelig ønsker at håndtere den beskidte side af UTF-8 vs UTF-16, skal du give koden til konvertering (hvis det er nødvendigt) osv.


Dette gøres normalt ved at give overbelastninger af samme funktion til forskellige typer og for hvert OS. På den måde vælges den rigtige funktion på kompileringstidspunktet.

Andre referencer 4


Faren er, at UTF-8 karaktertælling ikke er det samme som ASCII karaktertælling. E.g., U + 24B62 er et enkelt Unicode-tegn, men udvider til 4 UTF-8 byte. (Se her for andre eksempler.) [25]


Hvis du ikke bruger de to interchangeably, vil du være i orden.

Andre referencer 5


UTF-8 er en vild og skør måde at repræsentere tegn på. Du bør undgå at bruge det, hvor det er muligt. Windows API undgår UTF-8. (Hvis du insisterer på en 'multibyte' -konstruktion, snarere end en 'unicode' -bygning, vil den gøre alle konverteringer til dig under dækslerne, så det kan fortsætte med at bruge UTF16 - og hvis du ikke er forsigtig med ineffektiviteten af ​​alle dem skjulte konverteringer spiser dig op.) Biblioteket wxWidgets undgår UTF-8 på samme måde, og det er cross-platform med MAC'er.


Du bør tage et tip fra dette, og undgå selv UTF-8.


Hvornår skal du bruge UTF-8? Snag med UTF16 er, at det afhænger af byte ordren i ordene implementeret i hardware. Så når du overfører data mellem forskellige computere, som måske bruger en anden byteordre i deres hardware, skal du bruge UTF8, som har samme byteordre på hardware. Derfor bruger browsere og WWW-sider UTF8.

Andre referencer 6


Nej, der er ingen farer, hvis du følger retningslinjerne.
// tstring.hpp
#include <string>
#include <sstream>
#include <fstream>
#include <iostream>

#ifdef \_MSC\_VER
#include <tchar.h>
#include <windows.h>
#else
#ifdef \_\_GNUC\_\_
#include <MyProject/tchar\_linux.h>
#endif // \_\_GNUC\_\_
#endif


namespace std
{

#ifdef \_MSC\_VER

   // On Windows, the exact type of TCHAR depends on the UNICODE and
   // \_UNICODE macros. So the following is useful to complete the
   // tchar.h headers with the C++ Standard Library's symbols.

   #ifdef UNICODE

      typedef              wstring        tstring ;
      // etc.
      static wostream &    tcout          = wcout ;

   #else // #ifdef UNICODE

      typedef              string         tstring ;
      // etc.
      static ostream &     tcout          = cout ;

   #endif // #ifdef UNICODE

#else // #ifdef \_MSC\_VER

    #ifdef \_\_GNUC\_\_

    // On Linux, char is expected to be UTF-8 encoded, so the
    // following simply maps the txxxxx type into the xxxxx
    // type, forwaking the wxxxxx altogether.
    // Of course, your mileage will vary, but the basic idea is
    // there.

    typedef                string         tstring ;
    // etc.
    static ostream &       tcout          = cout ;

    #endif // \_\_GNUC\_\_

#endif // #ifdef \_MSC\_VER

} // namespace std
Det er faktisk den reneste og enkleste måde at gå på char , selvom du skriver for Kun Windows . [26] [27]


Og bemærk at UTF-8 er aldrig længere end UTF-16 for europæiske sprog eller ikke for BMP-tegn. Det kræver mere plads kun for kodepunkter kodet med 3 byte i UTF-8 og 2 i UTF-16, hvilket er netop U + 0800 til U + FFFF-området, char , som for det meste er CJK-tegn . [28]