PHP解析一个.txt文件

3
我正在开发一个网站,希望管理员能够上传包含员工ID和姓名的.txt文件。我需要解析.txt文件并将信息插入数据库,但是在解析时一直出现错误。
我尝试按照PHP-解析txt文件的格式进行操作,但在我的第一个$行explode()之后,出现了多个非法或未定义偏移量的错误。
.txt文件内容:
186298  "Cushing,Kathy N"
167876  "Roberts,Joseph Allen"
109876  "Smith,Sarah Quinn"
118679  "Hernandez,Juan"
187568  "Freeman,Colby Matthew"

.php 函数:

function updateMemberList()
{
        global $db_handle;
        $tmpName = $_SESSION['filename'];
        //$include_once ($_SERVER['DOCUMENT_ROOT'] . "../../uploads/updates/'$tmpName'");
        $txt_file = file_get_contents("../../uploads/updates/$tmpName");
        $rows = explode("\n", $txt_file);

        foreach($rows as $row => $data)
        {
            //Splits data into employee ID and full name
            $row_data = explode(' ', $data);

            $info[$row]['empid'] = $row_data[0];
            $info[$row]['name'] = $row_data[1];     //AFTER this line is where I start having errors

            //Splits name into last name and first name
            $row_name = explode(',', $info[$row]['name']);
            $info[$row_name]['lname'] = $row_name[0];
            $info[$row_name]['fname'] = $row_name[1];

            //Cleans " off last name
            $row_lname = explode('"', $info[$row_name]['lname']);
            $info[$row_lname]['lname'] = $row_lname[1];

            //Cleans middle name and " off first name
            $row_fname1 = explode(' ', $info[$row]['fname']);
            $info[$row]['fname'] = $row_fname1[0];
            $row_fname2 = explode('"', $info[$row]['fname']);
            $info[$row]['fname'] = $row_fname2[0];

            //Declares variables
            $uname = $info[row]['fname'] + "." + $info[$row]['lname'];
            $fname = $info[row]['fname'];
            $lname = $info[$row]['lname'];
            $empid = $info[$row]['empid'];

            //Checks to see if user is already in db
            $query = ("SELECT * FROM user WHERE username = '$uname'");
            $check = mysqli_query($db_handle, $query);
            $num_rows = $check->num_rows;

            //If user isn't in db, generates a password and adds them
            if ($num_rows < 1)
            {
                //Generates random 8 character password
                $length = 8;
                $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
                $charactersLength = strlen($characters);
                for ($i = 0; $i < $length; $i++)
                {
        $randomString[$i] = $characters[rand(0, $charactersLength - 1)];
                }
                $temppass = implode($randomString);
                $pword = password_hash($temppass, PASSWORD_DEFAULT);
                $addto = "INSERT INTO `user`(`username`, `first_name`, `last_name`, `employee_id`, `password_hash`, `isActive`, `firstLogin`) VALUES ('$uname', '$fname', '$lname', '$empid', '$pword', 1, 1)";
                mysqli_query($db_handle, $addto);
            }
        }
    }

有没有更简单的方法解析制表符之后的内容,以便抓取名字和姓氏,并且不会提示错误?

编辑:通过改用 .csv 文件而不是 .txt 文件解决了问题。


1
必须使用纯文本吗?最好使用结构化数据格式,如JSON或XML,但即使使用CSV也会使事情更加明确。这将让你头疼,因为你无法控制输入的质量。例如,通过使用JSON,您至少可以确保在开始尝试解析它之前,已经传递了可解析的文件(即通过执行json_decode(file_get_contents($file)))。 - Mike Miller
它以 .xlsx 格式提供,因此可以转换为 .csv 格式。 - Lance
在foreach中使用file()和explode()函数。 - Robert
1
看看本地CSV函数,它们将为您节省很多工作量。开发以捕获所有边缘情况将耗费时间。http://php.net/manual/en/function.str-getcsv.php - Mike Miller
我会查看的,Mike,谢谢。 - Lance
explode() 很少适用于这样的任务。而且这不像是 CSV,更像是 TSV。使用正则表达式可以更一致地提取信息。也可以避免按行迭代。(我也不会把两种都称作“解析”)。 - mario
4个回答

3

使用正则表达式会使得操作更简单,而且你不需要使用explode('\n')函数,只需使用file()函数即可。

  foreach($rows as $row => $data) { 
     $matches = array();
     preg_match('#([0-9]+).*? "([^""]+?)"#', $data, $matches);
     echo $matches[1]; //id
     echo $matches[2]; //name
  }

您也可以进行更改。

    $txt_file = file_get_contents("../../uploads/updates/$tmpName");
    $rows = explode("\n", $txt_file);

为了

    $rows = file("../../uploads/updates/$tmpName");

此外,要生成随机8位字符串,请使用:
$temppass = bin2hex(openssl_random_pseudo_bytes(4));

它更加安全。


在foreach()中,$t应该是什么? - Lance
1
在您的情况下,它应该是“$data”。我已经编辑了答案。 - Robert
在 echo $matches[] 行上出现了未定义的偏移错误。 - Lance
1
请使用我提供的代码,不要更改任何内容,否则会出现错误。我已经在fiddle中检查过这段代码。这是证明 -> http://ideone.com/u7xDFF - Robert
仍然出现错误,我不知道为什么会这样。不过我会继续尝试找出原因的。谢谢你的帮助!编辑:我插入了你的字符串,它可以工作,所以它在从我的.txt文件中提取数据时遇到了一些问题。 - Lance
所以,您的数据与您在问题中发布的不同,也许您有空字符串,因此您应该在循环中检查这一点。例如 if (empty($data)) { continue; } 此外,您可以检查 preg_match 是否返回 true,如果是,则不会出现未定义的索引。如果返回 false,则应跳过此记录,因为数据无效。 - Robert

0

0

试试这个。while循环的第一行:

//Splits data into employee ID and full name
$row_data   = array_map("trim", array_filter(explode('"', $data)));
$names      = explode(",", $row_data[1]);
$result     = array(
    "id"        => $row_data[0],
    "forname"   => $names[1],
    "surname"   => $names[0],
);

而 $result 应该长这样:

Array
(
    [id] => 186298
    [forname] => Kathy N
    [surname] => Cushing
)

希望这对您有所帮助。

-1

你需要用两个空格进行分隔:

$row_data = explode('  ', $data);

在代码的更上方,添加另一个空格实际上会导致解析错误。 - Lance
我可以看到$info[row]['fname'] + "." + $info[$row]['lname']这种字符串拼接方式是错误的。 - Daan
1
你可以使用 trim($info[$row]['name'], '"') 去掉双引号,这样会更简洁。 - Daan
implode函数正常工作,密码生成器直接从另一个完美运行的函数复制而来。此外,我不知道有trim()函数,谢谢! - Lance

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