Hace 6 meses | Por mr_b a tonsky.me
Publicado hace 6 meses por mr_b a tonsky.me

Hace veinte años, Joel Spolsky escribió: «No existe el texto plano. No tiene sentido tener una cadena de caracteres sin saber qué codificación utiliza. Ya no puedes esconder la cabeza en la arena y pretender que el texto “plano” es ASCII». Mucho ha cambiado en 20 años. En 2003 la pregunta principal era: ¿qué codificación es esta? En 2023 ya no es esa la cuestión: con un 98% de probabilidad la codificación será UTF-8. ¡Ya podemos volver a esconder la cabeza en la arena!

Comentarios

D

Me gustaba el ASCII

e

#6 para que necesitas saber la longitud en bytes? Hay funciones en todos los lenguajes que lo hace por ti, no cambia nada, en vez de llamar length llamas a size o como sea..

avalancha971

#10 Para no tener un overhead así para algo tan básico.

anv

#10 Bueno... será mi mente del siglo pasado que cuando piensa en las funciones que provee cada lenguaje trata de imaginar cómo estarán implementadas. Tener que recorrer una cadena entera byte a byte para poder determinar qué longitud tiene es de lo más ineficiente. Pero bueno, como ahora hay CPU "de sobra", nadie notará si obtener la longitud de una cadena tarda 50 o 100 veces más .

Dicho sea de paso, la cosa llega al extremo de que en python hay cadenas "normales", y cadenas utf8, que van precedidas por una letra u.

Pero bueno, con el tiempo he aprendido a convivir con utf8.

e

#17 #10 muchos lenguajes no usan unicode de longitud variable a no ser que les fuerces el tipo de variable a ello, aparte muchos lenguajes suelen tener para los string una cabecera que contiene un contador de longitud e info sobre el unicode usado, y otro tipo de optimizaciones que no vemos pero que hacen que no sea ningun problema, entre otras cosas por que ya no usamo procesadores de 8 bits pueden moverse 4 en 4 bytes como pez en el agua..
en mi trabajo actual he estado convirtiendo software legacy que no era unicode a unicode y es practicamente automatico, he teneido que ensuciarme las manos por que se uso mucho string como buffer de cosas binarias en vez de usar arrays de bytes y claro al cambiar a unicode el puntero saltaba de dos en dos y no de en uno en uno, pero si el codigo no tuviera esas guarradas la conversion es automatica practicamente.

l

#4 #6 Parece una tonteria, pero en ciertos procesamientos de texto masivo, tiene que afectar al rendimiento.
Supongo que los programas usan indices para orientar donde letras completas.
No se si hay algoritmos para entender una cadena que desconoces el comienzo.


Con los retornos de carro pasa lo mismo en Ascii, no puedes ir directo a la linea tal,porque tienes que ir buscando todos los saltos de linea para saber donde esta el tuyo.

#17 Creo que a partir de python3 todo es UTF, en rust tambiien es todo UTF.
No se si en la implementacion de la cadena. Tienen metadatos para no recorrer la cadena entera. Ya de paso se podrian poner para detectar los saltos de carro o los espacios y poder ir directo a la lineas o palabra x.

En C la cadena era bytes brutos y al final un Null. Para saber la longitud enteidno que tambien habria que buscar el NULL. En Rust No se hace asi porque es una fuente de corrupcion de sofware y entiendo un problema de rendimiento.

En python creo que tamiben hay implmentaciones no standar de Arrays y cadenas de texto, mas eficientes y optimas para quien necesite mas rendimiento. Modulo array y Bstrings o algo asi.


Mejor explicado en #27 de cosas qu me he imaginado.

#40 Mucho mas eficiente que usar el UTF-32 como dicen arriba.

thrasher

#17 aunque haya "CPU de sobra", tener que recorrer la cadena entera es un orden de complejidad lineal O(n) que en algunas situaciones puede impactar de forma horrible (imagina parsear y marcar referencias a un JSON de megas, por ejemplo).
En desarrollo no puede ser excusa tener recursos de sobra para no optimizar, y en este caso, es mejor utilizar más memoria que no CPU para tener accesos O(1).

anv

#29 En desarrollo no puede ser excusa tener recursos de sobra para no optimizar

Es lo usual hoy en día. Bueno, en realidad la excusa para no optimizar es que "time is money", y si haciendo una chapuza terminas rápido, que el cliente compre más memoria. Total, con lo que cuesta 1 día de trabajo se pagan muchos gigabytes de ram. Y así hemos llegado a donde estamos ahora.

