【问题标题】:Convert php array to csv string将php数组转换为csv字符串
【发布时间】:2013-04-27 11:37:02
【问题描述】:

我有几种方法可以将 php 数组从 stackoverflow 和 google 转换为 csv 字符串。但是我很麻烦,如果我想存储诸如 01727499452 之类的手机号码,它会保存为没有第一个 0 值。 我目前正在使用这段代码: Convert array into csv

谁能帮帮我。

Array   

[1] => Array
    (
        [0] => Lalu ' " ; \\ Kumar
        [1] => Mondal
        [2] => 01934298345
        [3] => 
    )

[2] => Array
    (
        [0] => Pritom
        [1] => Kumar Mondal
        [2] => 01727499452
        [3] => Bit Mascot
    )

[3] => Array
    (
        [0] => Pritom
        [1] => Kumar Mondal
        [2] => 01711511149
        [3] => 
    )

[4] => Array
    (
        [0] => Raaz
        [1] => Mukherzee
        [2] => 01911224589
        [3] => Khulna University 06
    )

)

我的代码块:

function arrayToCsv( array $fields, $delimiter = ';', $enclosure = '"', $encloseAll = false, $nullToMysqlNull = false ) {
$delimiter_esc = preg_quote($delimiter, '/');
$enclosure_esc = preg_quote($enclosure, '/');

$outputString = "";
foreach($fields as $tempFields) {
    $output = array();
    foreach ( $tempFields as $field ) {
        if ($field === null && $nullToMysqlNull) {
            $output[] = 'NULL';
            continue;
        }

        // Enclose fields containing $delimiter, $enclosure or whitespace
        if ( $encloseAll || preg_match( "/(?:${delimiter_esc}|${enclosure_esc}|\s)/", $field ) ) {
            $field = $enclosure . str_replace($enclosure, $enclosure . $enclosure, $field) . $enclosure;
        }
        $output[] = $field." ";
    }
    $outputString .= implode( $delimiter, $output )."\r\n";
}
return $outputString; }

谢谢,

Pritom。

【问题讨论】:

  • 这就是用别人轮子的问题。
  • 将其保存为字符串。无论如何,我建议将其用于电话号码,因为您也只想保存该 + ;)
  • 您应该使用 PHP 的内置 CSV 函数,例如 php.net/manual/en/function.fputcsv.php
  • 一些二手建议:如果您不打算对其进行算术运算,请将其存储为字符串。 The Daily WTF 包含许多以科学记数法打印的电话号码的示例,这些电话号码最终源于有人将其存储为整数。
  • 数字将正确存储在 CSV 中,前导零;但是当在 MS Excel 中打开时,Excel 将重新格式化它 - 要么使用已经支持格式信息的文件格式(不是 CSV),以便 Excel 不应用其标准行为,要么在保存 @987654326 时将其强制为公式字符串@

标签: php csv multidimensional-array phone-number


【解决方案1】:

此实现不使用文件指针,不应无意中修改传递给它的任何数据,并且仅根据需要转义,类似于fputcsv()(但没有$escape_char 废话):

function str_putcsv(array $fields, string $delimiter = ',', string $enclosure = '"') {
    $escs = [];
    foreach ($fields as $field) {
        $esc = (string) $field;
        if (
            false !== strpos($esc, $delimiter)
            || false !== strpos($esc, $enclosure)
        ) {
            $esc = $enclosure . strtr($esc, ["$enclosure" => "$enclosure$enclosure"]) . $enclosure;
        }
        $escs[] = $esc;
    }
    return implode($delimiter, $escs) . PHP_EOL;
}

如果您的 PHP 版本不支持 string 类型声明,请删除它们。

