Maison  >  Article  >  développement back-end  >  Explication détaillée des fichiers php et du codage des caractères

Explication détaillée des fichiers php et du codage des caractères

小云云
小云云original
2018-03-14 15:15:051899parcourir


Mon doute initial était : quelle est la différence entre les fichiers texte et les fichiers binaires ? Pourquoi l'un peut-il afficher le contenu, mais le contenu de l'autre ne peut souvent pas être affiché normalement (à l'aide d'un éditeur de texte) ?

Cette note de formation de l'Université du Maryland explique clairement la différence entre les deux : les fichiers texte sont un type de fichiers binaires, et le stockage sous-jacent est également 0 et 1. Les fichiers texte sont lisibles et portables, mais Expression ; les caractères sont limités ; le stockage des données des fichiers binaires est compact et n’a aucune restriction de codage de caractères. Les fichiers texte ne peuvent essentiellement stocker que du contenu composé de caractères limités tels que des chiffres, du texte, des signes de ponctuation, etc. Les fichiers binaires n'ont aucune contrainte de caractères et peuvent stocker des images, de l'audio, de la vidéo et d'autres données à volonté.

En utilisant l'exemple du stockage des nombres, vous pouvez voir clairement la différence dans le contenu de stockage des fichiers texte et des fichiers binaires. Par exemple, pour stocker le numéro 1234567890, le fichier texte doit stocker les codes ASCII des dix nombres 0 à 9. La représentation hexadécimale correspondante est :

, qui occupe 10 octets ; la représentation binaire correspondante de 1234567890 est ". 31 32 33 34 35 36 37 38 39 30", occupant 4 octets (la représentation binaire est de 32 bits, un octet est de 8 bits), et la représentation hexadécimale stockée dans le fichier est (big endian) : ‭0100 1001 1001 0110 0000 0010 1101 0010. 49 96 02 D2

Les fichiers texte stockent le contenu en

caractères et les fichiers binaires stockent le contenu en octets. C'est la différence la plus essentielle entre les deux fichiers. Sur la base de cette caractéristique, certaines conclusions communes peuvent être déduites : les fichiers binaires sont souvent plus compacts que les fichiers texte et occupent moins d'espace ; les fichiers texte sont plus conviviaux et peuvent être édités de manière WYSIWYG ; ouvert, etc.

En regardant l'éditeur de texte, les fichiers binaires sont souvent tronqués. Par exemple, un fichier binaire stocke un entier 1234 (quatre octets), qui est exprimé en hexadécimal comme :

. Après avoir ouvert l'éditeur de texte et l'avoir interprété caractère par caractère, vous constaterez que ces octets ne peuvent pas épeler les caractères affichables, vous devez donc les traiter comme du charabia. La raison de ce code tronqué est que l'éditeur de texte ne peut pas analyser correctement le flux d'octets, c'est pourquoi les fichiers binaires doivent être ouverts avec un logiciel spécial. Par exemple, un fichier jpg doit être ouvert avec un logiciel de visualisation d’images. S’il est ouvert avec un lecteur de musique, c’est fini ! Les fichiers vidéo doivent être ouverts avec un lecteur et un logiciel de compression, alors commençons ! 00 00 04 D2

Format de fichier

Après avoir compris la différence entre les fichiers texte et les fichiers binaires, examinons le format de fichier. Nous savons que Windows reconnaît le format de fichier en fonction de l'extension du fichier et appelle le programme correspondant pour ouvrir le fichier ; dans (comme) les systèmes Unix, l'extension est facultative, alors comment savoir quel est le format du fichier ?

Heureusement, il existe la commande file, qui peut nous indiquer dans quel format se trouve le fichier. L'extension du fichier n'est pas la différence essentielle dans le format de fichier, c'est le contenu qui l'est. Remplacez a.zip par a.txt/a.jgp/a.mp3. Quel que soit le nom du fichier, le fichier révélera sa forme originale : Zip archive data, at least v1.0 to extract.

Encodage

Après avoir parlé du fichier, parlons de l'encodage dans le contenu du fichier. Il existe 127 caractères ASCII courants. Il n'y a pas d'encodage à dire. De toute façon, presque toutes les méthodes d'encodage sont compatibles avec celui-ci. Les caractères codés et multi-octets, les méthodes de codage et l'ordre des octets sont les problèmes qui préoccupent les programmeurs. Pour un caractère chinois, le codage GBK nécessite deux octets, et le caractère boutien de la machine locale doit être pris en compte pour déterminer la forme finale de stockage ; lors de la communication réseau, il doit être converti en ordre d'octets réseau (big endian) afin que le récepteur puisse analysez-le normalement. Si les développeurs ne sont pas familiers avec le codage des caractères et rencontrent des caractères tronqués lors de la communication, le débogage sera difficile.

