Strings en .NET y el BOM

¿Conoceis el BOM? Los que no, teneis suerte… los que sí, seguro que lo habeis sufrido… 🙂 Para los que no, contaros que el BOM, o Byte Order Mask que es lo que significan sus siglas, no es nada más que una marca (de entre 2 y 3 bytes) al principio de un archivo Unicode que indica el formato de los datos… si están en little endian o big endian p.ej.

Quereis verlo en acción? Abrid el bloc de notas y teclead cualquier palabra, como p.ej. Agüero (algún fan del atleti por aqui???). Ahora haced un “guardar como” y marcad la opción “Unicode big endian” en codificación.

Ahora si miramos el tamaño del archivo, vereis que ocupa 14 bytes… Las cuentas no salen: Agüero tiene 6 letras, a 2 bytes la letra Unicode… sobran 2 bytes. El BOM. ¿Queréis más pruebas? Haced un type del archivo desde una consola. Vereis algo como:

■  A g ³ e r o

Este “cuadradito negro” que aparece al principio es el BOM. Que pasa si os lo cargais??? Si abris el fichero con un editor hexadecimal (como el mismo Visual Studio) vereis algo como:

FE FF 00 41 00 67 00 FC 00 65 00 72 00 6F   …A.g…e.r.o

Los dos primeros bytes (FE FF) son el BOM… borradlos para que vuestro archivo quede tal como:

00 41 00 67 00 FC 00 65 00 72 00 6F   .A.g…e.r.o

Lo guardais de nuevo y lo abrís con el bloc de notas… y esto es lo que vereis:

A g ü e r o

Sin BOM el bloc de notas identifica este archivo de texto como ANSI en lugar de Unicode, e interpreta el byte 00 de cada carácter Unicode como un carácter ANSI adicional.

¿Divertido, eh? Pues no os digo nada cuando uno se encuentra que según el protocolo o producto que use el BOM puede ser opcional, obligatorio o hasta prohibido…

¿Y porque os cuento todo esto? Pues porque me he encontrado con un comportamiento curioso (no digo ni que esté mal ni que esté bien) con las strings de .NET y el BOM. Tengo el siguiente código:

class Program
{
    static void Main(string[] args)
    {
        string foo = (char)0xfeff + "Foo";
    }
}

Fácil, eh? Creo una string y le añado el BOM al principio… Y ahora viene lo curioso:

  1. foo.Length devuelve 4 porque cuenta el BOM como un carácter más
  2. foo[0] es un carácter con valor 0xfeff
  3. foo[1] es un carácter con valor 0x0046 (‘F’)
  4. foo.StartsWith(foo[0] + «») devuelve true, indicando que la cadena empieza con el BOM
  5. foo.StartsWith(foo[1] + «») también devuelve true, indicando que la cadena empieza por “F”
  6. foo.Equals(foo.Substring(1)) devuelve false, indicando que ambas cadenas son distintas
  7. foo.CompareTo(foo.Substring(1)) devuelve 0, indicando que ambas cadenas son iguales
  8. foo.Trim se carga el BOM (o sea foo.Trim().Length vale 3)

En fin… parece ser que algunos métodos conocen el BOM y lo ignoran y otros no y lo tratan como un caracter más…

¿Curioso, no?

7 comentarios sobre “Strings en .NET y el BOM”

  1. Hola:

    La verdad, si que es curioso y…raro. Me pregunto como has llegado a «tropezarte» con esto.

    Gracias por trasmitirlo.

    Saludos.
    Oscar.SS

  2. Hola a todos!

    @Oscar.SS
    Jejejeee… Como he llegado a esto? Pues pasando cadenas entre .NET, Java, C y un «ente» llamado NCL… 😛

    @Julio
    Supongo que el comportamiento será el mismo en las cadenas VB.NET (al menos usando las funciones del Framework… las funciones de VisualBasic.dll no se como pueden comportarse)

    @JuanLu
    Lástima… al final 2-1… pero teneis opciones 😉

    Saludos!

  3. NCL??? Nat System Control Language… 🙂 La empresa que lo desarrolló es francesa: http://www.natsys.fr/
    En el cliente donde estoy es uno de los lenguajes en lo que está desarrollada parte de la aplicación con que debemos integrarnos…
    No se porque versión van hoy en dia, pero la que tenemos nosotros es bastante (pero bastante, eh?) antigua… 🙂

    Saludos!

  4. Hola,

    Hablando de NCL, podríais indicarme cómo conseguir información sobre programación NCL, necesito saber cómo pasar información desde NCL a .Net y viceversa.

    gracias

    Cristóbal

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *