7
votes

Comment puis-je décoder les données UTF-16 à Perl lorsque je ne connais pas l'ordre d'octet?

Si j'ouvre un fichier (et spécifiez un encodage directement):

FF FE 3C 00 68 00 74 00


1 commentaires

Pouvez-vous nous montrer un vidage des premiers octets de ce fichier?


3 Réponses :


5
votes

0 commentaires

1
votes

Qu'est-ce que vous essayez de faire impossible.

Vous lisez lignes du texte sans spécifier de codage, chaque octet contenant un caractère nouveau (par défaut \ x0a ) termine une ligne. Mais ce dernier caractère peut très bien être au milieu d'un caractère UTF-16, auquel cas votre prochaine ligne ne peut pas être décodée. Si vos données sont UTF-16LELE, cela se produira que toutes les flux de lignes de temps sont \ x0a \ x00 . Si vous avez UTF16-BE, vous pouvez avoir de la chance (les nouvelles lignes sont \ x00 \ x0a ), jusqu'à ce que vous obtenez un caractère avec \ x0a dans l'octet élevé.

Alors, ne faites pas cela, ouvrez le fichier dans le codage droit.


2 commentaires

Et si vous n'avez pas toujours de fichier et que vous ne recevez que une chaîne?


Ce n'est pas impossible: voir ma réponse pour la façon dont vous devez gérer des séquences d'octets incomplètes.



12
votes

Si vous spécifiez simplement "UTF-16", Perl va rechercher la marque de commande d'octet (BOM) pour déterminer la manière de l'analyser. S'il n'y a pas de naissance, ça va faire exploser. Dans ce cas, vous devez dire à l'encode quel octet-ordre vous avez en précisant soit "UTF-16LE" pour Little-Endian ou "UTF-16BE" pour Big-Endian.

Il y a quelque chose d'autre en cours avec votre situation , mais il est difficile de dire sans voir les données que vous avez dans le fichier. Je reçois la même erreur avec les deux extraits. Si je n'ai pas de bom et que je ne spécifie pas d'ordre d'octets, mon Perl se plaint de toute façon. Quel Perl utilisez-vous et quelle plate-forme avez-vous? Votre plate-forme a-t-elle l'endansion native de votre dossier? Je pense que le comportement que je vois est correct selon les docs. P>

En outre, vous ne pouvez pas simplement lire une ligne dans un encodage inconnu (quelle que soit la valeur par défaut de Perl) puis expédiez cela sur Decode . Vous pourriez vous retrouver au milieu d'une séquence multi-octets. Vous devez utiliser Encode :: FB_Quiet Code> Pour enregistrer la partie du tampon que vous ne pouviez pas décoder et ajouter cela à la partie suivante des données: P>

open my($lefh), '<:raw', 'text-utf16.txt';

my $string;
while( $string .= <$lefh> ) {
    print decode("UTF-16LE", $string, Encode::FB_QUIET) 
    }


2 commentaires

Vous savez que si je concaténate les chaînes dans un grand tampon, je peux utiliser la décodage avec succès.


Vous pouvez décoder le tout à la fois parce qu'il voit la naissance de la chaîne entière. La briser dans des lignes individuelles signifie que la naissance n'est que pour le premier morceau. Le coode ne fait rien de spécial pour essayer de deviner qu'une chaîne est en quelque sorte liée à une autre.