【讨论】:

    【解决方案2】:

    受@alexcristea 回答的启发:

    function array2csv($data, $delimiter = ',', $enclosure = '"', $escape_char = "\\")
    {
        $f = fopen('php://memory', 'r+');
        foreach ($data as $item) {
            fputcsv($f, $item, $delimiter, $enclosure, $escape_char);
        }
        rewind($f);
        return stream_get_contents($f);
    }
    
    $list = array (
        array('aaa', 'bbb', 'ccc', 'dddd'),
        array('123', '456', '789'),
        array('"aaa"', '"bbb"')
    );
    var_dump(array2csv($list));
    

    【讨论】:

      【解决方案3】:

      这就是你需要的

      $out = "";
      foreach($array as $arr) {
          $out .= implode(",", $arr) . PHP_EOL;
      
      }
      

      它遍历您的数组,在每个循环上创建一个新行,用“,”分隔数组值。

      【讨论】:

      • 这是我想要的吗?请阅读我的问题,如果您不清楚,请问我。
      • 应该是,我不明白你为什么不这样做:) 试一试,看看它是否符合你的期望。
      • 我在很多情况下都使用过类似的东西,它在警告(或两个)的情况下效果很好。如果 $arr 中的某些值包含“,”字符,则会中断。 csv 格式有处理它的方法,但该解决方案没有解决这些问题。此外,您正在使用 "\r\n" 编写 Windows 特定的换行符,这在某些情况下可能会导致问题。使用常量PHP_EOL 将产生更多可移植的代码。
      • OP 应该尝试检查 $out 的内容
      【解决方案4】:

      你可以使用str_putcsv函数:

      if(!function_exists('str_putcsv'))
      {
          function str_putcsv($input, $delimiter = ',', $enclosure = '"')
          {
              // Open a memory "file" for read/write...
              $fp = fopen('php://temp', 'r+');
              // ... write the $input array to the "file" using fputcsv()...
              fputcsv($fp, $input, $delimiter, $enclosure);
              // ... rewind the "file" so we can read what we just wrote...
              rewind($fp);
              // ... read the entire line into a variable...
              $data = fread($fp, 1048576);
              // ... close the "file"...
              fclose($fp);
              // ... and return the $data to the caller, with the trailing newline from fgets() removed.
              return rtrim($data, "\n");
          }
       }
      
       $csvString = '';
       foreach ($list as $fields) {
           $csvString .= str_putcsv($fields);
       }
      

      在@johanmeiring 创建的函数GitHub 上了解更多信息。

      【讨论】:

      • 这是一件小事,但我认为你的意思是 $csvString .= str_putcsv($fp, $fields);。缺少 $ ;)
      • 不应该是str_putcsv($fields);而不是str_putcsv($fp, $fields);
      • 我喜欢这个解决方案。当我“借用”它时,我做了一个小修改:... $len = ftell($fp)+1; rewind($fp); $data = fread($fp,$len); ...,它似乎有效。不知道1048576代表什么,所以不想直接用。
      【解决方案5】:

      这是一个更通用的解决方案。我实际上是在寻找一种为 SQL 批量插入制作字符串列表的方法。代码如下所示:

      foreach ($rows as $row) {
          $string = toDelimitedString($row);
          // Now append it to a file, add line break, whatever the need may be
      }
      

      这是我最终添加到我的 takeit 中的有用功能:

      /**
       * Convert an array of strings to a delimited string. This function supports CSV as well as SQL output since
       * the quote character is customisable and the escaping behaviour is the same for CSV and SQL.
       *
       * Tests:
       *  echo toDelimitedString([], ',', '\'', true) . "\n";
       *  echo toDelimitedString(['A'], ',', '\'', true) . "\n";
       *  echo toDelimitedString(['A', 'B'], ',', '\'', true) . "\n";
       *  echo toDelimitedString(['A', 'B\'C'], ',', '\'', true) . "\n";
       *  echo toDelimitedString([], ',', '\'', true) . "\n";
       *  echo toDelimitedString(['A'], ',', '"', true) . "\n";
       *  echo toDelimitedString(['A', 'B'], ',', '"', true) . "\n";
       *  echo toDelimitedString(['A', 'B"C'], ',', '"', true) . "\n";
       *
       * Outputs:
       *  <Empty String>
       *  'A'
       *  'A','B'
       *  'A','B''C'
       *  <Empty String>
       *  "A"
       *  "A","B"
       *  "A","B""C"
       *
       * @param array $array A one-dimensional array of string literals
       * @param string $delimiter The character to separate string parts
       * @param string $quoteChar The optional quote character to surround strings with
       * @param bool $escape Flag to indicate whether instances of the quote character should be escaped
       * @return string
       */
      function toDelimitedString(array $array, string $delimiter = ',', string $quoteChar = '"', bool $escape = true)
      {
          // Escape the quote character, since it is somewhat expensive it can be suppressed
          if ($escape && !empty($quoteChar)) {
              $array = str_replace($quoteChar, $quoteChar . $quoteChar, $array);
          }
      
          // Put quotes and commas between all the values
          $values = implode($array, $quoteChar . $delimiter . $quoteChar);
      
          // Put first and last quote around the list, but only if it is not empty
          if (strlen($values) > 0) {
              $values = $quoteChar . $values . $quoteChar;
          }
      
          return $values;
      }
      

      【讨论】:

        【解决方案6】:

        上面的函数并不完全正确,因为它把\n看作一个元素,这不是我们想要的,因为每一行必须只用\n分隔。所以更高效的代码是:

        function array2csv($array, $delimiter = "\n") {
            $csv = array();
            foreach ($array as $item=>$val) 
            {
                if (is_array($val)) 
                { 
                    $csv[] = $this->array2csv($val, ";");
                } 
                else 
                {
                    $csv[] = $val;
                }
            }
            return implode($delimiter, $csv);
        }
        

        【讨论】:

          【解决方案7】:

          我正在使用此函数将 php 数组转换为 csv。它也适用于多维数组。

          public function array_2_csv($array) {
          $csv = array();
          foreach ($array as $item=>$val) {
          if (is_array($val)) { 
              $csv[] = $this->array_2_csv($val);
              $csv[] = "\n";
          } else {
              $csv[] = $val;
            }
           }
          return implode(';', $csv);
          }
          

          【讨论】:

            【解决方案8】:

            由于它是 CSV 而不是 JSON 之类的东西,所以无论如何都会将所有内容作为字符串读取,因此只需将您的数字转换为字符串:

            • (string)$variable
            • strval($variable)(我更喜欢这里)
            • 与空字符串连接,例如$variable . ''

            PHP 的gettype() 也是一种选择。您可以使用我描述的一种方法将每个字段类型转换为一个字符串(即使它已经是一个),或者您可以通过这样做来调用您所追求的数字字段:

            if (gettype($field) == 'integer' || gettype($field) == 'double') {
                $field = strval($field); // Change $field to string if it's a numeric type
            }
            

            这是添加的完整代码

            function arrayToCsv( array $fields, $delimiter = ';', $enclosure = '"', $encloseAll = false, $nullToMysqlNull = false ) {
                $delimiter_esc = preg_quote($delimiter, '/');
                $enclosure_esc = preg_quote($enclosure, '/');
            
                $outputString = "";
                foreach($fields as $tempFields) {
                    $output = array();
                    foreach ( $tempFields as $field ) {
                        // ADDITIONS BEGIN HERE
                        if (gettype($field) == 'integer' || gettype($field) == 'double') {
                            $field = strval($field); // Change $field to string if it's a numeric type
                        }
                        // ADDITIONS END HERE
                        if ($field === null && $nullToMysqlNull) {
                            $output[] = 'NULL';
                            continue;
                        }
            
                        // Enclose fields containing $delimiter, $enclosure or whitespace
                        if ( $encloseAll || preg_match( "/(?:${delimiter_esc}|${enclosure_esc}|\s)/", $field ) ) {
                            $field = $enclosure . str_replace($enclosure, $enclosure . $enclosure, $field) . $enclosure;
                        }
                        $output[] = $field." ";
                    }
                    $outputString .= implode( $delimiter, $output )."\r\n";
                }
                return $outputString; 
            }
            

            【讨论】:

              【解决方案9】:

              您确定这些数字实际上是在没有前导零的情况下保存的吗?您是否在文本编辑器中查看过实际的 CSV 输出?

              如果您刚刚在电子表格应用程序中打开了 CSV 文件,则很可能是电子表格将您的电话号码解释为数值并在显示它们时去掉了零。您通常可以通过更改该特定列的格式选项在电子表格中解决此问题。

              【讨论】:

                猜你喜欢
                • 2013-05-05
                • 1970-01-01
                • 2023-03-18
                • 2018-01-29
                • 2013-08-12
                • 2021-12-27
                • 1970-01-01
                • 2010-10-15
                相关资源
                最近更新 更多