Lors du traitement des données binaires dans PHP, Pack () et unback () sont de puissantes paires de fonctions qui peuvent convertir les données en chaînes binaires ou analyser les valeurs d'origine. Cependant, de nombreux développeurs rencontrent souvent un problème commun lors de l'utilisation de ces deux fonctions: les données emballées avec Pack () semble brouillé ou des exceptions lors du déballage avec unback () . Cette situation est principalement causée par les chaînes de format malarices.
Supposons que vous ayez un entier et une chaîne et que vous souhaitez les emballer dans un magasin de données binaires ou un transfert, puis déballer et le récupérer:
$data = pack('N/A4', 12345678, 'test');
De nombreuses personnes peuvent penser que le code ci-dessus emballera correctement un entier 12345678 et un «test» de chaîne. Mais lors de l'exécution, vous constaterez que les données résolues par Unleback () ne sont pas comme vous le souhaitez:
$unpacked = unpack('Nnum/A4str', $data);
print_r($unpacked);
La sortie peut être vide, brouillée ou même avertissement de déclenchement.
raison? La chaîne de format est mal écrite.
Les chaînes de format de pack () et de dismack () doivent correspondre exactement, non seulement dans l'ordre, mais aussi en longueur, en taille et en type.
Analyons attentivement l'exemple d'erreur ci-dessus:
$data = pack('N/A4', 12345678, 'test');
Cette chaîne de format n'est pas réellement légale. Parce que n représente un long de 4 octets unsignet (Big-Endien), mais / est un caractère illégal (il n'a aucun sens dans ce contexte). La véritable façon de l'écrire devrait être:
$data = pack('Na4', 12345678, 'test');
Lors du déballage, vous devez également aligner strictement le format:
$unpacked = unpack('Nnum/a4str', $data);
À ce stade, la sortie est ce que nous attendons:
Array
(
[num] => 12345678
[str] => test
)
Notez une différence subtile:
A4 signifie "une chaîne remplie d'octets vides", que la chaîne soit si longue ou non;
A4 signifie "une chaîne remplie d'espaces", et l'espace à la fin sera ignoré;
n signifie 2 octets non signés courts (Big Endian);
V signifie 2 octets non signés courts (Little Endian);
N signifie 4 octets non signés longs (Big Endian);
V représente 4 octets non signés longs (Little Endian);
Si vous utilisez la mauvaise lettre, le résultat peut être complètement faux.
Si vous avez affaire à des structures de données multiplateformes ou à des protocoles binaires (comme un protocole de communication client téléchargé à partir de m66.net ), vous devez accorder plus d'attention à la longueur et à l'ordre de la structure de données.
Par exemple, définissez une structure de paquets comme suit:
Numéro de version de 2 octets (UINT16)
Timestamp de 4 octets (Uint32)
ID utilisateur de 8 octets (Uint64)
Nom d'utilisateur de 20 octets (String)
Peut être écrit comme:
$data = pack('nNVa20', 1, time(), 123456789, 'hello');
Le déballage correspondant doit être exactement le même:
$unpacked = unpack('nversion/Ntime/Vuid/a20username', $data);
Mais note: ne confondez pas l'ordre de V et N ! Si le serveur utilise la structure du langage C pour définir que l'ordre des octets est Big-Endian, mais que vous utilisez V (Little-Endian) pour le lire, alors la solution est erronée.
Pour éviter les erreurs de chaîne de format, il est recommandé d'encapsuler les définitions de structure en constantes ou des fonctions clairement commentées pour une maintenance et une collaboration faciles. Par exemple:
define('USER_STRUCT_FORMAT', 'nversion/Ntime/Vuid/a20username');
function encodeUser($version, $time, $uid, $username) {
return pack(USER_STRUCT_FORMAT, $version, $time, $uid, $username);
}
function decodeUser($binary) {
return unpack(USER_STRUCT_FORMAT, $binary);
}
Cela peut éviter les erreurs causées par les chaînes de format d'orthographe manuellement à plusieurs endroits et faciliter également la synchronisation des documents.
L'utilisation de Pack () et Deteback () est un moyen standard de traiter les données binaires en PHP, mais les exigences pour les chaînes de format sont très strictes. Le déballage du code brouillé n'est pas un problème de fonction la plupart du temps, mais un décalage dans les formats. Gardez à l'esprit:
La signification et le nombre d'octets de chaque symbole de format;
L'ordre des petites et des extrémités ne peut pas se tromper;
La commande de déballage et l'ordre d'emballage doivent être cohérentes;
La longueur de la chaîne doit être fixe ou clairement indiquée;
Il est recommandé que l'emballage structurel soit unifié pour une réutilisation facile.
La prochaine fois que vous rencontrerez un code de surclassement () , ne vous précipitez pas pour douter des données, vérifiez d'abord si votre chaîne de format est écrite correctement.