【问题标题】:PHP pdftk ASCII encoding issuePHP pdftk ASCII 编码问题
【发布时间】:2015-08-10 02:06:29
【问题描述】:

我编写了一个函数,它将包含 PDF 字段数据的字符串作为主题传递给 preg_match_all()。但是,无论我做什么,我都无法获得预期的输出,因为我来到这里 http://www.phpliveregex.com/p/bjN。在我的开发环境中,我得到了这个:

数组(1) { [0]=> 数组(0) { } }

我能够让它工作的唯一方法是在我的字符串输入上调用 var_dump(),将它分配给我的函数中的一个变量,并用反斜杠转义双引号。但是,此解决方案不起作用,因为我想动态传递不同的字符串。

我已经尝试过的函数包括 preg_replace()、preg_quote()、addslashes()、addcslashes() 和 htmlentities() 来转义或编码任何可能导致问题的字符。到目前为止没有任何效果。

下面引用的是我在输入上调用 var_dump() 时得到的输出。正如我上面所说,将它分配给一个变量并将其传递给 preg_match_all() 对我有用。所以这个问题似乎归结为:什么可能阻止我的输入字符串与 preg_match_all() 一起正常工作,这对于我调用 var_dump() 时得到的字符串也不是问题?

string(3277) "--- 字段类型:文本字段名称: fc-int01-generateAppearances FieldFlags:5 FieldJustification:左 --- FieldType: Text FieldName: Cake Size, Shape, and Pricing_edit;_aKGrUPU76IVzjjqnxACWRA FieldNameAlt: 请描述 定制蛋糕尺寸和特殊要求。字段标志:0 FieldJustification: Left --- FieldType: Text FieldName: Todays Date FieldNameAlt: 今天的日期 FieldFlags: 0 FieldJustification: Left --- 字段类型:按钮字段名称:类型字段标志:49152 FieldJustification:左 FieldStateOption:交货 FieldStateOption: 取货用 FieldStateOption: Off --- FieldType: 文本 FieldName:名称 FieldNameAlt:名称 FieldFlags:0 FieldJustification: Left --- FieldType: Text FieldName: Date of Event FieldNameAlt: 事件日期 FieldFlags: 0 FieldJustification: Left --- FieldType:文本 FieldName:事件时间 FieldNameAlt:时间 事件 FieldFlags: 0 FieldJustification: Left --- FieldType: Text FieldName:事件类型 FieldNameAlt:事件类型 FieldFlags:0 FieldJustification:左 --- FieldType:文本 FieldName:事件位置 (如果请求交付) FieldNameAlt:事件位置(如果交付 被请求)FieldFlags:0 FieldJustification:Left --- FieldType: 文本 FieldName:取件时间 FieldNameAlt:取件时间 FieldFlags:0 FieldJustification: Left --- FieldType: Text FieldName: Number of 客人 FieldNameAlt:客人数量 FieldFlags:0 FieldJustification:左 --- FieldType:文本 FieldName:电话号码 FieldNameAlt: 电话号码 FieldFlags: 0 FieldJustification: Left --- FieldType:按钮 FieldName:蛋糕大小、形状和定价 FieldFlags: 49152 FieldJustification:左 FieldStateOption:自定义 FieldStateOption:关闭 FieldStateOption:矩形 1/2 表 ($60.00) 最多可提供 12 个 FieldStateOption:矩形 1/3 表 ($40.00) 服务 最多 8 个 FieldStateOption:矩形 1/4 表 ($30.00) 最多可提供 6 个 FieldStateOption:矩形整张表(100.00 美元)最多可提供 24 个 FieldStateOption:第 6 轮“(40.00 美元)最多可服务 8 个 FieldStateOption:第 9 轮“(50.00 美元)最多可容纳 16 人 FieldStateOption:方形 1/6 表(20.00 美元)最多可提供 4 个 FieldStateOption: Square 2/3 Sheet ($50.00) 最多可容纳 16 人 --- 字段类型:按钮字段名称:蛋糕口味字段标志:49152 FieldJustification:左 FieldStateOption:胡萝卜 FieldStateOption: 巧克力 FieldStateOption:柠檬 FieldStateOption:关闭 FieldStateOption:红色天鹅绒 FieldStateOption:香草 --- FieldType: 按钮 FieldName:Cake Fillings FieldFlags:49152 FieldJustification: 左侧 FieldStateOption:Buttercream FieldStateOption:奶油奶酪 FieldStateOption:黑巧克力 FieldStateOption:柠檬凝乳 FieldStateOption:关闭 FieldStateOption:草莓慕斯 --- 字段类型:按钮字段名称:蛋糕糖霜字段标志:49152 FieldJustification:左 FieldStateOption:巧克力奶油 FieldStateOption:奶油奶酪 FieldStateOption:关闭 FieldStateOption: 草莓奶油 FieldStateOption:香草奶油 FieldStateOption: Whipped cream --- FieldType: Text FieldName: Cake 文字的铭文和颜色 FieldNameAlt:蛋糕铭文和 书写 FieldFlags 的颜色:4096 FieldJustification:左 --- 字段类型:文本字段名称:浇头和特殊装饰 FieldNameAlt:浇头和特殊装饰 FieldFlags:4096 字段对齐:左“

