我有一个表单,允许用户上传文本文件或将文件的内容复制/粘贴到textarea.我可以很容易地区分这两者并将他们输入的任何一个放入一个字符串变量,但是我从那里去哪里?
我需要遍历字符串的每一行(最好不要担心不同机器上的换行符),确保它只有一个令牌(没有空格,制表符,逗号等),清理数据,然后生成SQL查询基于所有线条.
我是一个相当优秀的程序员,所以我知道如何做到的一般想法,但是我用PHP工作已经很久了,我觉得我在寻找错误的东西,从而得出无用的信息.我遇到的关键问题是我想逐行读取字符串的内容.如果它是一个文件,那将很容易.
我主要寻找有用的PHP函数,而不是如何做到的算法.有什么建议?
Kyr*_*ril 170
preg_split 包含文本的变量,并遍历返回的数组:
foreach(preg_split("/((\r?\n)|(\r\n?))/", $subject) as $line){
// do stuff with $line
}
Run Code Online (Sandbox Code Playgroud)
Erw*_*els 141
我想提出一个明显更快(和内存效率)的替代方案:strtok而不是preg_split.
$separator = "\r\n";
$line = strtok($subject, $separator);
while ($line !== false) {
# do something with $line
$line = strtok( $separator );
}
Run Code Online (Sandbox Code Playgroud)
测试性能,我在17000行测试文件上迭代100次:preg_split花了27.7秒,而strtok花了1.4秒.
请注意,虽然$separator定义为"\r\n",strtok将在任一字符上分开 - 从PHP4.1.0开始,跳过空行/标记.
请参阅strtok手册条目:http: //php.net/strtok
Fer*_*rCa 94
如果你需要处理不同系统中的换行,你可以简单地使用PHP预定义常量PHP_EOL(http://php.net/manual/en/reserved.constants.php)并简单地使用explode来避免正则表达式引擎的开销.
$lines = explode(PHP_EOL, $subject);
Run Code Online (Sandbox Code Playgroud)
pgu*_*rio 18
这是过于复杂和丑陋,但在我看来这是要走的路:
$fp = fopen("php://memory", 'r+');
fputs($fp, $data);
rewind($fp);
while($line = fgets($fp)){
// deal with $line
}
fclose($fp);
Run Code Online (Sandbox Code Playgroud)
strtok:由于建议的解决方案之一使用strtok,不幸的是它没有指出潜在的内存问题(尽管它声称内存效率高)。当使用strtok根据本手册中,:
请注意,只有第一次调用 strtok 时才使用字符串参数。每次对 strtok 的后续调用只需要使用令牌,因为它会跟踪它在当前字符串中的位置。
它通过将文件加载到内存中来做到这一点。如果您使用的是大文件,则在完成对文件的循环后,您需要刷新它们。
<?php
function process($str) {
$line = strtok($str, PHP_EOL);
/*do something with the first line here...*/
while ($line !== FALSE) {
// get the next line
$line = strtok(PHP_EOL);
/*do something with the rest of the lines here...*/
}
//the bit that frees up memory
strtok('', '');
}
Run Code Online (Sandbox Code Playgroud)
根据手册,对于文件上传部分,您可以使用以下file命令:
//Create the array
$lines = file( $some_file );
foreach ( $lines as $line ) {
//do something here.
}
Run Code Online (Sandbox Code Playgroud)
考虑到您需要能够在不同的机器上处理换行符,基里尔的答案是最好的。
“我主要是在寻找有用的 PHP 函数,而不是如何实现它的算法。有什么建议吗?”
我经常使用这些:
foreach(preg_split('~[\r\n]+~', $text) as $line){
if(empty($line) or ctype_space($line)) continue; // skip only spaces
// if(!strlen($line = trim($line))) continue; // or trim by force and skip empty
// $line is trimmed and nice here so use it
}
Run Code Online (Sandbox Code Playgroud)
^ 这是您正确断行的方式,跨平台兼容Regexp:)
| 归档时间: |
|
| 查看次数: |
125619 次 |
| 最近记录: |