ppma

#29, lo que dice #36. Hoy en día se usan frameworks de decenas de MB en memoria para chorradas como crear un botón. Tú me dirás.

cosmonauta

#29 Como dice #17, es común en muchos lenguajes que un string tenga una cabecera con su longitud o sea que la complejidad se ha resuelto con un pequeño uso extra de memoria.

anv

#40 es común en muchos lenguajes que un string tenga una cabecera con su longitud

Pero es que no basta con tener la longitud. ¿Qué pasa si quiero extraer solamente la tercera letra? Claro, almaceno internamente en utf16 o utf32. Así gasto memoria pero puedo hacer búsquedas rápido. Pero... ¿y si en el 99% de los casos nadie saca substrings? estoy usando un formato de almacenamiento innecesario.
Claro, está la posibilidad de que el usuario decida lo que quiere. O incluso que el compilador lo decida.
Pero nos olvidamos de cuando vamos a trabajar a nivel más bajo. ¿Qué pasa si quiero extraer texto de un paquete recibido por un socket tcp/ip? ¿Y si quiero armar un paquete de datos para grabar directo a disco en un formato específico? Claro. Toca convertir.

Obviamente hay soluciones. Pero no deja de ser una complicación extra.

cosmonauta

#42 Para un caso de uso tan particular donde el rendimiento es fundamental se puede tirar de una implementación a nivel de bytes. Para la mayoría de casos de uso, no tener que preocuparse de acentos u otros alfabetos es un inmenso beneficio.

Hace muchos años, cuando unicode no estaba tan extendido, tuve que lidiar con una base de datos que guardaba muchos nombres de personas con procedencias del este y a veces alfabeto ruso y fue un auténtico infierno conseguir que todo (BD, Backend, frontend, excels, etc..) funcionase en unicode. Hoy es mucho más fácil.


Todo tiene ventajas e inconvenientes.

anv

#43 Para la mayoría de casos de uso, no tener que preocuparse de acentos u otros alfabetos es un inmenso beneficio.

Pues sí. Total se compra un ordenador más potente y listo roll

thrasher

#6 si necesitas esa casuística, la solución principal es utilizar UTF-32, que utiliza siempre 4 bytes por carácter, a costa de ocupar de media más espacio en comparación con UTF-8. Esto es lo que se usa internamente en memoria, para poder trabajar cómodamente con cadenas, dejando UTF-8 para datos almacenados en disco.

e

#26 o UTF16, dependiendo del luegaje ya usan cabeceras para los string que contienen la longitud ya calculada y optimizada

thrasher

#28 es que con UTF16 ya tienes acceso a todos los codepoints que puedes necesitar habitualmente.
De hecho, MySQL recomienda utilizar utf8mb4 como character encoding, y una cosa que no sabía es que el encoding utf8 es un alias a utf8mb3, así que siempre almacena 3 bytes por carácter
https://stackoverflow.com/questions/30074492/what-is-the-difference-between-utf8mb4-and-utf8-charsets-in-mysql

Penetrator

#26 #28 Si os leéis el artículo, podréis ver que ninguna de esas es la solución. Básicamente, porque hay caracteres (glifos) que se definen utilizando más de un code point.

S

#50 La animación que tiene editando los glifos mola, básicamente convierte fácilmente una familia en pareja separada, con un solo hijo, solo quedan los hijos, etc. lol

e

#50 he leido el articulo pero se por experiencia propia que no se trabaja asi, los lenguajes salvo que los fuerzes usan una version de longitud fija 2, 3 o 4 bytes.

Penetrator

#56 Que lo usen los lenguajes no significa que esté exento de problemas.

e

#57 no son problemas son complicaciones, renuncias a tener caracteres chorras como los smiles etc.. pero tb usar longitud variable tiene sus complicaciones o problemas como tu llamas alas complicaciones.

Penetrator

#58 #59 Si sólofueran los emoticonos... Las vocales acentuadas también se pueden representar con dos codepoints.

m

#60: Como digo más abajo, Unicode hoy por hoy es una chapuza, es como un edificio al que se le añaden estancias según hace falta y el resultado final es un horror estético, no es práctico...

