Я хочу создать файл в PHP со следующими условиями:
Больше информации:
Позвольте мне привести пример:
Score = 64
Name = Jack
Last Name = Saliv
Age = 21
By default, this file is generated as follows:
64JackSaliv21
And the Hex value becomes this value:
36344A61636B53616C69763231
But I want to get the following value:
䃿JackSaliカ
And the Hex value is:
FFFEFF404A00610063006B00530061006C00690076FFFEFF15
.
В следующих темах я не получил желаемых результатов!
@ChrisHaas, Да, значение UTF-16 (LE) 64 равно 36 00 34 00, но перед этим значение 64 должно быть преобразовано в шестнадцатеричное, а затем должно быть сохранено шестнадцатеричное значение 64, равное 40. в финальном файле.
Итак, вы хотите сохранить число 64, а не строку 64. UTF предназначена для кодирования символов, а не чисел. Итак, 40 — это не UTF (LE или любая другая) кодировка 64, это просто десятичное число 64, преобразованное в основание 16. Я просто хочу внести ясность. Единственным материалом UTF будет их имя. Верно?
Строка, которую вы говорите, что хотите, это полная ерунда. Это два однобайтовых целых числа, хранящихся в двоичном формате, каждому из которых предшествует бессмысленная спецификация UTF16LE со строкой UTF16LE в середине. Пожалуйста, объясните, почему вы думаете, что вам нужна эта строка.
@ChrisHaas, да, в какой-то степени, в конечном итоге я хочу подойти к чему-то вроде этого ответа: stackoverflow.com/a/76192895/21197857
Можете ли вы показать, что вы пробовали раньше, чтобы решить эту проблему?






