2011-01-27 5 views
1

Je rencontre des problèmes d'encodage bizarres lorsque je manipule des fichiers téléchargés.Fichiers non-UTF8 (fichier Google CSV)

Je dois accepter n'importe quel type de fichier texte, et être capable de lire le contenu. Plus précisément, vous rencontrez des problèmes avec les fichiers téléchargés à partir d'une exportation Google Contacts.

J'ai fait l'habituel utf8_encode/decode, mb_detect_encoding, etc. Toujours retourne comme si la chaîne est UTF-8, et essayé de nombreuses options iconv pour essayer de revenir à l'encodage, mais échoué.

test.php

header('Content-type: text/html; charset=UTF-8'); 

if ($stream = fopen($_FILES['list']['tmp_name'], 'r')) 
{ 
    $string = stream_get_contents($stream); 

    fclose($stream); 
} 

echo substr($string, 0, 50); 
var_dump(substr($string, 0, 50)); 
echo base64_encode(serialize(substr($string, 0, 50))); 

Sortie

��N�a�m�e�,�G�i�v�e�n� �N�a�m�e�,�A�d�d�i�t�i�o�n� 
��N�a�m�e�,�G�i�v�e�n� �N�a�m�e�,�A�d�d�i�t�i�o�n� 
czo1MDoi//5OAGEAbQBlACwARwBpAHYAZQBuACAATgBhAG0AZQAsAEEAZABkAGkAdABpAG8AbgAiOw== 
+2

Les erreurs de codage sont trop vagues. Nous avons besoin d'un exemple. Essayez d'écrire un 'base64_encode (serialize ($ excerpt))' ici. – mario

+0

Mis à jour avec des exemples d'extraits. – James

+0

D'où vient la chaîne $? Pouvez-vous montrer le code que vous utilisez pour l'obtenir? Quel encodage produisez-vous dans ceci? –

Répondre

3

Le début de la chaîne porte les octets \ xFF \ xFE qui représentent le Byte Order Mark pour UTF-16 Little Endian. Toutes les lettres sont en réalité des séquences de deux octets. Principalement un \ 0 suivi par le caractère ASCII.

En les imprimant sur la console, le client terminal interprétera correctement les séquences UTF-16. Mais vous devez le décoder manuellement (mieux via iconv) pour rendre le tableau entier affichable.

+0

http://www.codeunit.co.za/2010/03/05/php-convert-a-utf-16-string-to-a-utf-8-string/ fourni le code à convertir, merci de remarquer la nomenclature – James

+0

@James, avez-vous utilisé ce fn() dans un scénario d'importation important? Je suis confronté à des utilisateurs qui téléchargent de gros fichiers (10-200mb) pour l'importation, et il ne semble pas faisable de l'exécuter sur TOUS les champs, et je n'ai pas le luxe de tout charger en mémoire. – Jakub

+1

@Jakub: Vous pouvez utiliser la fonction [iconv ("UTF-16", "UTF-8", $ str)] (http://www.php.net/manual/fr/function.iconv.php) pour cette. Ou si les fichiers téléchargés ne doivent pas être lus, essayez 'system (" Recoder UTF-16..UTF-8 '$ filename' ");' pour une conversion rapide sur place sur les serveurs BSD/Linux. – mario

0

Quand je décodées la pièce base64, je vis une chaîne mixte étrange: s:50:"\xff\xfeN\x00a\x00m\x00e\x00,\x00G\x00i\x00v\x00e\x00n\x00 \x00N\x00a\x00m\x00e\x00,\x00A\x00d\x00d\x00i\x00t\x00i\x00o\x00n\x00". La partie après la seconde : est une chaîne Unicode (UCS2) de 2 octets incluse en ASCII ", alors que "s" et "50" sont des caractères ASCII. Cette pièce \ff\fe est une marque d'ordre d'octet d'une chaîne UCS2. C'est fou mais analysable.

Je suppose que vous divisez la chaîne d'entrée par :, déposez " depuis le début et la fin et essayez de décoder chaque chaîne résultante séparément.