A mí lo de que hay que actualizar ha sido lo que más claro me ha dejado que está mal implementado. No siempre se puede actualizar, no siempre hay una persona que se hace cargo de ello... o sea, imaginad un artículo de la Wikipedia, no hay problema en actualizarlo, pero... ¿Quién lo hace? ¿Quién se percata de que un símbolo raro que aparece es un Unicode antiguo que han cambiado? ¿Se pone un robot rastreador? ¿Quién lo programa y corre con el gasto de funcionamiento, si bastante cuestan los servidores?

m

#50: Los emojiconos... en mi opinión es un error representar los emojiconos como una letra cualquiera.

Se tendría que haber buscado otra forma de hacerlo en mi opinión. El BBcode yo creo que estaba bien, con llaves, alguna palabra clave y listo. En aplicaciones de mensajería se puede implementar de forma transparente para el usuario, pulsando un botón y sacando la carita o dibujo correspondiente.

anv

#26 la solución principal es utilizar UTF-32, que utiliza siempre 4 bytes por carácter,

Claro, pero por un lado el standard hoy en día es utf-8. Por otro lado si me decantara por algo sería por ascii, no por algo tan ineficiente como utf-32.

Esto es lo que se usa internamente en memoria, para poder trabajar cómodamente con cadenas

Claro, como la memoria sobra, abusemos de ella. Total que la gente se compre un ordenador nuevo si hace falta.

Debe ser mis viejas costumbres de hacer programas que entraran en 64kb (en realidad 8K si era posible). Después se preguntan como un ordenador 1000 veces más lento arrancaba 100 veces más rápido.

pawer13

#34 Por otro lado si me decantara por algo sería por ascii, no por algo tan ineficiente como utf-32. Y que haces con símbolos como la ñ, las tildes y demás caracteres que no son ascii?

anv

#46 Y que haces con símbolos como la ñ, las tildes y demás caracteres que no son ascii?

Pues hay varias alternativas. Puedes usar por ejemplo iso8859-17 o simplemente poner ~ en lugar de la ñ o algo así.

pawer13

#65 Es decir, hacer una ñapa para no usar el estándar

anv

#79 Si. Justamente porque el estándar ha sido pensado para solucionar un problema pero causando otros que antes no existían. Cuando esos problemas nuevos son importantes, es razonable dejar de lado el estándar en favor de la optimización.

s

#26 Creo que no has leído el artículo. Advierte precisamente que usar UTF-32 pude no ser suficiente, ya que hay representaciones gráficas de caracteres que utilizan dos códigos UTF-32.

m

#6: Y peor aún, aún teniendo todo bien hecho, según lo último del final NO puedes saber cómo representar lo que está escrito si no te dicen nada. Tampoco hay un estándar para usar en programación de forma más o menos transparente... o sea, obtener la longitud de una cadena como almacenamiento o como visualización en pantalla (el típico .length) o buscar una cadena dentro de otra. Otro problema es que un mismo carácter tenga múltiples representaciones diferentes, una de forma directa y otra juntando dos "letras" en memoria para hacer una "letra" en pantalla. Creo que si las vocales con acentos ya están representadas, lo suyo es no poner acentos como "añadidura" a las vocales. En los emojiconos puede tener más sentido para representar las posibles variaciones (color de piel, género...), pero en letra normal, no.

Otro problema gordo es que se actualice año tras año... ¿Y si quiero distribuir mi aplicación en CD-ROM o como sea? ¿Y si no puedo actualizar mi aplicación año tras año porque no soy programador y tengo mejores cosas que hacer? ¿Y si quiero que los bytes de un texto no cambien para que un hash generado desde ellos tampoco cambie? Las actualizaciones deberían ser siempre para añadir cosas, NUNCA para modificar retroactivamente lo que se ha implementado.

Y otro problema: añadir emojiconos a símbolos que son antiguos, como por ejemplo, una flecha, porque te está forzando un aspecto estético, mientras que la representación en texto (o sea un contorno) permite elegir el color de la fuente, si es cursiva o negrita... Los emojiconos deberían ser siempre en caracteres exclusivos, y como antes, no convertir en emojicono un símbolo que nunca lo ha sido.

llorencs

#2 Eh, ¿por qué te has hecho viejo? Yo aún me he encontrado con ese problema. Y con CSVs (principalmente) aún ocurre. UTF-8 o UTF-8-BOM. Hay aplicaciones que fuerzan el BOM y otras no.

r

#5 Como sea un CSV que haya pasado por Excel, entonces hay casi un cien por cien de probabilidades de que esté codificado en 'latin-1' si quien te lo ha enviado tiene al menos un apellido en español.