La formulation de la norme UCS (Universal Multiple Octet Coded Character Set) permet aux développeurs d'éviter les jeux de caractères multi-octets confus. Dans la norme UCS, tous les caractères ont des points de code uniques et les caractères correspondants peuvent être trouvés en fonction des points de code. UCS utilise deux octets pour représenter un point de code (la norme UCS-4 est de 4 octets), correspondant à un caractère. Parce qu'il utilise deux octets, il peut accueillir 2 ^ 16-1 (6w+) caractères, ce qui correspond essentiellement aux caractères couramment utilisés dans divers pays (UCS-4 peut théoriquement accueillir jusqu'à 2 milliards de caractères et accueille actuellement plus de 16 W de caractères). Notez qu'UCS n'est qu'une norme qui stipule la correspondance biunivoque entre les points de code et les caractères, mais ne définit pas comment les stocker dans l'ordinateur.

Le travail de stipulation de la méthode de stockage des caractères Unicode est complété par l'UTF (Unicode Transformation Format). Les solutions les plus couramment utilisées sont UTF-16 et UTF-8. UTF-16 utilise deux octets pour représenter un caractère. Les schémas de codage de caractères par défaut pour les plateformes Windows, MacOS et Java sont UTF-16. Puisqu'il y a deux octets, il existe deux schémas : big-endian et small-endian. Pour les fichiers contenant uniquement des caractères ASCII, l'utilisation de l'encodage UTF-16 entraîne un gaspillage important d'espace (gaspillage de 50 % du stockage). Le schéma d'encodage UTF-8 proposé par Ken Thompson (inventeur du langage C) et Robe Pike (inventeur du langage Go). Il est rapidement devenu populaire. UTF-8 est un flux à un octet, il n'y a aucun problème d'ordre des octets et aucune nomenclature n'est requise. UTF-8 est actuellement le standard Web commun.

Correspondance

La plage de valeurs de USC-2 est U+0000~U+FFFF, et la relation correspondante avec UTF-8 est la suivante :

十六进制 二进制
0000 0000-0000 007F 0xxxxxxx
0000 0080-0000 07FF 110xxxxx 10xxxxxx
0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

从编码可以看出,与二进制相比,浪费了很多空间。不过这也没办法,可显示的字符更容易阅读和理解,人类很难抗拒这个诱惑。

UTF-8转换规则为: 1. 如果某字节第一位是 0 ,那么判定为 ASCII 字节,除了 0 外余下的 7 位是 ASCII 码,所以 UTF-8 是兼容 ASCII 码的; 2. 如果第一个字节是 1 ,那么连续的几个 “1” 代表从这个字符开始,后面连续的几个字节其实是一个字位,且后面的字节都要以10开头。

了解如上规则,我们的程序便可轻松的处理UTF-8编码的字节流。例如要找出“中”的UTF-8编码,则可以这样处理(注意文件是UTF-8编码):

$char = "中";
$length = strlen($char);
$bytes = pack("a" . $length, $char);echo "UTF-8:" . bin2hex($bytes) . "\n";
// 或者echo "UTF-8:";for ($index = 0; $index < $length; ++ $index) 
{    echo bin2hex($char{$index});
}echo PHP_EOL;

也可以写出针对UTF-8编码的strlen函数:

function myStrlen(string $string){
    $slen = strlen($string);
    $mlen = 0;
    $maxByteLength = 4;
    $maxOffset = 7;    for ($i = 0; $i < $slen; ++ $i) {
        $byte = ord($string{$i});        // 从01xxxxxx开始对比,直到11110xxxx 10xxxxxx 10xxxxxx 10xxxxxx。只需要对比第一个字节即可
        for ($offset = 0; $offset < $maxByteLength; ++ $offset) {
            $result = $byte & (1 << ($maxOffset - $offset));            if ($result === 0) {
                $i += $offset;
                ++ $mlen;                break;
            }
        }
    }    return $mlen;
}

$string = "Coder不是工程师!";echo "mb_strlen:" . mb_strlen($string) . "\n";echo "mStrlen:" . myStrlen($string) . "\n";

相关推荐:

关于字符编码问题的详细介绍

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn