在PHP中使用文件和utf8

Ger*_*set 8 php unicode file-io utf-8

假设我有一个名为foo.txt的文件,在utf8中编码:

aoeu  
qjkx
ñpyf
Run Code Online (Sandbox Code Playgroud)

我想得到一个数组,其中包含该文件中的所有行(每个索引一行),其中包含字母aoeuñpyf,并且只包含带有这些字母的行.

我编写了以下代码(也编码为utf8):

$allowed_letters=array("a","o","e","u","ñ","p","y","f");

$lines=array();
$f=fopen("foo.txt","r");
while(!feof($f)){
    $line=fgets($f);
    foreach(preg_split("//",$line,-1,PREG_SPLIT_NO_EMPTY) as $letter){
        if(!in_array($letter,$allowed_letters)){
            $line="";
        }
    }
    if($line!=""){
        $lines[]=$line;
    }
}
fclose($f);
Run Code Online (Sandbox Code Playgroud)

然而,在那之后,$lines数组中只有aoeu线.
这似乎是因为不知何故,$allowed_letters"ñ"与foo.txt中的"ñ"不同.
此外,如果我打印文件的"ñ",会出现一个问号,但如果我这样打印print "ñ";,它就会起作用.
我怎样才能使它工作?

Yan*_*hon 10

如果您运行的是Windows,则操作系统不会以UTF-8保存文件,但是在cp1251(或其他...)中,默认情况下您需要以该格式显式保存文件,或者utf8_encode()在执行检查之前运行每一行.即:

$line=utf8_encode(fgets($f));
Run Code Online (Sandbox Code Playgroud)

如果您确定该文件是UTF-8编码的,那么您的PHP文件是否也是UTF-8编码的?

如果一切都是UTF-8,那么这就是你需要的:

foreach(preg_split("//u",$line,-1,PREG_SPLIT_NO_EMPTY) as $letter){
   // ...
}
Run Code Online (Sandbox Code Playgroud)

(附加uunicode字符)

但是,让我建议一种更快捷的方式来执行检查:

$allowed_letters=array("a","o","e","u","ñ","p","y","f");

$lines=array();
$f=fopen("foo.txt","r");
while(!feof($f)){
    $line=fgets($f);

    $line = str_split(rtrim($line));
    if (count(array_intersect($line, $allowed_letters)) == count($line)) {
            $lines[] = $line;
    }
}
fclose($f);
Run Code Online (Sandbox Code Playgroud)

(添加空格字符以允许空格字符,并删除rtrim($line))