如果我将此字符串分配给一个临时变量并转义引号,那么 preg_match_all() 将按预期工作。当我使用分配的字符串对该变量调用 var_dump() 时,长度为 3268 个字符,而我的直接输入为 3277 个字符(上图)。因此,输入字符串可能发生了一些奇怪的事情。

对此的任何帮助将不胜感激!

这是我为提高可读性而修改的类文件:

class Pdf_form {

    public function get_pdf_fields($pdf) {
        $cmd = "pdftk $pdf dump_data_fields output -";

        $descriptorspec = array(
           1 => array("pipe", "w")
        );

        $process = proc_open($cmd, $descriptorspec, $pipes);

        if(!is_resource($process)) {
            return FALSE;
        }

        $dump_data = stream_get_contents($pipes[1]);
        fclose($pipes[1]);

        $status = proc_close($process);

        return $this->parse_fields($dump_data);
    }

    private function parse_fields($dump_data) {
        preg_match_all('/FieldType: .+?(?= ---|$)/', $dump_data, $field_data);

        return $field_data;
    }
}

【问题讨论】:

  • “由于 $ 和“(双引号)字符的存在,它不能作为输入传递给 preg_match_all” 你为什么会这样认为?这显然是主题和不是模式,这些字符不会出现问题。
  • 你是对的,我引用的字符串是主题。在 preg_match_all() 返回这个“array(1) { [0]=> array(0) { } }”之前,我认为自己不会有任何问题。只有在我用反斜杠转义 $ 和 " 之后, preg_match_all() 才返回我的预期。 - 编辑:你对不需要转义的美元符号是正确的,因为我刚刚测试过,但双引号仍在证明在他们逃脱之前有问题。
  • 您能在preg_match_allpreg_replace 中发布您是如何运行此字符串的吗?
  • " html实体替换"
  • chris85:当然 - 我已将其添加到我的原始帖子中

标签: php regex string character-encoding preg-match-all


【解决方案1】:

我认为你可以使用 Newdoc 语法。

文档中的示例。

echo <<<'EOT'
My name is "$name". I am printing some $foo->foo.
Now, I am printing some {$foo->bar[1]}.
This should not print a capital 'A': \x41
EOT;

https://php.net/language.types.string#language.types.string.syntax.nowdoc11

编辑 如果你只想替换所有双引号,你可以使用 str_replace。

$a = str_replace('"', '\"', $a);

【讨论】:

  • 除非有办法将我的动态输入字符串转换为 nowdoc 格式,否则我不知道这将如何工作。
  • 我误解了这个问题。但这应该可以用 \" $string = str_replace('"', '\"', $string); 替换所有双引号
  • 在“修复”之前应该首先确定问题。没有理由需要在这里转义双引号。
  • Karl:我使用 str_replace() 做了同样的事情,就像你在这里建议的那样,但它没有成功转义双引号。除了我在原帖中提到的怀疑之外,我不知道为什么会发生这种情况。
【解决方案2】:

事实证明,在我的输入中似乎是空格的一些字符,甚至可能是全部字符实际上被编码为 ASCII 换行符(ASCII 十进制代码 10)。因此,在调用 pdftk 的 dump_data_fields 操作和通过 stream_get_contents() 将数据传输到我的 php 脚本之间,数据以这种方式编码。

我的解决方案是在我的输入上调用 preg_replace() 以用空格替换所有换行符。这是它的样子:

$dump_data = preg_replace('/\n/', ' ', $dump_data);

preg_match_all('/FieldType:.+?(?=.---|$)/', $dump_data, $field_data);

希望这对其他人有帮助!

【讨论】:

    【解决方案3】:

    在php函数中传递字符串

    mysqli_real_escape_string();
    

    如果你使用 mysqli 连接 如果使用 mysql 则使用

    mysql_real_escape_string();
    

    【讨论】:

    • 什么?这里没有 DB 谈话。
    • 即使您不想将记录保存在数据库中,也可以使用此功能。我的意思是无论您是要插入数据库还是存储在变量中,它都会返回相同的内容。
    • 不首先它会抛出警告。 Warning: mysql_real_escape_string(): [2002] No such file or directory (trying to connect via unix:///var/mysql/mysql.sock)Warning: mysql_real_escape_string(): A link to the server could not be established in 等。如果目标只是转义引号,为什么不 php.net/addslashes?但即便如此,这也不是问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-26
    • 2017-11-05
    • 2016-07-09
    • 2011-10-14
    • 2021-06-13
    相关资源
    最近更新 更多