【问题标题】:PHP parse a .txtPHP 解析一个 .txt
【发布时间】:2015-10-06 00:05:11
【问题描述】:

我正在开发一个网站,希望管理员能够上传包含员工 ID 和姓名的 .txt 文件。我需要解析 .txt 文件并将信息插入数据库,但在解析时我不断出错。

我尝试遵循PHP - parsing a txt file 的格式,但在我的第一个 $row 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 解决了问题

【问题讨论】:

  • 必须是纯文本吗?最好是像 JSON 或 XML 这样的结构合理的数据格式,否则即使使用 CSV 也会使事情变得更加明确。这注定会让您头疼,因为您无法控制输入的质量。例如,通过使用 JSON,您至少可以确保在开始尝试解析之前传递了一个可解析的文件(即通过执行 json_decode(file_get_contents($file))
  • 它以 .xlsx 格式提供,因此可以转换为 .csv
  • 在foreach中使用file()和explode()
  • 查看原生 CSV 函数,它们会为您省去很多精力。开发以捕获所有边缘情况将非常耗时php.net/manual/en/function.str-getcsv.php
  • 我去看看 Mike,谢谢。

标签: php mysql parsing


【解决方案1】:

遵循https://stackoverflow.com/users/1552594/mike-miller 的建议并从 .txt 文件转换为 .csv 文件。这使得一切都更容易运行并解决了所有错误。

【讨论】:

    【解决方案2】:

    使用正则表达式让它变得更简单,你也不需要 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");
    

    Morover,生成随机的 8 长度字符串使用

    $temppass = bin2hex(openssl_random_pseudo_bytes(4));
    

    它更安全。

    【讨论】:

    • foreach() 中的 $t 应该是什么?
    • 在你的情况下应该是$data我已经编辑了答案
    • 在 echo $matches[] 行上获取未定义的偏移错误
    • 完全使用我给你的代码没有改变你得到这个错误我已经在小提琴中检查了这个代码。这是证据 -> ideone.com/u7xDFF
    • 仍然抛出错误,我不知道它为什么会这样做。不过,我会继续努力弄清楚。谢谢您的帮助!编辑:我插入了你的字符串并且它工作了,所以它在尝试从我的 .txt 文件中提取数据时遇到了一些问题。
    【解决方案3】:

    试试这个。 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
    )
    

    希望这有帮助。

    【讨论】:

      【解决方案4】:

      你需要用 2 个空格爆炸:

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

      【讨论】:

      • 添加另一个空格实际上会导致代码进一步解析错误。
      • 我可以看到$info[row]['fname'] + "." + $info[$row]['lname'] 这是连接字符串的错误方式。
      • 你可以把trim($info[$row]['name'], '"')的双引号去掉,这要短得多。
      • 内爆有效,密码生成器直接从另一个运行良好的功能复制。另外,我不知道有一个 trim() 函数,谢谢!
      猜你喜欢
      • 2011-07-15
      • 1970-01-01
      • 1970-01-01
      • 2016-05-21
      • 2011-05-12
      • 2014-03-28
      • 1970-01-01
      • 1970-01-01
      • 2014-01-18
      相关资源
      最近更新 更多