Señores de Microsoft, ¿tan complicado es poner por defecto como codificación UTF-8 cuando se exporta a CSV? Es más, ¿podéis hacer que por favor los decimales aparezcan en los CSV como un jodido punto y quitar de una maldita vez el separador de miles?

c

#11 Y si un dato viene entre comillas, tratadlo como un String que 001 no es lo mismo que 1.

Dragstat

#23 las comillas y los comas cuando tratas CSVs clap

c

#11 Lo de la codificación de caracteres en Windows es de locos

ppma

#11 Lo de los miles no es cosa de microsoft ni office. Han elegido usar la notación establecida en el sistema, que si lo tienes configurado por defecto en español es con . como separador de miles y , como separador de decimales. Yo trabajo en ciencia, y por interpolabilidad lo primero que hago es cambiar esas dos cosas en las propiedades del sistema. Mano de santo.

#5 No, si lo de viejo ha sido al ver las fechas en el gráfico y darme cuenta de los "hitos" que he vivido.

Lenari

#2 Con, pero bastantes editores de texto te lo quitan, con lo cual al final te tienes que acostumbrar a trabajar sin.

P

#2 Sin, obviamente. Me cago en los conbomistas

D

#8 qué susto me he dao... yo pensaba que me habían juaqueao lol lol

P.D.: El modo lectura es tu amigo.

Xtampa2

#8 #19 #24 #22 #37 Podéis probar el modo noche de la página lol

D

#51 A mí me gusta al natural.

D

#51 la puta, me horripiencanta!

m

#19: Cursed cursors. (cursores malditos)

D

#8 A mí me ha hecho gracia. Pero es un poco sádico el cabronazo.

F

#24 Dificulta la lectura. Es de ser un capullo.

D

#37 Supongo que estoy entrenado a bloquear lo que me distrae: mis sobrinos dificultan la lectura mucho más, o las canciones repetitivas del colegio del al lado.

F

#38 Tus sobrinos son niños. Hacen cosas de niños. No las hacen para dificultarte la lectura. Lo mismo con el colegio de al lado.

En cambio, el capullo ese ha puesto lo de los cursores única y exclusivamente para tocar los cojones y dificultar la lectura. Que le den.

S

#48 Pues gracias a vuestros comentarios me he dado cuenta de que existían, ni los había visto.

j0seant

#48 seguramente no ha sido esa la intención, sino la de lucirse añadiendo alguna tontería que suele ser el motivo muchas veces, sin pararse a pensar en la experiencia de quien va a leerlo, pasa con frecuencia que hacemos cosas sin muchas veces pensar en que nosotros mismos como lectores/usuarios/consumidores veríamos como molesto.. y ya la forma en que funciona el modo noche que ha puesto el tío es pa matarlo

C

#8 Los cursores sí me han rallado un poco, pero el color, como uso el complemento Dark Reader en Firefox... ni me había enterado.

DORO.C

UTF-8 mb4 o la barbarie!

ur_quan_master

#1 mb4 en lugar de utf a secas porque sin duda es necesario poder escribir U+01F4A9

lol

c

#3 Espero que no tengas usuarios del china, japón...

systembd

#21 ¿Esos bárbaros que utilizan 16 (o 24) bits por carácter/glifo? No nos merecen

ur_quan_master

#21 no has visto el símbolo unicode que he enviado.

c

#77 💩 hahaha

HeilHynkel

Y yo que llegué a usar caracteres ASCII de 7 bits .... anda que no soy mayor ni ná.

Del EBCDIC no digo ná porque los mainframes lo deben seguir usando.

s

#7 Pues sí, como cuando los años en los que Plan9 tenía un desarrollo activo en el sitio de donde salió Unix: The history of UTF-8 as told by Rob Pike http://doc.cat-v.org/bell_labs/utf-8_history

avalancha971

#7 Yo aún uso SMS encoding de 7bits.

D

#15 sale más barato

e

#7 que hacias con el bit que te sobraba? correcion de errores?

HeilHynkel

#30

Nada, pero los terminales serie que usábamos hacian una cosa muy rara (ahora, para ellos sería de lo mas normal) Se codificaban en 7 bit pero si cambiabas el idioma (en el terminal) se cambiaba la representación de los símbolos. Por ejemplo la Ñ aparecía en un código por debajo de 127 (eliminando el simbolo correspondiente, claro)

