如何在PHP中检查字符串是普通字符串还是二进制字符串?

12

可能重复:
如何在PHP中检查文件是ASCII还是二进制文件

我有一个函数可以接受一个图片文件的名称(普通字符串),或者直接接受作为二进制字符串的图像字节。就像使用file_get_contents函数返回的那样。

如何区分这两种情况?


我认为这是同一个问题:https://dev59.com/THRB5IYBdhLWcg3wZmlz - Rijk
这个问题在这里得到了回答:https://dev59.com/THRB5IYBdhLWcg3wZmlz - Matthew
1
这怎么是“完全重复”的?那里打开文件并检查MIME。而我这里有二进制数据作为字符串。我该如何检查它的MIME? - AppleGrew
2个回答

14

如果您只使用 ASCII 字符的 32 到 126,并且没有任何对 Unicode 字符的期望,您可以检查输入是否仅由可打印字符组成。您可以使用 ctype_print() 来实现这一点。

if (ctype_print($filename)) { // this is most probably not an image

你也可以检查参数是否是有效的图像,或者是否存在一个以该名称命名的文件。

但创建两个不同的函数会更好、更可靠:

  • 一个名为load_image_from_string()的函数,它始终将图像作为参数。
  • 另一个名为load_image_from_file()的函数,它将读取该文件并调用load_image_from_string()函数。

2
此外,您可以尝试有根据的猜测 - 如果字符串的长度超过1k字节,则很可能是图像。 - Maxim Krizhanovsky
2
@AppleGrew:构造函数要尽量简单,不要在其中添加太多代码。相反,创建两个可以具有相同父类的对象。一个需要文件名字符串,另一个需要二进制数据字符串或类似内容。或者创建一个工厂方法来处理。 - hakre
制表符和回车符会导致ctype_print()返回FALSE,这是不幸的。 - dotancohen
大多数文件名不包含制表符和回车符,幸运的是 :) - Arnaud Le Blanc
整数有时也不符合ctype_print()的可打印条件。 - CMCDragonkai
显示剩余7条评论

2

在PHP中,所有的字符串都是二进制的(截至当前PHP 5.3版本),所以没有办法区分。因此,从技术上讲,你无法区分参数是二进制数据还是文件名(都是字符串)。

但你可以创建第二个函数来处理文件,并重复使用处理图像数据的函数。因此,函数名称清楚地表明了它所期望的参数。


如果你需要根据传递给函数的类型做出决定,那么必须为数据添加上下文信息。一种方法是将特定类型的参数作为函数的参数:

abstract class TypedString
{
    private $string;
    public final function __construct($string)
    {
        $this->string = (string) $string;
    }
    public final function __toString()
    {
        return $this->string;
    }
}

class FilenameString extends TypedString {}

class ImageDataString extends TypedString {}


function my_image_load(TypedString $string)
{
    if ($string instanceof FilenameString)
    {
        $image = my_image_load_file($string);
    }
    elseif ($string instanceof ImageDataString)
    {
        $image = my_image_load_data($string);
    }
    else
    {
         throw new Exception('Invalid Input');
    }
    # continue loading the image if needed
}
function my_image_load_file($filename)
{
    # load the image from file and return it
}
function my_image_load_data($data)
{
    # load the image from data and return it
}

然而,我认为使用适当命名的函数更容易处理,否则,如果您仅使用类进行类型区分,则会使事情变得不必要地复杂。


1
hakre,你的回答听起来像是“无法确定一个数字是10还是1000,因为它们都是数字”。尽管我同意“字符串就是字符串”,但在这种情况下,两个字符串的性质不同 - 一个类型的字符串可能只包含文件名中有效的字符,而另一个字符串可能有其他字符,并且看起来并不像文件名。 - binaryLV
从本质上讲,字符串在类型上并没有区别。但是不管怎样,你想通过评论实现什么目的呢?告诉我字符串的内容可能不同吗?这对我来说并不新鲜。这就是为什么我们使用字符串变量来存储不同值的原因。但通常我们会在数据旁边使用上下文。而且上下文应该是清晰的,否则你最终会遇到复杂性问题,说:“糟糕的事情将停止工作。” - hakre
1
这是语言规范的问题,任何问题都会被定义为hacky,除非你重新实现字符串或字节数组。 - Andrew Koster

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接