在PHP中读取CSV文件,删除空格和特殊字符,并将其存储在db中

在PHP中读取CSV文件,删除空格和特殊字符,并将其存储在db中,php,Php,我用php编写了这段代码。它是从一个简单的csv文件中读取和存储数据库中的数据。 但当我试图读取一个带有特殊字符空格和多个逗号的csv文件时,它并没有读取值 <?php include_once 'connection.php'; if(isset($_POST['submit'])){ if($_FILES['csv_data']['name']){ $arrFileName = explode('.',$_FILES['csv_data']['name']);

我用php编写了这段代码。它是从一个简单的csv文件中读取和存储数据库中的数据。 但当我试图读取一个带有特殊字符空格和多个逗号的csv文件时,它并没有读取值

<?php
include_once 'connection.php';
if(isset($_POST['submit'])){
    if($_FILES['csv_data']['name']){

        $arrFileName = explode('.',$_FILES['csv_data']['name']);
        if($arrFileName[1] == 'csv'){
            $handle = fopen($_FILES['csv_data']['tmp_name'], "r");

            while (($data = fgetcsv($handle, 10000, ",")) !== FALSE) {
                echo $arrFileName;

                 $hr = mysqli_real_escape_string($conn,$data[1]);
                $min = mysqli_real_escape_string($conn,$data[2]);
                $day = mysqli_real_escape_string($conn,$data[3]);
                $month = mysqli_real_escape_string($conn,$data[4]);
                $year = mysqli_real_escape_string($conn,$data[5]);
                $castno = mysqli_real_escape_string($conn,$data[14]);
                $si = mysqli_real_escape_string($conn,$data[27]);
                $su = mysqli_real_escape_string($conn,$data[30]);
                $mng = mysqli_real_escape_string($conn,$data[33]);
                $phos = mysqli_real_escape_string($conn,$data[36]);
                $import="INSERT into hm(hr,min,day,month,year,castno,si,su,mng,phos) values('$hr','$min','$day','$month','$year','$castno','$si','$su','$mng','$phos')";
                mysqli_query($conn,$import);
            }

            fclose($handle);
            print "Import done";
        }
    }
}

我在日常生活中经常这样做,毫无疑问,如果您是在linux机箱上托管,并且能够在机器上访问sed和tr,那么最简单的方法就是:

// clean bad characters that are not detected by the tr below
shell_exec("sed -i '{s/\\x0C/ /g; s/\\x1A/ /g; s/\\xA0/ /g; s/\\x00/ /g;}' $filePath");

// clean the tmp file and place the clean file back in the original file path
shell_exec("tr '\\200-\\377' ' ' < $filePath > $cleanFilePath");

// remove any blank/empty lines in the file
shell_exec("sed -i '/^$/d' $cleanFilePath");
//清除下面的tr未检测到的错误字符
shell_exec(“sed-i'{s/\\x0C//g;s/\\x1A//g;s/\\xA0//g;s/\\x00//g;}'$filePath”);
//清理tmp文件并将清理后的文件放回原始文件路径
shell_exec(“tr'\\200-\\377'<$filePath>$cleanFilePath”);
//删除文件中的所有空行/空行
shell_exec(“sed-i'/^$/d'$cleanFilePath”);
这会查找十六进制字符,如果它们无效(匹配或超出某些范围),则会将其从文件中删除<据我所知,code>tr
没有就地功能(自从我查看以来已经有很长一段时间了),因此您最终将结果输出到
$cleanFilePath
中,它可以是您想要的任何位置。这也比PHP中的实现快得多(这些工具是为大型文本文件(也称为csv文件)构建的),所以为什么不利用它们呢


在我的日常工作中,我们在几秒钟内处理200万行的文件,这是一个巨大的提升。您可以在PHP中实现这一点,但根据我的经验(我最初在PHP中实现这一点的错误),我会避开该解决方案,因为它更复杂,速度也慢得多。

我可能建议您重构上述内容,以使用预先准备好的语句-它将更健壮、更高效,特别是在任何时候,如果一个不受信任的用户能够发布数据

<?php

    if( $_SERVER['REQUEST_METHOD']=='POST' && !empty( $_POST['submit'] ) && !empty( $_FILES['csv_data'] ) ){
        try{

            include_once 'connection.php';

            /* the sql query with placeholders ~ 10 columns, 10 placeholders */
            $sql='insert into `hm` ( `hr`,`min`,`day`,`month`,`year`,`castno`,`si`,`su`,`mng`,`phos` ) values(?,?,?,?,?,?,?,?,?,?);';

            /* Get various properties of the uploaded file */
            $obj=(object)$_FILES['csv_data'];
            $ext=strtolower( pathinfo( $obj->name, PATHINFO_EXTENSION ) );
            $name=$obj->name;
            $tmp=$obj->tmp_name;
            $err=$obj->error;

            /* If there are no errors and the file is a .csv proceed */
            if( $err== 0 && $ext=='csv' ){

                printf('Begin importing %s',$name);

                /* create the prepared statement object - exit if it fails */
                $stmt=$conn->prepare( $sql );
                if( !$stmt )throw new Exception('Failed to prepare query');

                /* Not know if these should be integers or strings... */
                $stmt->bind_param( 'ssssssssss', $hr,$min,$day,$month,$year,$castno,$si,$su,$mng,$phos );

                /* read the csv file */
                $data = new SplFileObject( $tmp );
                $data->setFlags( SplFileObject::READ_CSV );

                /* process each line - create variables */
                foreach( $data as $i => $line ) {
                    list( $hr,$min,$day,$month,$year,$castno,$si,$su,$mng,$phos )=$line;

                    /* insert the record */
                    $stmt->execute();
                }

                $stmt->close();

                printf( '<br />Importing %d lines from %s complete', $i, $name );
            }
        }catch( Exception $e ){
            exit( $e->getMessage() );
        }
    }
?>


你能举一个CSV文件不起作用的例子吗(最好是几行,而不是一个完整的文件)。NA,16,53,04,08,18,HMSMS_CM,ARL,,,,,,,,,,,,,,,,4,Si,,,1.23,S,,,0.046,Mn,(,0.139,P,,,0.122,我试过读取这些数据,它看起来读起来不错,当你说不读取时,你是说没有创建记录还是字段位于错误的位置?如果你尝试打印($data)在循环中,是否显示此记录?请尝试使用仅包含这一行的文件。但它没有读取格式中所需的值。因为CSV文件数据类似于.NA、16、53、04、08、18、HMSMS_CM、ARL、1、1、0、09532/3 T5 S1、、、、、、、、、、4、Si、、1.23、S、、0.046、Mn、,(,0.139,P,,,0.122,你能创建一个数据的pastebin粘贴吗?从这里给出的例子很难理解格式