在GAE上使用PHP解析远程CSV文件

7

我在使用Quercus开发PHP小应用时遇到了一个棘手的问题:

  1. 我有一个远程csv文件,可以下载并存储在字符串中
  2. 为了解析该字符串,我最好使用str_getcsv函数,但是Quercus还没有这个函数
  3. Quercus似乎知道fgetcsv函数,但是该函数需要一个文件句柄,而我没有(由于GAE不允许创建文件)也无法创建一个新的文件句柄

有没有人有什么办法可以解决这个问题,而不必放弃内置的PHP csv-parser函数并编写自己的解析器呢?


6
作为一个正在阅读《第22条军规》的人,我可以说这不是那本书。;) - Nick Johnson
1
不是一个坏主意,但是不行;“SplTempFileObject是一个未知的类名”。我还尝试了fopen("php://memory", "rw"),但也不起作用(“java.lang.IllegalStateException: Cannot marsahl false to BinaryOutput”)。 - futtta
也许您可以在Quercus中使用data-uris:http://php.net/manual/en/wrappers.data.php - hakre
等一下,我不明白为什么你不能只是使用''fopen()''打开远程流,然后使用''fgetscsv()''读取它 - 能否澄清一下? - Jonathan Chan
1
使用正则表达式解析CSV文件并不难,我认为在你的情况下这不是一个坏主意。 - nobody
显示剩余13条评论
5个回答

1

我认为最简单的解决方案是编写自己的解析器。这很容易,而且可以让你学习更多的正则表达式。在PHP中没有将CSV字符串转换为数组的解析器是没有意义的,因此编写自己的解析器是完全合理的。只要确保它不会太慢就可以了 ;)


0

这是我写的一个简单手动解析器,带有合格、非合格和转义功能的示例输入。它可以用于标题和数据行,并包含一个关联数组函数,将您的数据转换为kvp样式的数组。

//example data
$fields = strparser('"first","second","third","fourth","fifth","sixth","seventh"');
print_r(makeAssocArray($fields, strparser('"asdf","bla\"1","bl,ah2","bl,ah\"3",123,34.234,"k;jsdfj ;alsjf;"')));


//do something like this
$fields = strparser(<csvfirstline>);
foreach ($lines as $line)
    $data = makeAssocArray($fields, strparser($line));


function strparser($string, $div = ",", $qual = "\"", $esc = "\\") {
    $buff = "";
    $data = array();
    $isQual = false; //the result will be a qualifier
    $inQual = false; //currently parseing inside qualifier

    //itereate through string each byte
    for ($i = 0; $i < strlen($string); $i++) {
        switch ($string[$i]) {
            case $esc:
                //add next byte to buffer and skip it
                $buff .= $string[$i+1];
                $i++;
                break;
            case $qual:
                //see if this is escaped qualifier
                if (!$inQual) {
                    $isQual = true;
                    $inQual = true;
                    break;
                } else {
                    $inQual = false; //done parseing qualifier
                    break;
                }
            case $div:
                if (!$inQual) {
                    $data[] = $buff;    //add value to data
                    $buff = "";         //reset buffer
                    break;
                }
            default:
                $buff .= $string[$i];
        }
    }
    //get last item as it doesnt have a divider
    $data[] = $buff;
    return $data;
}

function makeAssocArray($fields, $data) {
    foreach ($fields as $key => $field)
        $array[$field] = $data[$key];
    return $array;
}

我已经尝试过那个duante了,但在GAE上不起作用(参见http://stackoverflow.com/questions/6979114/parse-remote-csv-file-with-php-on-gae#comment-8447584)。 - futtta

0

好主意,但是行不通;我复制粘贴了php.net上的示例代码,但在尝试stream_wrapper_register时代码崩溃了。太糟糕了,看起来没有解决办法(除了手动解析csv字符串)。 - futtta

0

你可以尝试使用fopenphp://tempphp://memoryphp.net)来使其工作。你需要打开php://tempphp://memory,写入内容,然后倒回去(php.net),最后将其传递给fgetcsv函数。我没有测试过,但这可能有效。


在这种情况下,编写一个解析程序可能是最好的选择。对行进行切割,并使用正则表达式来正确处理带有引号内逗号的内容。 - Jason

0

如果可以粗暴并快速地处理,我会只使用http://php.net/manual/en/function.exec.php来传递并使用sed和awk(http://shop.oreilly.com/product/9781565922259.do)进行解析。我知道您想使用PHP解析器。我以前尝试过但失败了,因为它对错误不够明确。希望这可以帮到您。祝您好运。


这在Google App Engine上的Quercus上行不通;没有exec,也没有sed和awk。 - futtta

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