如何解析包含数据中的换行符的Excel数据?

omg*_*tch 6 php csv excel parsing line-breaks

我正在尝试使用PHP解析一组CSV数据,但存在一个主要问题.其中一个字段是长描述字段,其本身包含机箱内的换行符.

我的主要问题是编写一段可以逐行拆分数据的代码,但也可以识别不应该使用数据中的换行符.此字段中的换行符未正确转义,因此很难与合法的换行符区分开来.

我试图想出一个能够正确处理它的正则表达式,但到目前为止还没有运气.有任何想法吗?

CSV格式:

"####","text data here", "text data \n with linebreaks \n here"\n
"####","more text data", "more data \n with \n linebreaks \n here"\n
Run Code Online (Sandbox Code Playgroud)

Ste*_*hen 10

根据aleske,PHP的fgetcsv函数文档中的一位评论者:

PHP的CSV处理是非标准的,与RFC4180相矛盾,因此fgetcsv()无法正确处理[包含换行符]的文件......

他提供了以下功能来解决这个限制:

function csvstring_to_array(&$string, $CSV_SEPARATOR = ';', $CSV_ENCLOSURE = '"', $CSV_LINEBREAK = "\n") { 
  $o = array(); 

  $cnt = strlen($string); 
  $esc = false; 
  $escesc = false; 
  $num = 0; 
  $i = 0; 
  while ($i < $cnt) { 
$s = $string[$i]; 

if ($s == $CSV_LINEBREAK) { 
  if ($esc) { 
    $o[$num] .= $s; 
  } else { 
    $i++; 
    break; 
  } 
} elseif ($s == $CSV_SEPARATOR) { 
  if ($esc) { 
    $o[$num] .= $s; 
  } else { 
    $num++; 
    $esc = false; 
    $escesc = false; 
  } 
} elseif ($s == $CSV_ENCLOSURE) { 
  if ($escesc) { 
    $o[$num] .= $CSV_ENCLOSURE; 
    $escesc = false; 
  } 

  if ($esc) { 
    $esc = false; 
    $escesc = true; 
  } else { 
    $esc = true; 
    $escesc = false; 
  } 
} else { 
  if ($escesc) { 
    $o[$num] .= $CSV_ENCLOSURE; 
    $escesc = false; 
  } 

  $o[$num] .= $s; 
} 

$i++; 
  } 

//  $string = substr($string, $i); 

  return $o; 
} 
Run Code Online (Sandbox Code Playgroud)

看起来它会成功.

  • 这个优秀的图书馆也有效:http://code.google.com/p/parsecsv-for-php/ (4认同)
  • `fgetcsv($file)`。在 2019 年 php 7 中工作正常 (2认同)

Ada*_*m F 5

我发现在将 CSV 转换为 unix 格式后,您可以使用普通的 CSV 解析器。

这是一个对我有用的函数。

function dos2unix($s) {
    $s = str_replace("\r\n", "\n", $s);
    $s = str_replace("\r", "\n", $s);
    $s = preg_replace("/\n{2,}/", "\n\n", $s);
    return $s;
}
Run Code Online (Sandbox Code Playgroud)

和一个解析函数

function csvstring_to_array($string, $separatorChar = ',', $enclosureChar = '"', $newlineChar = PHP_EOL) {
    // @author: Klemen Nagode
    $string = dos2unix($string);
    $array = array();
    $size = strlen($string);
    $columnIndex = 0;
    $rowIndex = 0;
    $fieldValue="";
    $isEnclosured = false;
    for($i=0; $i<$size;$i++) {

        $char = $string{$i};
        $addChar = "";

        if($isEnclosured) {
            if($char==$enclosureChar) {

                if($i+1<$size && $string{$i+1}==$enclosureChar){
                    // escaped char
                    $addChar=$char;
                    $i++; // dont check next char
                }else{
                    $isEnclosured = false;
                }
            }else {
                $addChar=$char;
            }
        }else {
            if($char==$enclosureChar) {
                $isEnclosured = true;
            }else {

                if($char==$separatorChar) {

                    $array[$rowIndex][$columnIndex] = $fieldValue;
                    $fieldValue="";

                    $columnIndex++;
                }elseif($char==$newlineChar) {
                    echo $char;
                    $array[$rowIndex][$columnIndex] = $fieldValue;
                    $fieldValue="";
                    $columnIndex=0;
                    $rowIndex++;
                }else {
                    $addChar=$char;
                }
            }
        }
        if($addChar!=""){
            $fieldValue.=$addChar;

        }
    }

    if($fieldValue) { // save last field
        $array[$rowIndex][$columnIndex] = $fieldValue;
    }
    return $array;
}
Run Code Online (Sandbox Code Playgroud)