PHP 8.2.12兼容改造:pack函数H类型报错求助
PHP 6.0.0-dev 迁移到 PHP 8.2.12 的pack函数兼容问题解决
问题描述
将基于PHP 6.0.0-dev的十六进制处理代码适配到PHP 8.2.12时,遇到pack函数报错:Warning: pack(): Type H: not enough characters in string。原环境中某字段以i格式处理值0,升级后该字段变为以H8格式处理0,触发上述警告。尝试修改default分支强制使用i格式处理,但导致原本应使用H8格式的字段(如值16000000、0d000000)也被错误转换为i格式,结果混乱。咨询是否需要新增H8格式处理逻辑,并在switch中单独设置case分支解决问题。
输出对比
PHP 8.2.12 输出
i 0 i 0 H8 0 << 异常结果 Warning: pack(): Type H: not enough characters in string in C:\xampp\htdocs\services\parser\include.php on line 683 H8 16000000 H8 0d000000
原PHP 6.0.0-dev 输出
i 0 i 0 i 0 << 原处理结果 H8 16000000 H8 0d000000
核心parser函数代码
function parser($output, $input, $indexing, $blockheader) { global $typearr, $stop_error_msg; $filearray = file($input, FILE_SKIP_EMPTY_LINES); $filesize = sizeof($filearray); $struct = explode("\t", trim($filearray[0])); $col_names = explode("\t", trim($filearray[1])); if ($blockheader == 1) { // Define or replace strsize() function // $block = strsize($struct); $block = count($struct); // Example replacement if ($indexing == 1) $block += 4; $filesize_bin = pack("i", ($filesize - 2)); fwrite($output, $filesize_bin); $blockbin = pack("i", $block); fwrite($output, $blockbin); } for ($i = 2; $i < $filesize; $i++) { $store = 0; $temporary = explode("\t", trim($filearray[$i])); if ($indexing == 1) fwrite($output, pack("i", $i - 2)); for ($st = 0; $st < count($struct) - 1; $st++) { if ($temporary[$st] == '') { $stop_error_msg .= "<br>Empty cell. Probably mistake at excel file:<br>ROW:".($i+1)."<br>COLUMN:".($st+1)."<br>NAME:".$col_names[$st]."<br>DATA:".$temporary[$st]; return false; } if (stristr($struct[$st], 'string[') !== false) { preg_match("/^(string\[)?([\d]+)/", $struct[$st], $str_ret); if (strlen($temporary[$st]) >= $str_ret[2]) { $temporary[$st] = substr($temporary[$st], 0, $str_ret[2] - 1); echo "<br>Warning! Text overflow. Tail of string had been cut: ROW:".($i+1)." COLUMN:".($st+1)." NAME:".$col_names[$st]." DATA:'".$temporary[$st]. "' SIZE:". $str_ret[2]; } $resulthex = pack("a".$str_ret[2], trim(str_replace("\x22\x22\x22\x22", "\x22\x22", $temporary[$st]), "\x22")); fwrite($output, $resulthex); continue; } $type = $typearr[$struct[$st]]['type']; switch($type) { case "xeh": $resulthex = xeh($temporary[$st]); break; case "xeh64": $resulthex = xeh64($temporary[$st]); break; case "clcode": $resulthex = clcode($temporary[$st]); break; case "exclcode": if(($resulthex = exclcode($temporary[$st])) === false) { $stop_error_msg .= " Probably mistake at excel file:<br>ROW:".($i+1)."<br>COLUMN:".($st+1)."<br>NAME:".$col_names[$st]."<br>DATA:".$temporary[$st]; return false; } break; case "ccode": $resulthex = ccode($temporary[$st]); break; case "f": case "d": $trans = array("," => "."); $resulthex = pack($type, strtr("" . $temporary[$st] . "", $trans)); break; case "bulltype": if(($resulthex = bulltype($temporary[$st])) === false) { $stop_error_msg .= " Probably mistake at excel file:<br>ROW:".($i+1)."<br>COLUMN:".($st+1)."<br>NAME:".$col_names[$st]."<br>DATA:".$temporary[$st]; return false; } break; case "bttype": if(($resulthex = bttype($temporary[$st])) === false) { $stop_error_msg .= " Probably mistake at excel file:<br>ROW:".($i+1)."<br>COLUMN:".($st+1)."<br>NAME:".$col_names[$st]."<br>DATA:".$temporary[$st]; return false; } break; case "effbttype": if(($resulthex = effbttype($temporary[$st])) === false) { $stop_error_msg .= " Probably mistake at excel file:<br>ROW:".($i+1)."<br>COLUMN:".($st+1)."<br>NAME:".$col_names[$st]."<br>DATA:".$temporary[$st]; return false; } break; case "stb": if(($resulthex = stb($temporary[$st])) === false) { $stop_error_msg .= " Probably mistake at excel file:<br>ROW:".($i+1)."<br>COLUMN:".($st+1)."<br>NAME:".$col_names[$st]."<br>DATA:".$temporary[$st]; return false; } break; case "stb4": if(($resulthex = stb4($temporary[$st])) === false) { $stop_error_msg .= " Probably mistake at excel file:<br>ROW:".($i+1)."<br>COLUMN:".($st+1)."<br>NAME:".$col_names[$st]."<br>DATA:".$temporary[$st]; return false; } break; case "stb12": if(($resulthex = stb12($temporary[$st])) === false) { $stop_error_msg .= " Probably mistake at excel file:<br>ROW:".($i+1)."<br>COLUMN:".($st+1)."<br>NAME:".$col_names[$st]."<br>DATA:".$temporary[$st]; return false; } break; case "stb16": if(($resulthex = stb16($temporary[$st])) === false) { $stop_error_msg .= " Probably mistake at excel file:<br>ROW:".($i+1)."<br>COLUMN:".($st+1)."<br>NAME:".$col_names[$st]."<br>DATA:".$temporary[$st]; return false; } break; case "res": $resulthex = resource($temporary[0]); break; case "qitid": $resulthex = qitid($temporary[$st]); break; case "lqitem": $resulthex = lqitem($temporary[$st]); break; case "store": if(($resulthex = store($temporary[$st], $store, $temporary[10])) === false) { $stop_error_msg .= " Probably mistake at excel file:<br>ROW:".($i+1)."<br>COLUMN:".($st+1)."<br>NAME:".$col_names[$st]."<br>DATA:".$temporary[$st]; return false; } $store++; break; case "qcode": $resulthex = qcode($temporary[$st]); break; case "spcode": $resulthex = spcode($temporary[$st]); break; case "text": $len = strlen($temporary[$st]); $len = $len + 1; $resulthex=pack("a".$len, $temporary[$st]); $plen=pack("i", $len); fwrite($output, $plen); break; case "param": if(($resulthex = param($temporary[$st], $temporary[$st+1])) === false) { $stop_error_msg .= " Probably mistake at excel file:<br>ROW:".($i+1)."<br>COLUMN:".($st+1)."<br>NAME:".$col_names[$st]."<br>DATA:".$temporary[$st]; return false; } $st++; break; default: echo $type." ".$temporary[$st]."<br>"; $resulthex = pack($type, $temporary[$st]); # error indication is in this script } if(!empty($err_arr) && isset($err_arr['message']) && stripos($err_arr['message'], 'function.date') !== false) { $stop_error_msg .= "<br>Pack error. Probably mistake at excel file:<br>ROW:".($i+1)."<br>COLUMN:".($st+1)."<br>NAME:".$col_names[$st]."<br>DATA:".$temporary[$st]; return false; } fwrite($output, $resulthex); } } return true; }
修改尝试及结果
修改后的default分支代码
default: echo "i " . $temporary[$st] . "<br>"; $resulthex = pack("i", $temporary[$st]); # error indication is in this script
修改后输出
i0 i0 i0 << 异常结果 i16000000 << 错误转换为i格式 i0d000000 << 错误转换为i格式
解决方案建议
需要在switch分支中单独添加case "H8"的处理逻辑,针对十六进制字符串长度不足8位的情况做补零处理,同时保留原有的格式映射逻辑,避免混淆不同类型的字段:
switch($type) { // ... 保留原有所有case分支不变 case "H8": // 将输入值补零到8位十六进制字符,确保pack函数不会报错 $hex_value = str_pad($temporary[$st], 8, '0', STR_PAD_LEFT); echo "H8 " . $hex_value . "<br>"; $resulthex = pack("H8", $hex_value); break; default: echo $type." ".$temporary[$st]."<br>"; $resulthex = pack($type, $temporary[$st]); }
处理效果说明
- 对于值为
0的H8类型字段,会被补全为00000000,执行pack("H8")时不会触发警告 - 原本应使用H8格式的
16000000、0d000000会保持原有格式处理,不会被错误转换为i格式 - 原
i格式字段依然会按default分支(当type为"i"时)正常处理
另外需确认$typearr中的类型映射是否正确,确保需要用i格式的字段对应的type值为"i",需要用H8格式的字段对应的type值为"H8",避免类型映射错误导致的兼容问题。
内容的提问来源于stack exchange,提问作者Willy Sudwihartono
相关产品推荐
相关产品推荐

