Comment éviter de trébucher sur UTF-8 BOM lors de la lecture de fichiers

je suis en train de consommer un flux de données qui a récemment ajouté un en-tête Unicode BOM (U+FEFF), et ma tâche rake est maintenant fichue par elle.

je peux sauter les 3 premiers octets avec file.gets[3..-1] mais y a-t-il une façon plus élégante de lire les fichiers dans Ruby qui peut gérer cela correctement, si un BOM est présent ou non?

33
demandé sur Andrew Vit 2009-02-12 23:59:59

3 réponses

avec ruby 1.9.2 vous pouvez utiliser le mode r:bom|utf-8

text_without_bom = nil #define the variable outside the block to keep the data
File.open('file.txt', "r:bom|utf-8"){|file|
  text_without_bom = file.read
}

ou

text_without_bom = File.read('file.txt', encoding: 'bom|utf-8')

ou

text_without_bom = File.read('file.txt', mode: 'r:bom|utf-8')

cela n'a pas d'importance, que le BOM soit disponible dans le fichier ou non.


Vous pouvez également utiliser l'option d'encodage avec d'autres commandes:

text_without_bom = File.readlines(@filename, "r:utf-8")

(Vous obtenez un tableau avec toutes les lignes).

ou avec CSV:

require 'csv'
CSV.open(@filename, 'r:bom|utf-8'){|csv|
  csv.each{ |row| p row }
}
55
répondu knut 2015-12-01 21:28:53

Je ne sauterais pas aveuglément les trois premiers octets; et si le producteur arrête ajoutant le BOM à nouveau? Ce que vous devez faire est examiner les premiers octets, et s'ils sont 0xEF 0xBB 0xBF, ignorez-les. C'est la forme que prend le caractère BOM (U+FEFF) en UTF-8; je préfère le traiter avant d'essayer de décoder le flux parce que la manipulation de BOM est tellement incohérente d'un langage/outil/framework à l'autre.

In en fait, c'est comme ça que tu es supposé pour gérer un BOM. Si un fichier a été servi comme UTF-16, Vous devez examiner les deux premiers octets avant de commencer le décodage afin de savoir si vous devez le lire comme big-endian ou little-endian. Bien sûr, le BOM UTF-8 n'a rien à voir avec l'ordre des octets, il est juste là pour vous faire savoir que l'encodage est UTF-8, au cas où vous ne le saviez pas déjà.

10
répondu Alan Moore 2009-02-13 15:33:06

Je ne ferais pas" confiance " à un fichier pour être encodé en UTF-8 quand un BOM de 0xEF 0xBB 0xBF est présent, vous pourriez échouer. Habituellement, lors de la détection de la BOM UTF-8, Il devrait vraiment être un fichier encodé UTF-8 Bien sûr. Mais, si par exemple quelqu'un vient d'ajouter le BOM UTF-8 à un fichier ISO, vous ne réussirez pas à encoder un tel fichier si mal s'il y a des octets qui sont au-dessus de 0x0F. Vous pouvez faire confiance au fichier si vous avez seulement des octets jusqu'à 0x0F à l'intérieur, parce que dans ce cas, c'est un fichier ascii compatible UTF-8 et au en même temps, il s'agit d'un fichier UTF-8 valide.

S'il n'y a pas seulement des octets <= 0x0F dans le fichier (après le BOM), pour être sûr QU'il est correctement encodé UTF-8 vous devrez vérifier les séquences valides et - même lorsque toutes les séquences sont valides - vérifier aussi si chaque point codé d'une séquence utilise la séquence la plus courte possible et vérifier aussi s'il n'y a pas de point codé qui correspond à un HIGH - ou low-Merchant. Vérifiez également si le nombre maximum d'octets d'une séquence n'est pas supérieur à 4 et le nombre le plus élevé codepoint est 0x10ff. Les limites de codepoint les plus élevées aussi les bits de charge utile du startbyte ne doivent pas être supérieurs à 0x4 et le premier octet suivant la charge utile ne doit pas être supérieur à 0xF. Si toutes les vérifications mentionnées passent avec succès, votre BOM UTF-8 dit la vérité.

0
répondu brighty 2013-06-04 10:05:47