Est-il possible de convertir un fichier en UTF-8 de mon côté?
Si j’ai un accès au fichier après la soumission avec
$_FILES['file']['tmp_name']
Remarque: L'utilisateur peut télécharger un fichier CSV avec tout type de jeu de caractères. Je rencontre généralement un jeu de caractères unknown 8 bits.
J'essaie
$row = array();
$datas = file($_FILES['file']['tmp_name']);
foreach($datas as $data) {
$data = mb_convert_encoding($data, 'UTF-8');
$row[] = explode(',', $data);
}
Mais le problème est que ce code supprime les caractères spéciaux tels que guillemets simples.
Ma première question est htmlspecialchars supprimer la valeur à l'intérieur du tableau?
Je le mets pour des informations supplémentaires. Merci à ceux qui peuvent aider!
avant de pouvoir le convertir en utf-8, vous devez savoir en quoi consiste le jeu de caractères . Si vous ne pouvez pas comprendre cela, vous ne pouvez pas le convertir de manière rationnelle en utf8 .. Cependant, un moyen insensé de le convertir en utf-8, si le codage ne peut pas être déterminé, consiste simplement à effacer tous les octets qui ne sont pas valides dans utf-8, vous pouvez peut-être utiliser ce comme solution de rechange ...
avertissement, code non testé (im soudainement pressé), mais peut ressembler à ceci:
foreach ( $datas as $data ) {
$encoding = guess_encoding ( $data );
if (empty ( $encoding )) {
// encoding cannot be determined...
// as a fallback, we simply strip any bytes that isnt valid utf-8...
// obviously this isn't a reliable conversion scheme.
// also this could probably be improved
$data = iconv ( "ASCII", "UTF-8//TRANSLIT//IGNORE", $text );
} else {
$data = mb_convert_encoding ( $data, 'UTF-8', $encoding );
}
$row [] = explode ( ',', $data );
}
function guess_encoding(string $str): string {
$blacklist = array (
'pass',
'auto',
'wchar',
'byte2be',
'byte2le',
'byte4be',
'byte4le',
'BASE64',
'UUENCODE',
'HTML-ENTITIES',
'7bit',
'8bit'
);
$encodings = array_flip ( mb_list_encodings () );
foreach ( $blacklist as $tmp ) {
unset ( $encodings [$tmp] );
}
$encodings = array_keys ( $encodings );
$detected = mb_detect_encoding ( $str, $encodings, true );
return ( string ) $detected;
}
Essayez ceci.
L’exemple que j’ai utilisé était quelque chose que j’étais en train de faire dans un environnement de test, vous devrez peut-être légèrement modifier le code.
J'ai eu un fichier texte avec les données suivantes dans:
test
café
áÁÁÁááá
žžœš¥±
ÆÆÖÖÖasØØ
ß
Ensuite, j'ai eu un formulaire qui a pris une entrée de fichier et effectué le code suivant:
function neatify_files(&$files) {
$tmp = array();
for ($i = 0; $i < count($_FILES); $i++) {
for ($j = 0; $j < count($_FILES[array_keys($_FILES)[$i]]["name"]); $j++) {
$tmp[array_keys($_FILES)[$i]][$j]["name"] = $_FILES[array_keys($_FILES)[$i]]["name"][$j];
$tmp[array_keys($_FILES)[$i]][$j]["type"] = $_FILES[array_keys($_FILES)[$i]]["type"][$j];
$tmp[array_keys($_FILES)[$i]][$j]["tmp_name"] = $_FILES[array_keys($_FILES)[$i]]["tmp_name"][$j];
$tmp[array_keys($_FILES)[$i]][$j]["error"] = $_FILES[array_keys($_FILES)[$i]]["error"][$j];
$tmp[array_keys($_FILES)[$i]][$j]["size"] = $_FILES[array_keys($_FILES)[$i]]["size"][$j];
}
}
return $files = $tmp;
}
if (isset($_POST["submit"])) {
neatify_files($_FILES);
$file = $_FILES["file"][0];
$handle = fopen($file["tmp_name"], "r");
while ($line = fgets($handle)) {
$enc = mb_detect_encoding($line, "UTF-8", true);
if (strtolower($enc) != "utf-8") {
echo "<p>" . (iconv($enc, "UTF-8", $line)) . "</p>";
} else {
echo "<p>$line</p>";
}
}
}
?>
<form action="<?= $_SERVER["PHP_SELF"]; ?>" method="POST" enctype="multipart/form-data">
<input type="file" name="file[]" />
<input type="submit" name="submit" value="Submit" />
</form>
La fonction neatify_files
est quelque chose que j'ai écrit pour rendre le tableau $_FILES
plus logique dans sa présentation.
Le formulaire est un formulaire standard qui POST
s simplement les données sur le serveur.
Note: L’utilisation de $_SERVER["PHP_SELF"]
est un risque pour la sécurité, voir ici pour plus d’informations .
Lorsque les données sont publiées, je stocke le fichier dans une variable. De toute évidence, si vous utilisez l'attribut multiple
, votre code ne ressemblera pas vraiment à ceci.
$handle
stocke tout le contenu du fichier texte dans un format en lecture seule; d'où l'argument "r"
.
$enc
utilise la fonction mb_detect_encoding
pour détecter le codage (duh).
Au début, j'avais du mal à obtenir le bon encodage. Définir le encoding_list
pour utiliser uniquement UTF-8 et définir strict
sur true.
Si l'encodage est UTF-8, j'imprime simplement la ligne. Sinon, je l'ai converti en UTF-8 à l'aide de la fonction iconv
.
vous pouvez convertir le texte du fichier en données binaires en utilisant ce qui suit
FUNCTION bin2text($bin_str)
{
$text_str = '';
$chars = EXPLODE("\n", CHUNK_SPLIT(STR_REPLACE("\n", '', $bin_str), 8));
$_I = COUNT($chars);
FOR($i = 0; $i < $_I; $text_str .= CHR(BINDEC($chars[$i])), $i );
RETURN $text_str;
}
FUNCTION text2bin($txt_str)
{
$len = STRLEN($txt_str);
$bin = '';
FOR($i = 0; $i < $len; $i )
{
$bin .= STRLEN(DECBIN(ORD($txt_str[$i]))) < 8 ? STR_PAD(DECBIN(ORD($txt_str[$i])), 8, 0, STR_PAD_LEFT) : DECBIN(ORD($txt_str[$i]));
}
RETURN $bin;
}
après avoir converti les données en binaire, vous devez simplement changer le texte en méthode php mb_convert_encoding ($ fileText, "UTF-8");
Essayons ça:
function encode_utf8($data)
{
if ($data === null || $data === '') {
return $data;
}
if (!mb_check_encoding($data, 'UTF-8')) {
return mb_convert_encoding($data, 'UTF-8');
} else {
return $data;
}
}
Usage:
$content = file_get_contents($_FILES['file']['tmp_name']);
$content = encode_utf8($content);
$rows = explode("\n", $content);
foreach ($rows as $row) {
print_r($row);
}
function convert_file_to_utf8($source, $target) {
$content=file_get_contents($source);
# detect original encoding
$original_encoding=mb_detect_encoding($content, "UTF-8, ISO-8859-1, ISO-8859-15", true);
# now convert
if ($original_encoding!='UTF-8') {
$content=mb_convert_encoding($content, 'UTF-8', $original_encoding);
}
$bom=chr(239) . chr(187) . chr(191); # use BOM to be on safe side
file_put_contents($target, $bom.$content);
}