在标准PHP库中,是否有将字符串转换为二进制,然后再转回字符串的方法?
为了澄清我的意图,我要把密码存储在数据库中。 我将首先使用哈希函数进行转换,然后最终以二进制形式存储。
我发现最好的方法是使用此函数。 似乎可以同时进行哈希和二进制输出。
在标准PHP库中,是否有将字符串转换为二进制,然后再转回字符串的方法?
为了澄清我的意图,我要把密码存储在数据库中。 我将首先使用哈希函数进行转换,然后最终以二进制形式存储。
我发现最好的方法是使用此函数。 似乎可以同时进行哈希和二进制输出。
pack
和base_convert
。// Convert a string into binary
// Should output: 0101001101110100011000010110001101101011
$value = unpack('H*', "Stack");
echo base_convert($value[1], 16, 2);
// Convert binary into a string
// Should output: Stack
echo pack('H*', base_convert('0101001101110100011000010110001101101011', 2, 16));
当然可以!
那么...
$bin = decbin(ord($char));
... 然后再返回来。
$char = chr(bindec($bin));
str_pad(..., 8, 0, STR_PAD_LEFT)
:) - Yoshi一个字符串只是一系列字节的序列,因此在PHP中它实际上是二进制数据。您到底想做什么?
编辑
如果您想在数据库中存储二进制数据,问题通常是数据库中的列定义。PHP不区分二进制数据和字符串,但数据库会。例如,在MySQL中,您应该将二进制数据存储在 BINARY
, VARBINARY
或 BLOB
列中。
另一种选择是使用base64_encode
对PHP字符串进行编码,并将其存储在数据库中的某个 VARCHAR
或 TEXT
列中。但请注意,当使用base64_encode
时,字符串的长度将增加。
但是,您需要将其转换为数据库列定义所期望的格式。
在 PHP 中,任何字符串(直到 5.3 及以后版本)都是二进制字符串。这意味着它只包含二进制数据。
(这没有改变,PHP 6 没有实现,本答案的其余部分可能仅具有历史意义,它仍然可以工作,但我IRC中的 b'string'
已被删除 - 或者没有。)
但是,由于向后兼容 PHP 6,您可以将字符串显式转换为二进制:
$string = 'my binary string';
$binary = b'my binary string';
$string = $binary; // "convert" binary string into string
$binary = $string // "convert" string into binary string
我发现最简单的方法是将其转换为十六进制而不是字符串。如果这对您有用:
$hex = bin2hex($bin); // It will convert a binary data to its hex representation
$bin = pack("H*" , $hex); // It will convert a hex to binary
或者
$bin = hex2bin($hex); // Available only on PHP 5.4
echo bindec("00000001") . "\n";
echo bindec("00000010") . "\n";
echo bindec("00000100") . "\n";
echo bindec("00001000") . "\n";
echo bindec("00010000") . "\n";
echo bindec("00100000") . "\n";
echo bindec("01000000") . "\n";
echo bindec("10000000") . "\n";
echo bindec("01000001") . "\n";
# big binary string
echo bindec("111010110111011110000110001")."\n";
1
2
4
8
16
32
64
128
65
123452465
# convert to binary strings "00000001"
echo decbin(1) . "\n";
echo decbin(2) . "\n";
echo decbin(4) . "\n";
echo decbin(8) . "\n";
echo decbin(16) . "\n";
echo decbin(32) . "\n";
echo decbin(64) . "\n";
echo decbin(128) . "\n";
# convert a ascii character
echo str_pad(decbin(65), 8, 0, STR_PAD_LEFT) ."\n";
# convert a 'char'
echo str_pad(decbin(ord('A')), 8, 0, STR_PAD_LEFT) ."\n";
# big number...
echo str_pad(decbin(65535), 8, 0, STR_PAD_LEFT) ."\n";
echo str_pad(decbin(123452465), 8, 0, STR_PAD_LEFT) ."\n";
上述输出:
1
10
100
1000
10000
100000
1000000
10000000
01000001
01000001
1111111111111111
111010110111011110000110001
在2021年,任何人都可以使用SteeveDroz答案;但不幸的是,这仅适用于一个字符。因此,我将其放入for循环中,循环遍历并更改字符串的每个字符。
编辑:我刚刚意识到,我制作的binary_encode函数没有将字符转换为8位(这非常重要),它将它们转换为6-7位,但幸运的是,我只需要在前面添加所需的额外0即可使其成为8位。我更新了下面的编码函数。 另外,我不需要修复解码函数,因为它可以使用前置的0来工作,也可以不使用 :)
function binary_encode($str){
# Declare both Binary variable and Prepend variable
$bin = (string)""; $prep = (string)"";
# Iterate through each character of our input ($str)
for($i = 0; $i < strlen($str); $i++){
# Encode The current character into binary
$bincur = decbin( ord( $str[$i] ) );
# Count the length of said binary
$binlen = strlen( $bincur );
# If the length of our character in binary is less than a byte (8 bits); Then
# For how ever many characters it is short;
# it will replace with 0's in our Prepend variable.
if( $binlen < 8 ) for( $j = 8; $j > $binlen; $binlen++ ) $prep .= "0";
# Build our correct 8 bit string and add it to our Binary variable
$bin .= $prep.$bincur." ";
# Clear our Prepend variable before the next Loop
$prep = "";
}
# Return the final result minus the one whitespace at the end
# (from our for loop where we build the 8 bit string
return substr($bin, 0, strlen($bin) - 1);
}
function binary_decode($bin){
$char = explode(' ', $bin);
$nstr = '';
foreach($char as $ch) $nstr .= chr(bindec($ch));
return $nstr;
}
使用方法:
$bin = binary_encode("String Here");
$str = binary_decode("1010011 1110100 1110010 1101001 1101110 1100111 100000 1001000 1100101 1110010 1100101");
http://sandbox.onlinephpfunctions.com/code/2553fc9e26c5148fddbb3486091d119aa59ae464
http://sandbox.onlinephpfunctions.com/code/1d71888cd41371646431f9914ccd86cf5ef6303e
var bytes = new byte[] { 0x41, 0x42, 0x43 };
但是,显然这不是一种好的方式来表示这些字节!字符串"ABC"是一个高效的表示方法,因为实际上它是相同的BLOB(只是在这种情况下它不是那么大)。
在实践中,您通常会从返回字符串的函数中获取BLOBs - 比如哈希函数或其他内置函数,如fread。
在罕见的情况下(但在尝试/原型时并不罕见),您需要从一些硬编码的字节构造字符串,我不知道比将“十六进制字符串”转换为PHP中通常称为“二进制字符串”的任何东西更有效:
$myBytes = "414243";
$data = pack('H*', $myBytes);
var_dump($data);
,它将显示string(3) "ABC"
。这是因为0x41 = 65十进制= 'A'(在基本上所有编码中)。class blob
{
function __construct($hexStr = '')
{
$this->appendHex($hexStr);
}
public $value;
public function appendHex($hexStr)
{
$this->value .= pack('H*', $hexStr);
}
public function getByte($index)
{
return unpack('C', $this->value{$index})[1];
}
public function setByte($index, $value)
{
$this->value{$index} = pack('C', $value);
}
public function toArray()
{
return unpack('C*', $this->value);
}
}
// Construct a blob with 3 bytes: 0x41 0x42 0x43.
$b = new blob("414243");
// Append 3 more bytes: 0x44 0x45 0x46.
$b->appendHex("444546");
// Change the second byte to 0x41 (so we now have 0x41 0x41 0x43 0x44 0x45 0x46).
$b->setByte(1, 0x41); // or, equivalently, setByte(1, 65)
// Dump the first byte.
var_dump($b->getByte(0));
// Verify the result. The string "AACDEF", because it's only ASCII characters, will have the same binary representation in basically any encoding.
$ok = $b->value == "AACDEF";
$s = "\x41"
等同于 $s = "A"
(前提是源代码存储在 A 是字节 0x41 的编码中)。 - Dojo很有趣,Stefan Gehrig的答案实际上是正确的。您不需要将字符串转换为“011010101”字符串才能将其存储在数据库的BINARY字段中。无论如何,既然这是谷歌搜索“php convert string to binary string”时出现的第一个答案,那么我对此问题做出了贡献。
Francois Deschenes得到的最高票答案对于长字符串(字节串或位串)是错误的,因为
由于与内部使用的“double”或“float”类型相关的属性,base_convert()可能会在大数字上失去精度。有关更具体的信息和限制,请参见手册中的浮点数部分。
来自:https://secure.php.net/manual/en/function.base-convert.php
为了解决这个限制,您可以将输入字符串切成块。下面的函数实现了这种技术。
<?php
function bytesToBits(string $bytestring) {
if ($bytestring === '') return '';
$bitstring = '';
foreach (str_split($bytestring, 4) as $chunk) {
$bitstring .= str_pad(base_convert(unpack('H*', $chunk)[1], 16, 2), strlen($chunk) * 8, '0', STR_PAD_LEFT);
}
return $bitstring;
}
function bitsToBytes(string $bitstring) {
if ($bitstring === '') return '';
// We want all bits to be right-aligned
$bitstring_len = strlen($bitstring);
if ($bitstring_len % 8 > 0) {
$bitstring = str_pad($bitstring, intdiv($bitstring_len + 8, 8) * 8, '0', STR_PAD_LEFT);
}
$bytestring = '';
foreach (str_split($bitstring, 32) as $chunk) {
$bytestring .= pack('H*', str_pad(base_convert($chunk, 2, 16), strlen($chunk) / 4, '0', STR_PAD_LEFT));
}
return $bytestring;
}
for ($i = 0; $i < 10000; $i++) {
$bytestring_in = substr(hash('sha512', uniqid('', true)), 0, rand(0, 128));
$bits = bytesToBits($bytestring_in);
$bytestring_out = bitsToBytes($bits);
if ($bytestring_in !== $bytestring_out) {
printf("IN : %s\n", $bytestring_in);
printf("BITS: %s\n", $bits);
printf("OUT : %s\n", $bytestring_out);
var_dump($bytestring_in, $bytestring_out); // printf() doesn't show some characters ..
die('Error in functions [1].');
}
}
for ($i = 0; $i < 10000; $i++) {
$len = rand(0, 128);
$bitstring_in = '';
for ($j = 0; $j <= $len; $j++) {
$bitstring_in .= (string) rand(0,1);
}
$bytes = bitsToBytes($bitstring_in);
$bitstring_out = bytesToBits($bytes);
// since converting to byte we always have a multitude of 4, so we need to correct the bitstring_in to compare ..
$bitstring_in_old = $bitstring_in;
$bitstring_in_len = strlen($bitstring_in);
if ($bitstring_in_len % 8 > 0) {
$bitstring_in = str_pad($bitstring_in, intdiv($bitstring_in_len + 8, 8) * 8, '0', STR_PAD_LEFT);
}
if ($bitstring_in !== $bitstring_out) {
printf("IN1 : %s\n", $bitstring_in_old);
printf("IN2 : %s\n", $bitstring_in);
printf("BYTES: %s\n", $bytes);
printf("OUT : %s\n", $bitstring_out);
var_dump($bytes); // printf() doesn't show some characters ..
die('Error in functions [2].');
}
}
echo 'All ok!' . PHP_EOL;
$bits_in = "101";
$bits_in_len = strlen($bits_in); // <-- keep track if input length
$bits_out = bytesToBits(bitsToBytes("101"));
var_dump($bits_in, $bits_out, substr($bits_out, - $bits_in_len)); // recover original length with substr
$string="1001"; //this would be 2^0*1+....0...+2^3*1=1+8=9
$bit4=$string[0];//1
$bit3=$string[1];
$bit2=$string[2];
$bit1=$string[3];//1