Удаленно хранятся данные в ASCII.
Пример данных (во втором столбце в 16ой системе для понимания):
1) ]�1�*..� 5D 83 31 91 2A 12 00 D4
2) ]�1�*.� 5D 83 31 91 2A 1C 00 B9
3) ]�1�*‑�� 5D 83 31 91 2A 1E FF F0
4) ]�1�*.� 5D 83 31 91 2A 1F 0E F9
Я получаю эти данные, преобразую их в 16ые при помощи функции bin2hex() и сохраняю в таблице. В другом месте вытаскиваю из таблицы, преобразую обратно функцией hex2bin() и отправляю на обработку.
Пункты 1 и 2 содержат '00' (NUL символ), который никак не отображается в PHP, хотя и идет в счетчик символов var_dump(). В итоге записи, которые содержат этот символ не могут корректно обработаться. Насколько я смог понять, это связано с тем, что NUL символ не учитывается/теряется/удаляется/не может обработаться php (в редакторе даже не отображается <0x00>).
Пытался как-то выловить данный символ, чтобы попробовать произвести замену, но не смог найти способа поймать "ничего".
Совершенно зашел в тупик. Буду рад решению данной проблемы или идеям в какую сторону копать. Удаленные данные изменять нет возможности.
Код отвечающий за отправку в MQ строки такого вида "]�1�*..�":
$rcvQueue = self::getInstance()->openQueue(MQ_REASON_QUERY_ID);
if (!$rcvQueue instanceof MQObject) {
throw new \Exception(' $rcvOueue не MQObject - не получилось открыть очередь $rcvQueue');
}
$getOpts = [
'Version' => MQSERIES_MQGMO_VERSION_2,
'Options' => [MQSERIES_MQGMO_FAIL_IF_QUIESCING, MQSERIES_MQGMO_WAIT],
'WaitInterval' => $waitInterval, //10 sec
'MatchOptions' => [MQSERIES_MQMO_MATCH_CORREL_ID]
];
$MQMD = [
'MsgId' => MQSERIES_MQMI_NONE,
'CorrelId' => $messageId
];
$inMessage = $rcvQueue->get($getOpts, $MQMD);
if ($inMessage instanceof MQMessage) {
$oData = new \SimpleXMLElement($inMessage->data());
} else {
throw new \Exception(' MQ сервер вернул $inMessage который не MQMessage ');
}
PHP имеет несколько вариантов функций, выполняющих одно и то же действие. При обработке бинарных данных Вам стоит обращать внимание на описание функций, которые Вы используете. В частности, среди встроенных функций PHP есть помеченные как "бинарно-безопасная", т.е. корректно обрабатывающая двоичные данные и не пытающаяся как-либо их интерпретировать. Например, strcasecmp — Бинарно-безопасное сравнение строк без учета регистра.
Не забудьте также о возможности обращаться к любому байту в строке как элементу массива.
В то же время если Вы хотите далее обрабатывать данные как строку обычными функциями PHP, Вам действительно необходимо избавиться от 0x00
в ее теле. Для этого можно воспользоваться функцией str_replace()
:
$cleanString = str_replace("\0", '', $originalString);
На самом деле сложно дать какие-либо более конкретные рекомендации без уточнения по интерпретации пресловутых "данных", которые "обрабатываются". Уточните, может быть это данные в какой-либо конкретной кодировке, отличной от ASCII? И именно из-за этого у Вас проблемы с их обработкой, а вот если знать кодировку и использовать mbstring, то проблем не будет? И, кстати, среди функций mbstring есть и mb_detect_encoding — Определение кодировки символов - попробуйте прогнать свои входные данные через нее, вдруг она определит кодировку и "эти данные" обретут вменяемый смысл?
Прошло много времени, но я всё же решил проблему, поэтому выкладываю её описание и решение.
Суть проблемы:
На сайте происходит взаимодействие с IBM WebSphere MQ через PHP библиотеку https://github.com/rstmpw/ibmmq с использованием pecl расширения mqseries https://github.com/php/pecl-networking-mqseries.
Общение происходит через сообщения с уникальными генерируемыми MsgId состоящими из байтов. По-умолчанию генерация происходит в pecl расширении на основании текущих даты и времени. И здесь начинается сама проблема - в некоторые моменты генерируются MsgId, которые содержат нулевые байты, причем иногда они идут сплошным потоком до 12 недель.
Расширение mqseries работает с сишными null-терминированными строками и при копировании строки прекращает обработку на первом нулевом байте (файл mqseries_helper.c, макрос MQSERIES_SETOPT_RESBYTES, строка 87).
Соответственно, MsgId обрезается и возможности корректно его обработать не остается.
Решение:
Генерация MsgId со стороны сайта.
У меня на проекте есть обертка над библиотекой rstmpw/ibmmq для основных методов работы с ней. Нас интересует отправка сообщения в MQ:
public static function putMessageToMQ($outMessage)
{
$sendQueue = self::getInstance()->openQueue(MQ_SEND_QUERY_ID);
if (!($sendQueue instanceof MQObject)) {
throw new \Exception('$sendQueue не MQObject - не получилось открыть очередь отправки сообщения');
}
$outMessage->property('MsgId', hex2bin('414d5120') . openssl_random_pseudo_bytes(20));
$sendQueue->put($outMessage);
$messageId = $outMessage->property('MsgId');
return !empty($messageId) ? $messageId : false;
}
$sendQueue - объект класса MQObject из библиотеки.
$outMessage - объект класса MQMessage из библиотеки.
Интересующая нас строка в которой мы заранее задаём свойство MsgId для нашего сообщения отправляемого в MQ:
$outMessage->property('MsgId', hex2bin('414d5120') . openssl_random_pseudo_bytes(20));
Из документации MQ часть hex2bin('414d5120') - "AMQ " обязательна. А через openssl_random_pseudo_bytes мы генерируем псевдослучайную последовательность байт необходимой длины (в моем случае было 24 байта). Базируйтесь на своем MsgId.
Отступление:
У меня в проекте было много других проблем связанных с MQ прежде чем я добился корректной работы функционала, но они относятся только функционалу самого сайта и не будут нести полезной информации.
Также ещё раз спасибо ответу andreymal, который помог обратить внимание на конкретную область.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Решил наконец освоить что-то новое, перешел на linuxПеренёс файлы проекта на ноутбук, развернул xampp, открываю проект, и вижу, что данные из таблиц...
Как правильно реализовать регистрацию и авторизацию в мобильном приложении, подходит ли для этого RESTful веб приложение, какой протокол для...