php - utf8 - utf>- 8 sin bom
Detectar codificación de archivos en PHP (8)
Tengo un script que combina una cantidad de archivos en uno y se rompe cuando uno de los archivos tiene codificación UTF8. Me imagino que debería estar usando la función utf8_decode()
al leer los archivos, pero no sé cómo decir qué necesidad de decodificación.
Mi código es básicamente:
$output = '''';
foreach ($files as $filename) {
$output .= file_get_contents($filename) . "/n";
}
file_put_contents(''combined.txt'', $output);
Actualmente, al comienzo de un archivo UTF8, agrega estos caracteres en el resultado: 
¿Cómo va a manejar los caracteres no ASCII del archivo UTF-8 o 16 o 32?
Lo pregunto porque creo que puede haber un problema de diseño aquí.
Convertiría tu archivo de salida en UTF-8 (o 16 o 32) en lugar de hacerlo al revés.
Entonces no tendrás este problema.
¿También ha considerado los problemas de seguridad que pueden surgir al convertir un código UTF8 escapado? Ver este comentario :
Detectando la codificación multi-byte
Averigua en qué codificación está tu archivo fuente, luego conviértelo a UTF8 y deberías estar listo.
Esta es mi solución que funcionó como un encanto:
//check string strict for encoding out of list of supported encodings
$enc = mb_detect_encoding($str, mb_list_encodings(), true);
if ($enc===false){
//could not detect encoding
}
else if ($enc!=="UTF-8"){
$str = mb_convert_encoding($str, "UTF-8", $enc);
}
else {
//UTF-8 detected
}
mb_detect_encoding
función mb_detect_encoding
debería ser su última opción. Eso podría devolver una codificación INCORRECTA. El file -i /path/myfile.txt
comandos de Linux file -i /path/myfile.txt
funciona de maravilla. En PHP puedes usar:
function _detectFileEncoding($filepath) {
// VALIDATE $filepath !!!
$output = array();
exec(''file -i '' . $filepath, $output);
if (isset($output[0])){
$ex = explode(''charset='', $output[0]);
return isset($ex[1]) ? $ex[1] : null;
}
return null;
}
Para los servidores de Linux, uso este comando:
$file = ''your/file.ext''
exec( "from=`file -bi $file | awk -F''='' ''{print $2 }''` && iconv -f /$from -t utf-8 $file -o $file" );
Para asegurarme de que la salida sea UTF-8, no importa qué tipo de entrada sea, utilizo esta verificación :
if(!mb_check_encoding($output, ''UTF-8'')
OR !($output === mb_convert_encoding(mb_convert_encoding($output, ''UTF-32'', ''UTF-8'' ), ''UTF-8'', ''UTF-32''))) {
$output = mb_convert_encoding($content, ''UTF-8'', ''pass'');
}
// $output is now safely converted to UTF-8!
Escanea todo el archivo, encuentra cualquier tipo de codificación de mb_list_encodings, buen rendimiento ...
function detectFileEncoding($filePath){
$fopen=fopen($filePath,''r'');
$row = fgets($fopen);
$encodings = mb_list_encodings();
$encoding = mb_detect_encoding( $row, "UTF-8, ASCII, Windows-1252, Windows-1254" );//these are my favorite encodings
if($encoding !== false) {
$key = array_search($encoding, $encodings) !== false;
if ($key !== false)
unset($encodings[$key]);
$encodings = array_values($encodings);
}
$encKey = 0;
while ($row = fgets($fopen)) {
if($encoding == false){
$encoding = $encodings[$encKey++];
}
if(!mb_check_encoding($row, $encoding)){
$encoding =false;
rewind($fopen);
}
}
return $encoding;
}
Intenta usar la función mb_detect_encoding
. Esta función examinará su cadena e intentará "adivinar" cuál es su codificación. A continuación, puede convertirlo como desee. Sin embargo, como lo sugirió brulak , probablemente sea mejor que se convierta a UTF-8 en lugar de hacerlo para preservar los datos que está transmitiendo.
Recientemente encontré este problema y la salida de la función mb_convert_encoding()
fue UTF-8 . Después de echar un vistazo a los encabezados de respuesta, no había nada que mencionara el tipo de codificación, así que encontré Set http header to utf-8 php , que propone lo siguiente:
<?php
header(''Content-Type: text/html; charset=utf-8'');
Después de agregar eso a la parte superior del archivo php, todos los caracteres funky desaparecieron y se procesaron como deberían. No estoy seguro de si ese era el problema que buscaba el afiche original, pero encontré esto al tratar de resolver el problema yo mismo y pensé que lo compartiría.