Comentários
- Não é realmente correto. Eu explico, se você escrever " שָׁ " o caractere composto que consiste em " ש ", " ָ " e " ׁ ", vovels, então a remoção de cada um deles é lógico, você remove um ponto de código ao pressionar " backspace " e remova todos os caracteres, incluindo vovels, ao pressionar " del ". Mas, você nunca produz um estado de texto ilegal – pontos de código ilegais. Portanto, a situação quando você pressiona backspace e obtém texto ilegado está incorreta.
- CiscoIPPhone: se um bug for " relatado várias vezes, por muitas pessoas diferentes " e, alguns anos depois, um desenvolvedor escreve em um blog de desenvolvimento que " Acredite ou não, o comportamento é principalmente intencional! ", então (para dizer o mínimo) eu tendo a pensar que ' provavelmente não é a melhor decisão de design já feita. 🙂 Só porque ' é intencional, não ' significa que ' não um bug.
- Excelente postagem. UTF-16 é de fato o " pior dos dois mundos ": UTF8 tem comprimento variável, cobre todo Unicode, requer um algoritmo de transformação de e para pontos de código brutos, restringe-se a ASCII e não tem problemas de endianness. UTF32 tem comprimento fixo, não requer transformação, mas ocupa mais espaço e tem problemas de endianismo. Até aqui tudo bem, você pode usar UTF32 internamente e UTF8 para serialização. Mas UTF16 não tem benefícios: é ' dependente de endian, tem ' tem comprimento variável, ocupa muito espaço, é ' s não compatível com ASCII. O esforço necessário para lidar com o UTF16 de maneira adequada poderia ser melhor gasto no UTF8.
- @Ian: UTF-8 NÃO tem as mesmas ressalvas que o UTF-8. Você não pode ter substitutos em UTF-8. UTF-8 não se disfarça como algo que não é, mas a maioria dos programadores que usam UTF-16 está usando errado. Eu sei. Eu ' já os assisti várias vezes.
- Além disso, UTF-8 não ' t tem o problema porque todo mundo o trata como uma codificação de largura variável. O motivo do UTF-16 ter o problema é porque todos o tratam como uma codificação de largura fixa.
Resposta
Esta é uma resposta antiga.
Veja UTF-8 Everywhere para as últimas atualizações.
Opinião: Sim, o UTF-16 deve ser considerado prejudicial . A própria razão de existir é porque há algum tempo havia uma crença equivocada de que widechar será o que o UCS-4 agora é.
Apesar do “anglo-centrismo” do UTF-8, ele deve ser considerada a única codificação útil para texto. Pode-se argumentar que os códigos-fonte de programas, páginas da web e arquivos XML, nomes de arquivos do sistema operacional e outras interfaces de texto de computador para computador nunca deveriam ter existido. Mas quando o fazem, o texto não é apenas para leitores humanos.
Por outro lado, a sobrecarga de UTF-8 é um pequeno preço a pagar, embora tenha vantagens significativas. Vantagens como compatibilidade com código desconhecido que apenas passa strings com char*
. Isso é ótimo. Existem poucos caracteres úteis que são MAIS CURTOS em UTF-16 do que em UTF-8.
Eu acredito que todas as outras codificações morrerão eventualmente. Isso envolve MS-Windows, Java, ICU, python pare de usá-lo como favorito. Após longas pesquisas e discussões, as convenções de desenvolvimento em minha empresa proíbem o uso de UTF-16 em qualquer lugar, exceto em chamadas de API do sistema operacional, e isso apesar da importância de desempenho em nossos aplicativos e o fato de usarmos o Windows. As funções de conversão foram desenvolvidas para converter sempre UTF8 std::string
s em UTF-16 nativo, que o próprio Windows não oferece suporte adequadamente .
Para as pessoas que dizem “ use o que for necessário onde for necessário “, eu digo: há “uma grande vantagem em usar a mesma codificação em todos os lugares, e não vejo razão suficiente para faça o contrário. Em particular, acho que adicionar wchar_t
a C ++ foi um erro, assim como as adições Unicode a C ++ 0x. O que deve ser exigido das implementações STL é que todos std::string
ou char*
parâmetro seria considerado compatível com Unicode.
Também sou contra o “ uso abordagem do que você deseja “. Não vejo razão para tal liberdade. Já existe confusão suficiente sobre o assunto do texto, resultando em todo esse software corrompido. Tendo dito acima, estou convencido de que os programadores devem finalmente chegar a um consenso sobre o UTF-8 como uma forma adequada. (Eu venho de um país sem língua ascii e cresci no Windows, então era esperado que eu atacasse o UTF-16 com base em motivos religiosos).
Eu gostaria de compartilhar mais informações sobre como eu faço texto no Windows, e o que eu recomendo para todos os outros para correção unicode verificada em tempo de compilação, facilidade de uso e melhor multi-plataforma do código. A sugestão difere substancialmente do que normalmente é recomendado como a maneira adequada de usar Unicode no Windows. Ainda assim, uma pesquisa aprofundada dessas recomendações resultou na mesma conclusão. Então aqui vai:
- Não use
wchar_t
oustd::wstring
em qualquer lugar que não seja o ponto adjacente APIs que aceitam UTF-16. - Não use
_T("")
ouL""
literais UTF-16 (estes devem IMO ser retirados do padrão , como parte da descontinuação do UTF-16). - Não use tipos, funções ou seus derivados que sejam sensíveis à constante
_UNICODE
, comoLPTSTR
ouCreateWindow()
. - Ainda,
_UNICODE
sempre definido, para evite passarchar*
strings para WinAPI sendo compilada silenciosamente -
std::strings
echar*
em qualquer lugar no programa são considerados UTF-8 (se não for dito o contrário) - Todas as minhas strings são
std::string
, embora você possa passar char * ou literal de string paraconvert(const std::string &)
. -
use apenas funções Win32 que aceitem widechars (
LPWSTR
). Nunca aqueles que aceitamLPTSTR
ouLPSTR
. Passe os parâmetros desta forma:::SetWindowTextW(Utils::convert(someStdString or "string litteral").c_str())
(A política usa as funções de conversão abaixo.)
-
Com strings MFC :
CString someoneElse; // something that arrived from MFC. Converted as soon as possible, before passing any further away from the API call: std::string s = str(boost::format("Hello %s\n") % Convert(someoneElse)); AfxMessageBox(MfcUtils::Convert(s), _T("Error"), MB_OK);
-
Trabalhando com arquivos, nomes de arquivos e fstream no Windows:
- Nunca passa
std::string
ouconst char*
argumentos de nome de arquivo para a famíliafstream
. MSVC STL não suporta argumentos UTF-8, mas tem uma extensão não padrão que deve ser usada da seguinte forma: -
Converta
std::string
argumentos parastd::wstring
comUtils::Convert
:std::ifstream ifs(Utils::Convert("hello"), std::ios_base::in | std::ios_base::binary);
Teremos que manualmente remover o convertido, quando a atitude do MSVC em relação a
fstream
mudar. - Este código não é multiplataforma e pode ter que ser alterado manualmente em o futuro
- Consulte
fstream
caso de pesquisa / discussão unicode 4215 para obter mais informações. - Nunca produza arquivos de saída de texto com conteúdo não UTF8
- Evite usar
fopen()
por motivos RAII / OOD. Se necessário, use as convenções_wfopen()
e WinAPI acima.
- Nunca passa
// For interface to win32 API functions std::string convert(const std::wstring& str, unsigned int codePage /*= CP_UTF8*/) { // Ask me for implementation.. ... } std::wstring convert(const std::string& str, unsigned int codePage /*= CP_UTF8*/) { // Ask me for implementation.. ... } // Interface to MFC std::string convert(const CString &mfcString) { #ifdef UNICODE return Utils::convert(std::wstring(mfcString.GetString())); #else return mfcString.GetString(); // This branch is deprecated. #endif } CString convert(const std::string &s) { #ifdef UNICODE return CString(Utils::convert(s).c_str()); #else Exceptions::Assert(false, "Unicode policy violation. See W569"); // This branch is deprecated as it does not support unicode return s.c_str(); #endif }
Comentários
- Não posso ' concordar. As vantagens do utf16 em relação ao utf8 para muitos idiomas asiáticos dominam completamente os seus pontos. É ingênuo esperar que japoneses, tailandeses, chineses, etc. desistam dessa codificação. Os confrontos problemáticos entre conjuntos de caracteres ocorrem quando os conjuntos de caracteres geralmente parecem semelhantes, exceto com diferenças. Eu sugiro padronizar em: 7 bits fixos: iso-irv-170; Variável de 8 bits: utf8; Variável de 16 bits: utf16; 32 bits corrigidos: ucs4.
- @Charles: obrigado por sua contribuição. É verdade que alguns caracteres BMP são mais longos em UTF-8 do que em UTF-16. Mas, vamos ' s enfrentá-lo: o problema não está nos bytes que os caracteres BMP chineses ocupam, mas na complexidade do design de software que surge. Se um programador chinês precisa projetar para caracteres de comprimento variável de qualquer maneira, parece que UTF-8 ainda é um preço pequeno a pagar em comparação com outras variáveis no sistema. Ele pode usar UTF-16 como algoritmo de compressão se o espaço for tão importante, mas mesmo assim não será páreo para LZ, e depois de LZ ou outra compressão genérica, ambos assumem aproximadamente o mesmo tamanho e entropia.
- O que eu basicamente digo é que a simplificação oferecida por ter uma codificação que também é compatível com os programas char * existentes, e também é a mais popular hoje, pois tudo é inimaginável.É quase como nos bons e velhos " texto simples " dias. Quer abrir um arquivo com um nome? Não há necessidade de se preocupar com o tipo de Unicode que você está fazendo, etc. etc. Eu sugiro que nós, desenvolvedores, confinemos o UTF-16 a casos muito especiais de otimização severa onde um mínimo de desempenho vale homem-mês de trabalho.
- O Linux teve um requisito específico ao escolher usar UTF-8 internamente: compatibilidade com Unix. O Windows não ' não precisava disso e, portanto, quando os desenvolvedores implementaram o Unicode, eles adicionaram versões UCS-2 de quase todas as funções que tratam de texto e fizeram as multibyte simplesmente converterem para UCS-2 ligue para os outros. Posteriormente, eles substituem o UCS-2 pelo UTF-16. O Linux, por outro lado, manteve as codificações de 8 bits e, portanto, usou UTF-8, uma vez que ' é a escolha adequada nesse caso.
- @Pavel Radzivilovsky : BTW, seus escritos sobre " Eu acredito que todas as outras codificações morrerão eventualmente. Isso envolve que MS-Windows, Java, ICU, python parem de usá-lo como favorito. " e " Em particular, acho que adicionar wchar_t ao C ++ foi um erro, assim como as adições unicode ao C ++ Ox. " são bastante ingênuos ou muito arrogantes . E isso está vindo de alguém que está programando em casa com um Linux e que está feliz com os chars UTF-8. Para ser franco: Não ' acontecerá .
Resposta
Os pontos de código Unicode não são caracteres! Às vezes, nem mesmo são glifos (formas visuais) .
Alguns exemplos:
- pontos de código em algarismos romanos como “ⅲ”. (Um único caractere que se parece com “iii”.)
- Caracteres acentuados como “á”, que podem ser representados como um único caractere combinado “\ u00e1” ou um caractere e diacrítico separado “\ u0061 \ u0301 “.
- Caracteres como sigma em letras minúsculas do grego, que têm formas diferentes para posições intermediárias (” σ “) e finais (” ς “) de palavras, mas que devem ser considerados sinônimos para pesquisa.
- Hífen discricionário Unicode U + 00AD, que pode ou não ser exibido visualmente, dependendo do contexto, e que é ignorado para pesquisa semântica.
As únicas maneiras de obter edição Unicode certo é usar uma biblioteca escrita por um especialista ou se tornar um especialista e escrever uma você mesmo. Se você está apenas contando pontos de código, está vivendo em um estado de pecado.
Comentários
- Isso. Muito isso. O UTF-16 pode causar problemas, mas mesmo o uso do UTF-32 pode (e irá) causar problemas.
- O que é um personagem? Você pode definir um ponto de código como um caractere e se sair muito bem. Se você quer dizer um glifo visível ao usuário, isso é outra coisa.
- @tchrist com certeza para alocar espaço, essa definição está bem, mas para mais alguma coisa? Não muito. Se você manipular um caractere de combinação como um único caractere (ou seja, para excluir ou " tomar os primeiros N caracteres " operação), você ' terei um comportamento estranho e errado. Se um ponto de código só tem significado quando combinado com pelo menos outro, você pode ' não manipulá-lo sozinho de qualquer maneira sensata.
- @Pacerier, isso é atrasado para a festa, mas tenho que comentar sobre isso. Algumas línguas têm conjuntos muito grandes de combinações potenciais de diacríticos (c.f. vietnamita, ou seja, mệt đừ). Ter combinações em vez de um caractere por diacrítico é muito útil.
- uma pequena nota sobre a terminologia: pontos de código correspondem a caracteres Unicode ; Daniel está falando aqui são caracteres percebidos pelo usuário , que correspondem a grupos de grafemas unicode
Resposta
Existe uma regra simples sobre qual Unicode Transformation Form (UTF) usar: – utf-8 para armazenamento e comunicação – utf-16 para processamento de dados – você pode ir com utf-32 se a maior parte da API da plataforma que você usa for utf-32 (comum no mundo UNIX).
A maioria dos sistemas hoje usa utf-16 (Windows, Mac OS, Java, .NET, ICU , Qt). Veja também este documento: http://unicode.org/notes/tn12/
Voltar para “UTF-16 como prejudicial”, Eu diria: definitivamente não.
Pessoas que têm medo de substitutos (pensando que eles transformam Unicode em uma codificação de comprimento variável) não entendem as outras complexidades (muito maiores) que tornam o mapeamento entre caracteres e um ponto de código Unicode muito complexo: combinação de caracteres, ligaduras, seletores de variação, caracteres de controle, etc.
Basta ler esta série aqui http://www.siao2.com/2009/06/29/9800913.aspx e veja como o UTF-16 se torna um problema fácil.
Comentários
- Por favor, adicione alguns exemplos onde UTF-32 é comum no mundo UNIX!
- Não, você não deseja usar UTF-16 para processamento de dados. É ' é um pé no saco. Ele tem todas as desvantagens do UTF-8, mas nenhuma de suas vantagens. Ambos UTF-8 e UTF-32 são claramente superiores ao hack vicioso anteriormente conhecido como Mrs UTF-16, cujo nome de solteira era UCS-2.
- Ontem encontrei um bug na classe String principal do Java
equalsIgnoreCase
método (também outros na classe string) que nunca existiria se o Java tivesse usado UTF-8 ou UTF-32. Existem milhões dessas bombas adormecidas em qualquer código que usa UTF-16, e estou farto delas. O UTF-16 é uma varíola que assola nosso software com bugs insidiosos para todo o sempre. É claramente prejudicial e deve ser descontinuado e banido. - @tchrist Wow, portanto, uma função não substituta ciente (porque foi escrita quando não havia nenhuma e, infelizmente, está documentada de uma forma que provavelmente a torna impossível de se adaptar – especifica .toUpperCase (char)) resultará no comportamento errado? Você ' está ciente de que uma função UTF-32 com um mapa de pontos de código desatualizado não ' lidaria com isso melhor? Além disso, toda a API Java lida com substitutos não muito bem e os pontos mais intrincados sobre Unicode nem um pouco – e com o posterior, a codificação usada não ' teria qualquer importância.
- -1: Um
.Substring(1)
incondicional em .NET é um exemplo trivial de algo que quebra o suporte para todos os Unicode não BMP. Tudo que usa UTF-16 tem esse problema; é ' muito fácil tratá-lo como uma codificação de largura fixa e você vê problemas muito raramente. Isso a torna uma codificação ativamente prejudicial se você deseja oferecer suporte a Unicode.
Resposta
Sim, absolutamente.
Por quê? Tem a ver com exercitar o código .
Se você olhar para estas estatísticas de uso do codepoint em um grande corpo por Tom Christiansen, você verá que os pontos de código BMP trans-8 bits são usados em várias ordens se a magnitude for maior que os pontos de código não BMP:
2663710 U+002013 ‹–› GC=Pd EN DASH 1065594 U+0000A0 ‹ › GC=Zs NO-BREAK SPACE 1009762 U+0000B1 ‹±› GC=Sm PLUS-MINUS SIGN 784139 U+002212 ‹−› GC=Sm MINUS SIGN 602377 U+002003 ‹ › GC=Zs EM SPACE 544 U+01D49E ‹𝒞› GC=Lu MATHEMATICAL SCRIPT CAPITAL C 450 U+01D4AF ‹𝒯› GC=Lu MATHEMATICAL SCRIPT CAPITAL T 385 U+01D4AE ‹𝒮› GC=Lu MATHEMATICAL SCRIPT CAPITAL S 292 U+01D49F ‹𝒟› GC=Lu MATHEMATICAL SCRIPT CAPITAL D 285 U+01D4B3 ‹𝒳› GC=Lu MATHEMATICAL SCRIPT CAPITAL X
Siga o ditado TDD: “Código não testado é código quebrado” e reformule-o como “código não exercido é código quebrado” e pense na frequência com que os programadores precisam lidar com pontos de código não BMP.
Erros relacionados a não lidar com UTF-16 como uma codificação de largura variável têm muito mais probabilidade de passar despercebidos do que os erros equivalentes em UTF-8 . Algumas linguagens de programação ainda não garanta o fornecimento de UTF-16 em vez de UCS-2, e algumas das chamadas linguagens de programação de alto nível oferecem acesso a unidades de código em vez de pontos de código (até mesmo C deve fornecer acesso a pontos de código se você usar wchar_t
, independentemente do que alguns formulários podem servir).
Comentários
- " Bugs relacionados ao não tratamento de UTF-16 como uma codificação de largura variável tem muito mais probabilidade de passar despercebida do que os bugs equivalentes em UTF-8. " Este é o cerne do problema e, portanto, a resposta correta.
- Precisamente. Se o seu tratamento UTF-8 estiver bloqueado, ' será imediatamente óbvio. Se o seu tratamento UTF-8 for bloqueado, você ' só notará se inserir caracteres Han incomuns ou símbolos matemáticos.
- Muito verdadeiro, mas por outro lado Por outro lado, para que servem os testes de unidade se depender da sorte para encontrar bugs em casos menos frequentes?
- @musiphil: então, quando foi a última vez que você criou um teste de unidade para caracteres não BMP?
- Para desenvolver minha declaração anterior: mesmo com UTF-8, você não pode ter certeza de que cobriu todos os casos depois de ver apenas alguns exemplos funcionais. O mesmo com UTF-16: você precisa testar se o seu código funciona tanto com substitutos quanto com substitutos. (Alguém poderia até argumentar que UTF-8 tem pelo menos quatro casos principais, enquanto UTF-16 tem apenas dois.)
Resposta
Eu sugeriria que pensar que UTF-16 pode ser considerado prejudicial diz que você precisa obter maior compreensão de Unicode .
Já que fui reprovado por apresentar minha opinião sobre uma questão subjetiva, deixe-me explicar. O que exatamente o incomoda no UTF-16? Você prefere que tudo esteja codificado em UTF-8? UTF-7? Ou E o UCS-4? Claro que certos aplicativos não são projetados para lidar com cada código de caractere único por aí – mas eles são necessários, especialmente no domínio de informação global de hoje, para comunicação entre fronteiras internacionais.
Mas, realmente, se você acha que o UTF-16 deve ser considerado prejudicial porque é confuso ou pode ser implementado incorretamente (Unicode certamente pode ser), então qual método de codificação de caracteres seria considerado não prejudicial?
EDITAR: Para esclarecer: Por que considerar implementações impróprias de um padrão um reflexo da qualidade do próprio padrão? Como outros notaram posteriormente, apenas porque um aplicativo usa uma ferramenta inadequadamente, não significa que a ferramenta em si está com defeito. Se fosse esse o caso, provavelmente poderíamos dizer coisas como “var palavra-chave considerada prejudicial” ou “threading considerada prejudicial”. Acho que a pergunta confunde a qualidade e a natureza do padrão com as dificuldades que muitos programadores têm para implementar e usá-lo corretamente, o que eu acho que decorre mais da falta de compreensão de como o Unicode funciona, do que do próprio Unicode.
Comentários
- -1: Que tal abordar alguns dos ' objetivos de Artyom ons, em vez de apenas tratá-lo com condescendência?
- BTW: Quando comecei a escrever este artigo, quase quis escrever " O artigo do Joel on Softeare de Unicode deve ser considerado prejudicial " porque existem muitos erros. Por exemplo: a codificação utf-8 leva até 4 caracteres e não 6. Também não faz distinção entre UCS-2 e UTF-16 que são realmente diferentes – e realmente causam os problemas de que falo.
- Além disso, deve-se notar que quando Joel escreveu aquele artigo, o padrão UTF-8 era 6 bytes, não 4. RFC 3629 mudou o padrão para 4 bytes vários meses DEPOIS de ele ter escrito o artigo. Como quase tudo na Internet, vale a pena ler em mais de uma fonte e estar ciente da idade de suas fontes. O link não era ' t pretendia ser o " fim ser tudo ", mas em vez de um ponto de partida.
- Eu imagino: utf-8 ou utf-32 que são: codificação de comprimento variável em quase todos os casos (incluindo BMP) ou codificação de comprimento fixo sempre.
- @iconiK: Não seja bobo. UTF-16 não é absolutamente o padrão de facto para processamento de texto. Mostre-me uma linguagem de programação mais adequada para processamento de texto do que Perl, que sempre (bem, por mais de uma década) usou caracteres abstratos com uma representação UTF-8 subjacente internamente. Por causa disso, todo programa Perl lida automaticamente com todos os Unicode sem que o usuário tenha que ficar mexendo constantemente com substitutos idiotas. O comprimento de uma string é sua contagem em pontos de código, não em unidades de código. Qualquer outra coisa é pura estupidez colocando o reverso em compatibilidade com versões anteriores.
Resposta
Não há nada de errado com Utf- 16 codificação. Mas as linguagens que tratam as unidades de 16 bits como caracteres provavelmente devem ser consideradas mal projetadas. Ter um tipo chamado “char
” que nem sempre representa um caractere é muito confuso. Uma vez que a maioria dos desenvolvedores espera que um tipo de char represente um ponto de código ou caractere, muito código provavelmente será quebrado quando exposto a caracteres além do BMP.
Observe, entretanto, que mesmo usando utf-32 não significa que cada 32- o ponto de código de bit sempre representará um caractere. Devido à combinação de caracteres, um caractere real pode consistir em vários pontos de código. Unicode nunca é trivial.
A propósito. Provavelmente existe a mesma classe de bugs com plataformas e aplicativos que esperam que os caracteres sejam de 8 bits, que são alimentados com Utf-8.
Comentários
- No caso ' do Java, se você olhar sua linha do tempo ( java.com/en/javahistory/timeline.jsp), você vê que o desenvolvimento principal de String aconteceu enquanto o Unicode tinha 16 bits (mudou em 1996). Eles tiveram que se agarrar à capacidade de lidar com pontos de código não BMP, daí a confusão.
- @Kathy: No entanto, não é exatamente uma desculpa para C #. Geralmente, eu concordo que deve haver um tipo
CodePoint
, mantendo um único ponto de código (21 bits), um tipoCodeUnit
, segurando uma única unidade de código (16 bits para UTF-16) e um tipoCharacter
teria idealmente que suportar um grafema completo. Mas isso a torna funcionalmente equivalente aString
… - Essa resposta tem quase dois anos, mas posso ' t ajudar, mas comentar sobre isso. " Ter um tipo chamado ' char ' que nem sempre representa um personagem é bonito confuso. " E ainda assim as pessoas usam isso o tempo todo em C e similares para representar dados inteiros que podem ser armazenados em um único byte.
- E eu ' vi um lote de código C que não ' lida com a codificação de caracteres corretamente.
- C # tem uma desculpa diferente: ele foi projetado para Windows, e o Windows foi construído em UCS-2 (é ' muito chato que até hoje as APIs do Windows não suporte UTF-8). Além disso, acho que a Microsoft queria compatibilidade com o Java (o .NET 1.0 tinha uma biblioteca de compatibilidade com o Java, mas eles abandonaram o suporte ao Java muito rapidamente – eu ' estou supondo que isso se deve à Sun ' s processo contra a MS?)
Resposta
Minha escolha pessoal é para sempre usar UTF-8. É o padrão no Linux para quase tudo. É compatível com versões anteriores de muitos aplicativos legados. Há uma sobrecarga mínima em termos de espaço extra usado para caracteres não latinos em comparação a outros formatos UTF, e há uma economia significativa de espaço para caracteres latinos. Na web, as línguas latinas reinam supremas, e acho que o farão em um futuro próximo. E para abordar um dos principais argumentos na postagem original: quase todo programador está ciente de que UTF-8 às vezes terá caracteres de vários bytes nele. Nem todos lidam com isso corretamente, mas geralmente estão cientes, o que é mais do que pode ser dito sobre o UTF-16. Mas, é claro, você precisa escolher o mais adequado para sua aplicação. É por isso que há mais de um em primeiro lugar.
Comentários
- UTF-16 é mais simples para qualquer coisa dentro do BMP, que ' s porque é tão amplamente usado. Mas eu ' sou um fã de UTF-8 também, ele também não tem problemas com a ordem de bytes, o que funciona a seu favor.
- Teoricamente, sim. Na prática, existem coisas como, digamos, UTF-16BE, que significa UTF-16 em big endian sem BOM. Isso não é algo que eu inventei, é uma codificação real permitida em tags ID3v2.4 (tags ID3v2 são uma porcaria, mas são, infelizmente, amplamente utilizadas). E, nesses casos, você deve definir o endianismo externamente, porque o próprio texto não ' contém BOM. UTF-8 é sempre escrito de uma forma e não ' tem esse problema.
- Não, UTF-16 não é mais simples. É mais difícil. Ele engana e faz você pensar que tem largura fixa. Todo esse código está quebrado e ainda mais porque você não percebe até que seja tarde demais. CASO EM PONTO: Acabei de encontrar outro bug UTF-16 estúpido nas bibliotecas principais do Java ontem, desta vez em String.equalsIgnoreCase, que foi deixado no UCS-2 braindeath buggery, e então falha em 16/17 pontos de código Unicode válidos. Há quanto tempo esse código existe? Não há desculpa para ser bugado. UTF-16 leva à estupidez absoluta e um acidente esperando para acontecer. Execute screaming de UTF-16.
- @tchrist É preciso ser um desenvolvedor muito ignorante para não saber que UTF-16 não tem comprimento fixo. Se você começar com a Wikipedia, você lerá o seguinte no topo: " Produz um resultado de comprimento variável de uma ou duas unidades de código de 16 bits por ponto de código ". As perguntas frequentes sobre Unicode dizem o mesmo: unicode.org/faq//utf_bom.html#utf16-1 . Eu não ' não sei como o UTF-16 pode enganar alguém se estiver escrito em todos os lugares que tem comprimento variável. Quanto ao método, ele nunca foi projetado para UTF-16 e não deve ' ser considerado Unicode, tão simples quanto isso.
- @tchrist Você tem um fonte para suas estatísticas? Embora sejam poucos os bons programadores, acho que isso é bom, porque nos tornamos mais valiosos. 🙂 Quanto às APIs Java, as partes baseadas em char podem eventualmente ficar obsoletas, mas isso não é uma garantia de que não serão ' usadas. E eles definitivamente ' não serão removidos por motivos de compatibilidade.
Resposta
Bem, existe uma codificação que usa símbolos de tamanho fixo. Certamente quero dizer UTF-32. Mas 4 bytes para cada símbolo é muito muito espaço desperdiçado, por que usaríamos isso em situações cotidianas?
Na minha opinião, a maioria dos problemas surge do fato de que algum software caiu atrás do padrão Unicode, mas não foram rápidos em corrigir a situação. Opera, Windows, Python, Qt – todos eles surgiram antes que o UTF-16 se tornasse amplamente conhecido ou mesmo viesse a existir. Posso confirmar, porém, que no Opera, no Windows Explorer e no Bloco de notas não há mais problemas com personagens fora do BMP (pelo menos no meu PC). Mas de qualquer maneira, se os programas não reconhecem pares substitutos, então eles não usam UTF-16. Quaisquer que sejam os problemas que surgem ao lidar com esses programas, eles não têm nada a ver com o UTF-16 em si.
No entanto, acho que os problemas de software legado com suporte apenas a BMP são um tanto exagerados. Os caracteres fora do BMP são encontrados apenas em casos e áreas muito específicos. De acordo com o FAQ oficial do Unicode , “mesmo em texto do Leste Asiático, a incidência de pares substitutos deve ser bem inferior a 1% de todo o armazenamento de texto em média”.É claro que caracteres fora do BMP não devem ser negligenciados porque um programa não é compatível com Unicode de outra forma, mas a maioria dos programas não se destina a trabalhar com textos que contenham tais caracteres. É por isso que eles não são compatíveis. Para apoiá-lo, é desagradável, mas não uma catástrofe.
Agora vamos considerar a alternativa. Se o UTF-16 não existisse, não teríamos uma codificação adequada para texto não ASCII e todo o software criado para UCS-2 teria que ser completamente redesenhado para permanecer compatível com Unicode. O último provavelmente só retardaria a adoção do Unicode. Além disso, não teríamos sido capazes de manter a compatibilidade com o texto em UCS-2 como o UTF-8 faz em relação ao ASCII.
Agora, deixando de lado todas as questões de legado, quais são os argumentos contra a codificação Eu realmente duvido que os desenvolvedores hoje em dia não saibam que o UTF-16 tem tamanho variável, ele é escrito em todos os lugares com base na Wikipedia. UTF-16 é muito menos difícil de analisar do que UTF-8, se alguém apontou a complexidade como um possível problema. Também é errado pensar que é fácil confundir a determinação do comprimento da string apenas em UTF-16. Se você usa UTF-8 ou UTF-32, ainda deve estar ciente de que um ponto de código Unicode não significa necessariamente um caractere. Fora isso, não acho que haja algo substancial contra a codificação.
Portanto, não acho que a codificação em si deva ser considerada prejudicial. UTF-16 é um meio-termo entre simplicidade e compactação, e não há mal nenhum em usar o que for necessário onde for necessário . Em alguns casos, você precisa permanecer compatível com ASCII e precisa de UTF-8; em alguns casos, você deseja trabalhar com ideogramas Han e economizar espaço usando UTF-16; em alguns casos, você precisa de representações universais de caracteres usando um codificação de comprimento. Use o que for mais apropriado, apenas faça-o corretamente.
Comentários
- Essa ' é uma visão bastante limitada e centrada no anglo-saxão, Malcolm. Quase no mesmo nível de " ASCII é bom o suficiente para os EUA – o resto do mundo deve se encaixar conosco ".
- Na verdade, eu ' m da Rússia e encontro cirílicos o tempo todo (incluindo meus próprios programas), então não ' Acho que tenho uma visão anglo-centrada. 🙂 Mencionar ASCII não é totalmente apropriado, porque ' não é Unicode e não ' suporta caracteres específicos. UTF-8, UTF-16, UTF-32 suportam os mesmos conjuntos de caracteres internacionais, eles são destinados apenas para uso em suas áreas específicas. E este é exatamente o meu ponto: se você usa principalmente inglês, use UTF-8, se você usa principalmente cirílicos, use UTF-16, se você usa línguas antigas, use UTF-32. Muito simples.
- " Não é verdade, scripts asiáticos como japonês, chinês ou árabe também pertencem ao BMP. O BMP em si é na verdade muito grande e certamente grande o suficiente para incluir todos os scripts usados hoje em dia " Isso está tão errado. BMP contém caracteres 0xFFFF (65536). Só o chinês tem mais do que isso. Os padrões chineses (GB 18030) têm mais do que isso. O Unicode 5.1 já alocou mais de 100.000 caracteres.
- @Marcolm: " O próprio BMP é na verdade muito grande e certamente grande o suficiente para incluir todos os scripts usados hoje em dia " Não é verdade. Neste ponto, o Unicode já alocou cerca de 100 mil caracteres, muito mais do que o BMP pode acomodar. Existem grandes blocos de caracteres chineses fora do BMP. E alguns deles são exigidos pelo GB-18030 (padrão chinês obrigatório). Outros são exigidos pelos padrões japoneses e coreanos (não obrigatórios). Portanto, se você tentar vender qualquer coisa nesses mercados, precisará além do suporte BMP.
- Qualquer coisa que use UTF-16, mas só possa lidar com caracteres BMP estreitos, não está usando UTF-16. É bugado e quebrado. A premissa do OP é sólida: o UTF-16 é prejudicial, porque leva um ï cinco pessoas a escrever código quebrado. Você pode lidar com texto Unicode ou não. Se não puder, você está escolhendo um subconjunto, que é tão estúpido quanto o processamento de texto somente ASCII.
Resposta
Anos de trabalho de internacionalização do Windows, especialmente em idiomas do leste asiático, podem ter me corrompido, mas eu me inclino para UTF-16 para representações de strings internas ao programa e UTF-8 para rede ou armazenamento de arquivos de texto simples. como documentos. O UTF-16 geralmente pode ser processado mais rápido no Windows, porém, esse é o principal benefício de usar UTF-16 no Windows.
Dar o salto para o UTF-16 melhorou drasticamente a adequação do manuseio de produtos comuns texto internacional.Existem apenas alguns casos estreitos quando os pares substitutos precisam ser considerados (exclusões, inserções e quebra de linha, basicamente) e o caso médio é principalmente passagem direta. E, ao contrário das codificações anteriores, como as variantes JIS, o UTF-16 limita os pares substitutos a um intervalo muito estreito, de modo que a verificação é muito rápida e funciona para frente e para trás.
Concedido, é quase tão rápido quanto no correto- UTF-8 codificado também. Mas também há muitos aplicativos UTF-8 corrompidos que codificam incorretamente pares substitutos como duas sequências UTF-8. Portanto, UTF-8 também não garante a salvação.
O IE lida com pares substitutos razoavelmente bem desde 2000 ou mais, embora normalmente os esteja convertendo de páginas UTF-8 para uma representação UTF-16 interna; I “Tenho quase certeza de que o Firefox também acertou, então não me importo com o que o Opera faz.
UTF-32 (também conhecido como UCS4) é inútil para a maioria dos aplicativos, pois exige muito espaço, portanto, é praticamente impossível.
Comentários
- Não ' entendi bem o seu comentário sobre UTF-8 e pares substitutos. Os pares substitutos são apenas um conceito significativo na codificação UTF-16, certo? Talvez o código que converte diretamente da codificação UTF-16 para a codificação UTF-8 possa ter esse erro e caso, o problema é ler incorretamente o UTF-16, não escrever o UTF-8. Isso está certo?
- O que Jason ' s está falando é um software que implementa deliberadamente UTF-8 dessa maneira: crie um par substituto e, em seguida, UTF-8 pt codifique cada metade separadamente. O nome correto para essa codificação é CESU-8, mas a Oracle (por exemplo) apresenta incorretamente como UTF-8. Java emprega um esquema semelhante para serialização de objetos, mas ' está claramente documentado como " UTF-8 modificado " e apenas para uso interno. (Agora, se pudéssemos apenas fazer as pessoas LEITARem essa documentação e pararem de usar DataInputStream # readUTF () e DataOutputStream # writeUTF () inadequadamente …)
- AFAIK, UTF-32 ainda é codificação de comprimento variável, e não igual a UCS4, que é um intervalo específico de ponto de código.
- @Eonil, UTF-32 só será distinguível de UCS4 se tivermos um padrão Unicode que apresenta algo como um UCS5 ou maior.
- @JasonTrue Ainda assim, apenas os resultados são iguais coincidentemente, não garantidos pelo design. A mesma coisa aconteceu no endereçamento de memória de 32 bits, Y2K, UTF16 / UCS2. Ou temos alguma garantia dessa igualdade? Se tivermos, eu ficaria feliz em usá-lo. Mas eu não ' não quero escrever um código possível quebrável . Estou escrevendo um código de nível de caractere e a falta de uma maneira garantida de transcodificar entre o ponto de código UTF < – > está me incomodando muito .
Resposta
UTF-8 é definitivamente o caminho a percorrer, possivelmente acompanhado por UTF-32 para interno uso em algoritmos que precisam de acesso aleatório de alto desempenho (mas que ignora a combinação de caracteres).
Ambos UTF-16 e UTF-32 (bem como suas variantes LE / BE) sofrem de problemas de endianess, então devem nunca seja usado externamente.
Comentários
- O acesso aleatório em tempo constante também é possível com UTF-8, apenas use unidades de código em vez de pontos de código. Talvez você precise de acesso real e aleatório ao ponto de código, mas eu ' nunca vi um caso de uso e você ' provavelmente desejará acesso aleatório ao cluster de grafemas.
Resposta
UTF-16? definitivamente prejudicial. Apenas o meu grão de sal aqui, mas existem exatamente três codificações aceitáveis para texto em um programa:
- ASCII: ao lidar com coisas de baixo nível (por exemplo: microcontroladores) que não podem “ter recursos para nada melhor
- UTF8: armazenamento em mídia de largura fixa, como arquivos
-
codepoints inteiros (“CP”?): uma matriz dos maiores inteiros que são convenientes para sua linguagem de programação e plataforma (decai para ASCII no limite de recursos baixos). Deve ser int32 em computadores mais antigos e int64 em qualquer coisa com endereçamento de 64 bits.
-
Obviamente interfaces para uso de código legado qual codificação é necessária para fazer o código antigo funcionar corretamente.
Comentários
- @simon buchan, o
U+10ffff
max sairá pela janela quando (não se) ficarem sem pontos de código. Dito isso, usar int32 em um sistema p64 para velocidade é provavelmente seguro, pois duvido que ' ultrapassaráU+ffffffff
antes de foi forçado a reescrever seu código para sistemas de 128 bits por volta de 2050. (Esse é o ponto de " usar o maior int que seja conveniente " ao contrário de " maior " disponível (que provavelmente seria int256 ou bignums ou algo assim). - @David: Unicode 5.2 codifica 107.361 pontos de código.Existem 867.169 pontos de código não utilizados. " quando " é simplesmente bobo. Um ponto de código Unicode é definido como um número de 0 a 0x10FFFF, uma propriedade da qual UTF-16 depende. (Além disso, 2050 parece muito baixo para uma estimativa para sistemas de 128 bits, quando um sistema de 64 bits pode conter toda a Internet em seu espaço de endereço ' s.)
- @David: Seu " quando " estava se referindo à execução de pontos de código Unicode, não um switch de 128 bits que, sim, será nos próximos séculos. Ao contrário da memória, não há crescimento exponencial de caracteres, então o Unicode Consortium tem especificamente garantido que nunca alocará um ponto de código acima de
U+10FFFF
. Esta é realmente uma daquelas situações em que 21 bits é suficiente para qualquer pessoa. - @Simon Buchan: Pelo menos até o primeiro contato. 🙂
- Unicode usado para garantir que não haveria pontos de código acima de U + FFFF também.
Resposta
Unicode define pontos de código de até 0x10FFFF (1.114.112 códigos), todos os aplicativos em execução em ambiente multilíngue lidando com strings / nomes de arquivo etc. devem lidar com isso corretamente.
Utf-16 : cobre apenas 1.112.064 códigos. Embora aqueles no final de Unicode sejam dos planos 15-16 (Área de Uso Privado). Não pode crescer mais no futuro, exceto quebrar o conceito Utf-16 .
Utf-8 : cobre teoricamente 2.216.757.376 códigos. O intervalo atual de códigos Unicode pode ser representado por uma sequência de no máximo 4 bytes. Ele não sofre com o problema de ordem de bytes , é “compatível” com ascii.
Utf-32 : cobre teoricamente 2 ^ 32 = 4.294.967.296 códigos. Atualmente não é codificado por comprimento variável e provavelmente não o será no futuro.
Esses fatos são autoexplicativos. Eu não entendo que defenda o uso geral de Utf-16 . É codificado por comprimento variável (não pode ser acessado por índice), tem problemas para cobrir todo o intervalo Unicode , mesmo atualmente, a ordem de bytes deve ser tratada, etc. Não vejo nenhuma vantagem, exceto que é usado nativamente no Windows e em alguns outros lugares. Mesmo que, ao escrever código multiplataforma, seja provavelmente melhor usar Utf-8 nativamente e fazer conversões apenas nos pontos finais na forma dependente da plataforma (como já sugerido). Quando o acesso direto por índice é necessário e a memória não é um problema, Utf-32 deve ser usado.
O principal problema é que muitos programadores que lidam com Windows Unicode = Utf-16 nem mesmo sabem ou ignoram o fato de que é codificado com comprimento variável.
A forma como geralmente é na plataforma * nix é muito boa, strings c (char *) interpretadas como Utf-8 strings C codificadas e largas (wchar_t *) interpretadas como Utf-32 .
Comentários
- Observação: UTF -16 cobre todo o Unicode, já que o Consórcio Unicode decidiu que 10FFFF é o intervalo TOP de Unicode e definiu o comprimento máximo de 4 bytes UTF-8 e excluiu explicitamente o intervalo 0xD800-0xDFFF do intervalo de pontos de código válido e esse intervalo é usado para a criação de substituto pares. Portanto, qualquer texto Unicode válido pode ser representado com cada uma dessas codificações. Também sobre como crescer para o futuro. Não ' não parece que 1 milhão de pontos de código não seriam suficientes em um futuro distante.
- @Kerrek: Incorreto: UCS-2 não é um Unicode válido codificação. Todas as codificações UTF- * por definição podem representar qualquer ponto de código Unicode que seja válido para intercâmbio. UCS-2 pode representar muito menos do que isso, além de alguns mais. Repetição: UCS-2 não é uma codificação Unicode válida, mais do que ASCII.
- " Não entendo que defenda o uso geral de Utf- 8 . É codificado por comprimento variável (não pode ser acessado por índice) "
- @Ian Boyd, a necessidade de acessar um caractere individual de uma string em um padrão de acesso aleatório é incrivelmente exagerado. É quase tão comum quanto querer calcular a diagonal de uma matriz de caracteres, o que é extremamente raro. Strings são quase sempre processados sequencialmente, e como acessar UTF-8 char N + 1 dado que você está em UTF-8 char N é O (1), não há problema. Há muito pouca necessidade de fazer acesso aleatório de strings. Se você acha que vale a pena o espaço de armazenamento ir para UTF-32 em vez de UTF-8, é sua opinião, mas para mim, isso não é problema.
- @tchrist, eu garanto suas strings são virtualmente sempre processadas sequencialmente se você incluir a iteração reversa como " sequencial " e esticar isso uma pequena comparação posterior do final de uma string para uma string conhecida. Dois cenários muito comuns são truncar espaços em branco no final de strings e verificar a extensão do arquivo no final de um caminho.
Resposta
Adicione isto à lista:
O cenário apresentado é simples (ainda mais simples porque irei apresentá-lo aqui do que era originalmente! ): 1.Um WinForms TextBox fica em um Form, vazio. Ele tem um MaxLength definido como 20 .
2. O usuário digita no TextBox, ou talvez cola texto nele.
3.Não importa o que você digite ou cole no TextBox, você está limitado a 20, embora ele emitirá um bipe simpático para o texto além dos 20 (YMMV aqui; mudei meu esquema de som para me dar esse efeito!).
4.O pequeno pacote de texto é então enviado para outro lugar, para iniciar uma aventura emocionante.
Agora, este é um cenário fácil e qualquer pessoa pode escrevê-lo em seu tempo livre. Eu mesmo escrevi em várias linguagens de programação usando WinForms, porque estava entediado e nunca tinha tentado antes. E com texto em vários idiomas reais, porque estou conectado dessa forma e tenho mais layouts de teclado do que qualquer pessoa em todo o universo.
Até chamei a forma de Passeio no tapete mágico , para ajudar a amenizar o tédio.
Isso não funcionou, pelo que vale a pena.
Então, em vez disso, inseri o seguinte 20 caracteres em meu formato Passeio no tapete mágico :
0123401234012340123 𠀀
Ups.
Esse último caractere é U + 20000, o primeiro Extensão B ideograma de Unicode (também conhecido como U + d840 U + dc00, para seus amigos próximos que ele não tem vergonha de ser despido, por assim dizer, na frente) ….
E agora temos um jogo de bola.
Porque quando TextBox. MaxLength fala sobre
Obtém ou define o número máximo de caracteres que podem ser inseridos manualmente na caixa de texto.
o que realmente significa é
Obtém ou define o número máximo de cod UTF-16 LE As unidades que podem ser inseridas manualmente na caixa de texto e irão cortar impiedosamente a porcaria viva de qualquer string que tente fazer jogos bonitinhos com a noção de caráter lingüístico que apenas alguém tão obcecado como aquele Kaplan achará ofensivo (caramba, ele precisa saia mais!).
Vou tentar ver se o documento é atualizado …
Leitores regulares que lembre-se de que minha série UCS-2 a UTF-16 notará minha infelicidade com a noção simplista de TextBox.MaxLength e como ele deve lidar, no mínimo, com este caso em que seu comportamento draconiano cria uma sequência ilegal, que outras partes do .Net Framework podem lançar um
- System.Text.EncoderFallbackException : Incapaz de traduzir o caractere Unicode \ uD850 no índice 0 para a página de código especificada. *
exceção se você passar esta string em outro lugar no .Net Framework (como meu colega Dan Thompson estava fazendo).
Bem, talvez a série UCS-2 a UTF-16 completa esteja fora do alcance de muitos.
Mas não “Não é razoável esperar que TextBox.Text não produza um System.String que não fará com que outra parte do .Net Framework seja lançada? Quero dizer, não é como se houvesse uma chance na forma de algum evento no controle que informa sobre o truncamento futuro, onde você pode facilmente adicionar a validação mais inteligente – validação que o próprio controle não se importa em fazer. chegou a dizer que este controle punk está quebrando um contrato de segurança que poderia até levar a problemas de segurança se você classificasse causando exceções inesperadas para encerrar um aplicativo como um tipo bruto de negação de serviço. Por que qualquer processo ou método WinForms deveria algoritmo ou técnica produz resultados inválidos?
Fonte: Michael S.Kaplan MSDN Blog
Comentários
- Obrigado, link muito bom! Eu ' adicionei à lista de problemas na pergunta.
Resposta
Não diria necessariamente que o UTF-16 é prejudicial. Não é elegante, mas serve ao seu propósito de compatibilidade com versões anteriores do UCS-2, assim como o GB18030 faz com o GB2312 e o UTF-8 faz com ASCII.
Mas fazer uma mudança fundamental na estrutura do Unicode no meio do caminho, depois que a Microsoft e a Sun criaram APIs enormes em torno de caracteres de 16 bits, foi prejudicial. O fracasso em divulgar a mudança foi mais prejudicial.
Comentários
- UTF-8 é um superconjunto de ASCII , mas o UTF-16 NÃO é um superconjunto do UCS-2. Embora quase um superconjunto, uma codificação correta de UCS-2 em UTF-8 resulta na abominação conhecida como CESU-8; O UCS-2 não ' tem substitutos, apenas pontos de código comuns, portanto, eles devem ser traduzidos como tal. A vantagem real do UTF-16 é que ' é mais fácil atualizar um codebase UCS-2 do que uma reescrita completa para UTF-8. Engraçado, hein?
- Claro, tecnicamente UTF-16 não é ' um superconjunto de UCS-2, mas quando foi U + D800 a U + DFFF alguma vez usado para qualquer coisa, exceto substitutos UTF-16?
- Não ' importa. Qualquer processamento que não seja a passagem cega pelo bytestream exige que você decodifique os pares substitutos, o que você pode ' fazer se ' tratar novamente como UCS-2.
Resposta
UTF-16 é o melhor compromisso entre manipulação e espaço e é por isso que a maioria das principais plataformas (Win32, Java, .NET) o usa para representação interna de strings.
Comentários
- -1 porque UTF-8 provavelmente é menor ou não é significativamente diferente. Para certos scripts asiáticos, UTF-8 tem três bytes por glifo, enquanto UTF-16 tem apenas dois, mas isso é equilibrado por UTF-8 sendo apenas um byte para ASCII (que muitas vezes aparece mesmo em idiomas asiáticos em nomes de produtos, comandos e coisas assim). Além disso, nos referidos idiomas, um glifo transmite mais informações do que um caractere latino, por isso é justificado para ocupar mais espaço.
- Eu não chamaria a combinação de wor O lado oposto de ambas as opções é um bom compromisso.
- Ele ' não é mais fácil do que UTF-8. É ' tem comprimento variável também.
- Deixando os debates sobre os benefícios do UTF-16 de lado: o que você citou não motivo para Windows, Java ou .NET usando UTF-16. O Windows e o Java datam de uma época em que Unicode era uma codificação de 16 bits. UCS-2 era uma escolha razoável naquela época. Quando o Unicode se tornou uma codificação de 21 bits, a migração para UTF-16 era a melhor escolha que as plataformas existentes tinham. Isso não teve nada a ver com facilidade de manuseio ou compromissos de espaço. É ' é apenas uma questão de legado.
- .NET herda o legado do Windows aqui.
Resposta
Nunca entendi o ponto de UTF-16. Se você quiser a representação mais eficiente em termos de espaço, use UTF-8. Se quiser ser capaz de trate o texto como comprimento fixo, use UTF-32. Se você não quiser nenhum, use UTF-16. Pior ainda, já que todos os caracteres comuns (plano multilíngue básico) em UTF-16 cabem em um único ponto de código, erros que pressupõem que UTF-16 tem tamanho fixo será sutil e difícil de encontrar, enquanto se você tentar fazer isso com UTF-8, seu código falhará rápido e alto assim que você tentar internacionalizar.
Resposta
Como ainda não posso comentar, posto isso como uma resposta, pois parece que não posso contatar de outra forma os autores de utf8everywhere.org
. É uma pena que eu não obtenha automaticamente o privilégio de comentário, pois tenho reputação suficiente em outras trocas de pilha.
Este é um comentário à Opinião: Sim, o UTF-16 deve ser considerado prejudicial resposta.
Uma pequena correção:
Para evitar que alguém passe acidentalmente um UTF-8 char*
em versões de string ANSI de funções de API do Windows, deve-se defina UNICODE
, não _UNICODE
. _UNICODE
mapeia funções como _tcslen
para wcslen
, não MessageBox
para MessageBoxW
. Em vez disso, o UNICODE
define o último. Para prova, isso é do MS Visual Studio 2005 “s WinUser.h
cabeçalho:
#ifdef UNICODE #define MessageBox MessageBoxW #else #define MessageBox MessageBoxA #endif // !UNICODE
No mínimo, este erro deve ser corrigido em utf8everywhere.org
.
Uma sugestão:
Talvez o guia deva conter um exemplo de uso explícito do Wide- versão string de uma estrutura de dados, para torná-la menos fácil de perder / esquecê-la.O uso de versões de strings largas de estruturas de dados além do uso de versões de funções de strings amplas torna ainda menos provável que alguém chame acidentalmente uma versão de strings ANSI de tal função.
Exemplo do exemplo:
WIN32_FIND_DATAW data; // Note the W at the end. HANDLE hSearch = FindFirstFileW(widen("*.txt").c_str(), &data); if (hSearch != INVALID_HANDLE_VALUE) { FindClose(hSearch); MessageBoxW(nullptr, data.cFileName, nullptr, MB_OK); }
Comentários
- Concordo; obrigado! Vamos atualizar o documento. O documento ainda precisa de mais desenvolvimento e adição de informações sobre bancos de dados. Estamos felizes em receber contribuições de redações.
- @PavelRadzivilovsky
_UNICODE
ainda está lá 🙁 - obrigado por lembrar. Cubus, Jelle, Você gostaria de um usuário para nosso SVN?
- @Pavel Claro, agradeceria!
- @JelleGeerts: Peço desculpas por este atraso. Você pode nos contatar por e-mail (link do manifesto) ou do Facebook. Somos fáceis de encontrar. Embora eu acredite que corrigimos o problema que você trouxe aqui (e eu creditei lá), todos os debates UTF-8 vs UTF-16 ainda são relevantes. Se você tiver mais contribua sinta-se à vontade para nos contatar através desses canais privados.
Resposta
Alguém disse que UCS4 e UTF-32 eram mesmo. Não, mas eu sei o que você quer dizer. Um deles é uma codificação do outro, no entanto. Eu gostaria que eles tivessem pensado em especificar endianness desde o início, para que não tivéssemos a batalha de endianess travada aqui também. Eles não podiam ter previsto isso? Pelo menos o UTF-8 é o mesmo em todos os lugares re (a menos que alguém esteja seguindo a especificação original com 6 bytes).
Se você usar UTF-16, você deve incluir o tratamento para caracteres multibyte. Você não pode ir para o enésimo caractere indexando 2N em uma matriz de bytes. Você precisa percorrê-lo ou ter índices de caracteres. Caso contrário, você escreveu um bug.
A especificação de rascunho atual do C ++ diz que UTF-32 e UTF-16 podem ter variantes little-endian, big-endian e não especificadas. Sério? Se o Unicode tivesse especificado que todos deveriam fazer little-endian desde o início, tudo teria sido mais simples. (Eu teria ficado bem com o big-endian também.) Em vez disso, algumas pessoas implementaram de uma forma, outras de outra, e agora estamos presos à tolice à toa. Às vezes, é constrangedor ser um engenheiro de software.
Comentários
- Endianess não especificado deve incluir BOM como o primeiro caractere, usado para determinar de que maneira a string deve ser lida. UCS-4 e UTF-32 de fato são os mesmos hoje em dia, ou seja, um valor UCS numérico entre 0 e 0x10FFFF armazenado em um número inteiro de 32 bits.
- @Tronic: Tecnicamente, isso não é verdade. Embora o UCS-4 possa armazenar qualquer número inteiro de 32 bits, o UTF-32 é proibido de armazenar os pontos de código sem caracteres que são ilegais para intercâmbio, como 0xFFFF, 0xFFFE e todos os substitutos. UTF é uma codificação de transporte, não interna.
- Os problemas de endianness são inevitáveis, desde que diferentes processadores continuem a usar ordens de bytes diferentes. No entanto, poderia ter sido bom se houvesse uma " ordem " preferencial para armazenamento de arquivos UTF-16.
- Embora UTF-32 tenha largura fixa para pontos de código , não é largura fixa para caracteres . (Ouvi falar de algo chamado " combinação de caracteres "?) Então você pode ' ir ao N ' o caractere simplesmente indexando 4N na matriz de bytes.
Resposta
Não acho que seja prejudicial se o desenvolvedor for cuidadoso o suficiente.
E eles devem aceitar essa troca se também souberem disso.
Como um desenvolvedor de software japonês, acho o UCS-2 grande o suficiente e a limitação do espaço aparentemente simplifica a lógica e reduz a memória de tempo de execução, portanto, usar utf-16 na limitação do UCS-2 é bom o suficiente.
Há um sistema de arquivos ou outro aplicativo que assume que os pontos de código e bytes são proporcionais, de forma que o número do ponto de código bruto pode ser ajustado para algum armazenamento de tamanho fixo.
Um exemplo é NTFS e VFAT especificando UCS-2 como sua codificação de armazenamento de nome de arquivo.
Se esse exemplo realmente deseja se estender para suportar UCS-4, eu poderia concordar em usar utf-8 para tudo de qualquer maneira, mas o comprimento fixo tem bons pontos como:
- pode garantir o tamanho por comprimento (o tamanho dos dados e o comprimento do ponto de código são proporcionais)
- pode usar o número de codificação para pesquisa de hash
- dados não compactados são de tamanho razoável (em comparação com utf-32 / UCS-4)
No futuro, quando a memória / poder de processamento for barato, mesmo em quaisquer dispositivos incorporados, podemos aceitar que o dispositivo seja um pouco lento para perdas de cache extras ou falhas de página e memória extra uso, mas isso não vai acontecer em um futuro próximo, eu acho …
Comentários
- Para aqueles que estão lendo este comentário, é importante notar que UCS- 2 não é a mesma coisa que UTF-16. Por favor, procure as diferenças para entender.
Resposta
“Deve ser um dos mais populares codificações UTF-16 podem ser consideradas prejudiciais? “
Muito possivelmente, mas as alternativas não devem necessariamente ser vistas como sendo muito melhores.
O problema fundamental é que existem muitos conceitos diferentes sobre: glifos, caracteres, pontos de código e sequências de bytes. O mapeamento entre cada um deles não é trivial, mesmo com o auxílio de uma biblioteca de normalização. (Por exemplo, alguns caracteres em idiomas europeus que são escritos com um script baseado em latim não são escritos com um único ponto de código Unicode. E isso está no final mais simples da complexidade!) O que isso significa é que fazer tudo correto é incrivelmente difícil; erros bizarros são esperados (e em vez de apenas reclamar sobre eles aqui, diga aos mantenedores do software em questão).
A única maneira em que UTF- 16 pode ser considerado prejudicial ao contrário de, digamos, UTF-8 é que ele tem uma maneira diferente de codificar pontos de código fora do BMP (como um par de substitutos). Se o código deseja acessar ou iterar por ponto de código, isso significa que ele precisa estar ciente da diferença. OTOH, isso significa que um corpo substancial de código existente que assume “caracteres” pode sempre caber em uma quantidade de dois bytes – uma suposição bastante comum, se errada – pode em pelo menos continue a trabalhar sem reconstruir tudo. Em outras palavras, pelo menos você consegue ver aqueles personagens s que não estão sendo tratados da maneira certa!
Eu viraria sua pergunta do avesso e diria que toda a droga de Unicode deve ser considerada prejudicial e todos deveriam usar uma codificação de 8 bits, exceto Eu vi (nos últimos 20 anos) onde isso leva: confusão horrível sobre as várias codificações ISO 8859, além de todo o conjunto usado para cirílico e o conjunto EBCDIC, e … bem, Unicode para todas as suas falhas supera isso . Se não fosse um “compromisso tão desagradável entre diferentes países” mal-entendidos.
Comentários
- Sabendo nossa sorte, em alguns anos nós ' Vamos ficar sem espaço em UTF-16. Meh.
- A questão fundamental é que o texto é enganosamente difícil. Nenhuma abordagem para representar essas informações de forma digital pode ser descomplicada. É ' a mesma razão que datas são difíceis, calendários são difíceis, tempo é difícil, nomes pessoais são difíceis, endereços postais são difíceis: sempre que máquinas digitais se cruzam com construções culturais humanas, complexidade estoura. É um fato da vida. Humanos não funcionam em lógica digital.