Por ese motivo yo aprendí a codificar usando un teclado serigrafiado en español pero usando el layout inglés (de aquella el UNIX no tenía los caracteres españoles, al menos nuestra versión) Con el tiempo eso me vino bien cuando se descojonaba alguna máquina UNIX y se ponía solo el layout inglés. Yo podía teclear comandos unix sin problemas porque sabía de memoria donde estaban el guión, los slash, ...

También me suena que nos la armaban con los RS-232 porque por encima del 127 se enviaban caracteres de control (hace 30 años de aquello, tampoco me hagas mucho caso)

D

#30 Cada 7 caracteres tenías uno gratis! Es decir, con 7 bytes (56 bits) podías tener 8 caracteres. Hubo un tiempo en el que el espacio en disco/ancho de banda era un problema.

e

#35 pero tambien los mhz eran un problema, dudo que aprovecharan ese bit, por que aunque el espacio pera caro, los procesadores no estaban para muchas fiestas tampoco...

D

#39 Bueno si no recuerdo mal esto viene de muy muy antiguo, de cuando el estándar era ANSI antes de que existiera ASCII, o sea los años 60 o así. Así que no me sorprendería que en aquella época la arquitectura de los mainframes de la época no penalizase usar caracteres de 6 bits. Pero todo esto lo digo de memoria y podría estar equivocado, y ahora no puedo comprobarlo...

redscare

Problemas con el encoding, problemas de encriptacion y problemas con expresiones regulares. Top 3 de dolores de cabeza con los que todo programador se estrella tarde o temprano.

Por cierto que en pleno 2023 UTF-8 todavía NO es el encoding por defecto del SQL Server de Microsoft, y hay que dar saltos como un mono para usarlo. Lamentable.

c

#32 Ni en MySQL

j0seant

#32 a los angloparlantes les sobra con el ASCII/ANSI, cuesta muchas veces convencerles de que estos temas son importantes (especialmente a los usanos), por suerte cada vez hay más frikis del mundo asiático angloparlantes y son más conscientes de estas cosas, que de paso benefician a muchas otras lenguas, pero hace unos años no les convencías tan fácilmente por muchos ejemplos que les mostraras..

m

#32: Porque es una birria, lee el artículo, cuanto más bajes más verás que la implementación es una chapuza, ni siquiera es retrocompatible. O sea, si tienes un texto de 2010 lo lees ahora y lo mismo algún carácter cambia, algo que NUNCA debería suceder, no se puede forzar al usuario a actualizar las cosas porque eso no siempre es posible.

S

#62 También es que el tema de la codificiación, si encima quieres que sea enficiente, es complicado han tomado algunas ideas que parecían molar pero que también generan complicaciones. Hay vulnerabilidades informáticas que se basan en el uso de caracteres especiales, sus propiedades.


https://github.com/ocaml/ocaml/issues/10749

m

#69: Esa es otra, yo en las URLs tengo desactivados los caracteres Unicode, prefiero no ver las eñes a que me la cuelen.

skaworld

Nadie se va a quejar del fondo de pantalla con punteros de raton moviendose pa joder?

Itilvte

#22 no es el fondo de pantalla, son los cursores de todos los que están navegando por la página en ese momento, entiendo yo. Un concepto curioso pero distrayente.

i

Interesante que una cadena con Emojis no te de el largo real de la cadena (según perspectiva humana)
Es decir “ roll ”.strlen() no es 4.

t

#16 Si solo fuesen los emojis. Por ejemplo, según como representes una vocal acentuada, puede tener uno o dos de longitud.

c

#16 pues en ruby tira perfectamente.

3.1.2 :021 > " 😀 😀 😀 😀 😀 ".length
=> 5

S

#16 Es interesante, pero tampoco es tan inesperado. A mi no me parece tan raro, por una parte no tiene sentido aplicar la longitud de un texto por caracteres a emoticonos, por otra, estás hablando de tan bajo nivel que es normal que se centre en los datos, no tanto en su interpretación. Sin contar que para mi, algunos de esos emoticonos todavía los veo como automáticamente, que serían 3 caracteres.

Y que en algunos foros es como se copiaban en el portapapeles.

w

Muy bueno el artículo

Lito

Menos mal que es el mínimo absoluto.

c

Joder, que tortura era programar en C cuando se empezó con el Unicode.

Puto w_char_t

k

Articulazo! 👍