Читая ваши Delph вопросы, вместе с вашими комментариями, я действительно не до конца понимаю, что все это должно делать. Однако, учитывая входные данные вместе с выходными, я могу, по крайней мере, приблизиться к ним и сделать их точными с некоторыми дополнительными исправлениями.
По сути, вы можете использовать mb_convert_encoding , чтобы получить UTF-16LE, а затем вы можете получить байты в виде шестнадцатеричных строк, используя распаковать . Чтобы преобразовать десятичные числа в шестнадцатеричные строки, просто используйте dechex.
Из вашего примера я не уверен, почему десятичное число 64 при преобразовании в шестнадцатеричную строку 40 записывается как FF 40, а не только 40 или 40 00, но к переменной $finalStringWithNumbersPadded добавляется FF. Если бы возраст или оценка были больше, чем 255, я не совсем уверен, что делать, так как FF это 1111 1111 и полностью заполнен.
Кроме того, я предполагаю, что у вас есть опечатка в ваших ожидаемых байтах, символ для фамилии должен быть 76 00, а не только 76.
Надеюсь, код говорит сам за себя:
$score = 64;
$firstName = 'Jack';
$lastName = 'Saliv';
$age = 21;
$expected = 'FFFEFF404A00610063006B00530061006C00690076FFFEFF15';
$expectedCorrected = 'FFFEFF404A00610063006B00530061006C0069007600FFFEFF15';
// Convert to UTF-16LE and get hex, https://stackoverflow.com/a/16080439/231316
$nameAsUtf16LE = unpack('H*', mb_convert_encoding($firstName.$lastName, 'UTF-16LE', 'UTF-8'));
// UTF-16LE BOM
$utf16LeBom = 'FFFE';
// Convert to hex strings
$scoreAsHex = dechex($score);
$ageAsHex = dechex($age);
$finalString = sprintf(
'%1$s%2$s%3$s',
$utf16LeBom.$scoreAsHex,
strtoupper($nameAsUtf16LE[1]), // This is 1-based, not 0-based
$utf16LeBom.$ageAsHex,
);
$numberPadding = 'FF';
$finalStringWithNumbersPadded = sprintf(
'%1$s%2$s%3$s',
$utf16LeBom.$numberPadding.$scoreAsHex,
strtoupper($nameAsUtf16LE[1]), // This is 1-based, not 0-based
$utf16LeBom.$numberPadding.$ageAsHex,
);
echo 'Calculated : '.$finalString;
echo PHP_EOL;
echo 'Padded : '.$finalStringWithNumbersPadded;
echo PHP_EOL;
echo 'Expected : '.$expected;
echo PHP_EOL;
echo 'Expected Corrected : '.$expectedCorrected;
assert($finalStringWithNumbersPadded === $expectedCorrected);
/* Output:
Calculated : FFFE404A00610063006B00530061006C0069007600FFFE15
Padded : FFFEFF404A00610063006B00530061006C0069007600FFFEFF15
Expected : FFFEFF404A00610063006B00530061006C00690076FFFEFF15
Expected Corrected : FFFEFF404A00610063006B00530061006C0069007600FFFEFF15
*/
Демо: https://3v4l.org/XTdjA#v8.2.6
Редактировать
Чтобы записать строку шестнадцатеричных символов на диск в виде двоичных данных, вы можете использовать pack:
$bindata = pack('H*', 'FFFEFF404A00610063006B00530061006C0069007600FFFEFF15');
file_put_contents('testing.data', $bindata);
Спасибо, это именно то, что я хотел, к сожалению, я не могу оставить отзыв (вам нужно не менее 15 репутации, чтобы проголосовать), но я определенно очень рад, что на этом сайте есть такие профессиональные пользователи, как вы.
Можно ли дать объяснение этим значениям и что они делают? strtoupper($nameAsUtf16LE[1]) Я имею в виду это значение [1]. И какая польза от этого значения «%1$s%2$s%3$s»? Нужны ли этим кодам специальные ресурсы, программное или аппаратное обеспечение для работы на хосте? (Оказывают ли они давление на хозяина?)
Могу ли я добавить больше значений в команду sprintf? Например, почтовый индекс или идентификационный номер (тип оценки и возраст), а также адрес и описание (например, имя и фамилия)? Если я захочу добавить эти значения в коды, какими будут коды?
Я странный человек, который всегда использует полную форму для команд printf . В строке %1$s1$ означает «первый предоставленный заполнитель», а s означает интерпретировать его как строку. Вы никоим образом не обязаны использовать printf вообще, я просто сделал это, потому что иногда я думаю, что это облегчает чтение вместо объединения, в этом контексте нет никакой разницы, однако вы также можете делать с ним все, что хотите: 3v4l.org/lPrUK
$nameAsUtf16LE — это переменная, созданная путем преобразования предоставленной строки в UTF-16LE, а затем запуска функции unpack. pack и unpack — это действительно странные функции, в которые вы могли бы потратить часы, но просто знайте, что unpack в этом случае возвращает вам шестнадцатеричные значения предоставленной строки. Результатом unpack является массив, и по внутренним причинам есть только одно значение, и оно находится в индексе 1, следовательно, $nameAsUtf16LE[1]. strtoupper() просто заставляет шестнадцатеричный код быть в верхнем регистре, чтобы соответствовать вашим образцам, fffe против FFFE.
По большому счету, я не думаю, что этот код вообще будет заметен. Если вы нажмете предоставленную ссылку 3v4l, вы увидите вкладку «Производительность», которая показывает незначительность. «Нужны ли этим кодам специальные ресурсы… для запуска на хосте» — Просто PHP с расширением mbstring, которое, как мне кажется, в наши дни довольно часто устанавливается по умолчанию.
Отлично, какой метод следует использовать для сохранения конечного значения (например, FFFE404A00610063006B00530061006C0069007600FFFE15)? (Я хочу, чтобы конечное значение было сохранено как Hex в файле, то есть, если мы откроем файл с помощью Hex Editor, это значение будет отображать FFFE404A00610063006B00530061006C0069007600FFFE15) Я использовал метод stackoverflow.com/a/9973915/21197857 , но не сохранил шестнадцатеричное значение, а сохранил само значение в виде строки!
@AdamLuper, я добавил внизу образец записи на диск. Я отмечу, что попытка создать строковое представление данных для визуальной проверки, а затем преобразовать его обратно в двоичный файл, как мы делаем, немного странная/неэффективная. Тем не менее, если вы не обрабатывали много данных, я не думаю, что это имеет большое значение, и поскольку это немного странно (без обид), это значительно упрощает визуальную отладку и, возможно, тестирование.
Вы преподали мне много новых уроков, я вам благодарен. В основном я хотел задать этот вопрос на PHP, чтобы узнать, и я многому научился, и я действительно извиняюсь, если вопросы, которые я задавал, были простыми и странными, потому что мне было очень интересно узнать результаты кода с похожим подходом на двух разных платформах! ! (Delphi и PHP) и я не представлял, что PHP имеет возможность быть настолько гибким, конечно я думаю, что эти коды не очень полезны для других или устарели или может быть вообще бесполезны для кого-то еще, но эти советы от Вы узнали, что это было здорово для меня.
Я столкнулся с проблемой, и я хочу найти для нее простое решение, если шестнадцатеричные значения Age и Score являются отдельными буквами (например, значения от 10 до 15, чьи шестнадцатеричные значения становятся A, B, C, D, E, F и т. д.) Как мне поставить ноль перед этими однобуквенными значениями, чтобы эти значения не смешивались с другими значениями рядом с ними (или что я должен сделать, чтобы преобразовать нечетное значение в четное значение! Например, если не ошибаюсь думаю значение А должно быть 0А) чтобы однобуквенное значение стало двухбуквенным? (Учитывая, что шестнадцатеричные значения представляют собой две буквы -> 00)
Вы прыгаете между несколькими различными кодировками и системами счисления, что действительно создает путаницу. и вы также (эффективно) создаете двоичный формат файла. В начале и ближе к концу по непонятным причинам есть спецификация, поскольку мы отметили, что прикрепление спецификации к числовым данным не имеет никакого смысла. Большинство/все форматы двоичных файлов имеют четко определенную структуру, либо записи фиксированной длины, сигилы для интерпретации/завершения данных, количество байтов для структур переменной длины или указатели байтов. Как только этот файл станет «усовершенствованным», я не совсем уверен, как вы его прочтете.
В любом случае, еще один способ преобразовать целое число в шестнадцатеричную строку — использовать sprintf, см.: stackoverflow.com/a/47789382/231316 , но вам также может понадобиться преобразовать порядок байтов: stackoverflow.com/a/ 35100432/231316
Может я не правильно думаю, но разве строка
64не будет представлена как36 00 34 00в UTF-16 LE?