Dans le développement de PHP, nous devons parfois emballer plusieurs données en chaînes binaires au format spécifié, ce qui est pratique pour la transmission réseau ou le stockage de fichiers. La fonction du pack fourni par PHP peut atteindre cette exigence, mais elle nécessite de passer dans des chaînes de format complexes, et les formats de différents scénarios varient considérablement. Cet article présentera comment utiliser la fonction Pack pour encapsuler une fonction d'emballage générale qui prend en charge plusieurs formats pour améliorer la réutilisabilité et la flexibilité du code.
La syntaxe de base de la fonction du pack est:
string pack(string $format, mixed ...$values)
Le format $ spécifie le format, comme C représente les caractères non signés, N représente un entier endian endian Big-Endian en Endan 16 bits, etc.
$ Les valeurs sont des données dans le format correspondant.
Par exemple, emballez deux personnages non signés et un entier Big-endian 16 bits:
$data = pack('CCn', 0x01, 0x02, 0x1234);
La fonction que nous voulons résumer:
Accepte une chaîne de format et un tableau de valeurs correspondant.
Package automatique les valeurs une par une selon la chaîne de format.
Prend en charge les types de formats communs et est pratique pour l'expansion.
Gérer les erreurs qui décalagent les paramètres et les formats.
Exemple de signature de fonction:
function universalPack(string $format, array $values): string
Ce qui suit est une implémentation de base qui prend en charge les formats C , N , N , A, etc.:
function universalPack(string $format, array $values): string {
$result = '';
$formatLength = strlen($format);
$valueIndex = 0;
for ($i = 0; $i < $formatLength; $i++) {
$char = $format[$i];
$repeat = 1;
// Détecter s'il y a des doublons,commea4、C2attendez
if (isset($format[$i + 1]) && ctype_digit($format[$i + 1])) {
$repeat = (int)$format[$i + 1];
$i++;
}
for ($r = 0; $r < $repeat; $r++) {
if (!isset($values[$valueIndex])) {
throw new InvalidArgumentException("Le nombre de valeurs ne correspond pas au format");
}
$value = $values[$valueIndex];
$valueIndex++;
switch ($char) {
case 'C': // Personnages non signés
$result .= pack('C', $value);
break;
case 'n': // 16Big Big Endan octet Order
$result .= pack('n', $value);
break;
case 'N': // 32Big Big Endan octet Order
$result .= pack('N', $value);
break;
case 'a': // NULRemplir la corde,Se promenerrepeatDécider
if ($repeat < 1) {
throw new InvalidArgumentException("aLe format doit être spécifié en longueur");
}
$str = str_pad(substr($value, 0, $repeat), $repeat, "\0");
$result .= $str;
// aTraitement du format en même tempsrepeat,valueIndexAucun incrément
$valueIndex--;
break;
default:
throw new InvalidArgumentException("Caractères de format non pris en charge: $char");
}
}
}
return $result;
}
Supposons que vous souhaitiez emballer un paquet de données, la structure est:
Numéro de commande 1 octet ( c )
2 octets Longueur de données ( n )
ID de données de 4 octets ( n )
Contenu de données de 10 octets (String, A10 )
Exemple d'appel:
$command = 0x01;
$length = 14;
$dataId = 123456;
$content = "hello";
$packed = universalPack('CnNa10', [$command, $length, $dataId, $content]);
echo bin2hex($packed);
La sortie est:
01000e0001e24068656c6c6f0000000000
Les fonctions de pack sont très puissantes, mais le format et la valeur sont sujets aux erreurs lorsqu'ils sont utilisés directement.
Encapsulez une fonction universelle UniversalPack pour simplifier l'emballage des données multi-format.
Les fonctions peuvent continuer à être améliorées en fonction des besoins réels, tels que la prise en charge de plus de formats, la prise en charge de l'ordre des petites-endiviens, etc.
Dans les projets réels, la fonction de déballage peut également être combinée avec la fonction de déballage pour atteindre la fonction de déballage par les pairs.