2010-09-26 9 views
8

Lets sagen, ich habe eine Datei namens foo.txt codiert in UTF-8: in dieser Datei (eine ZeileArbeiten mit Dateien und UTF-8 in PHP

aoeu 
qjkx 
ñpyf 

Und ich möchte ein Array erhalten, die die Linien alle enthält pro Index), die die Buchstaben aoeuñpyf haben, und nur die Zeilen mit diesen Buchstaben.

Ich schrieb den folgenden Code (auch als utf8 codiert):

$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); 

jedoch danach, die $lines Array hat genau die aoeu Linie darin.
Das scheint zu sein, weil irgendwie das "ñ" in $allowed_letters nicht dasselbe ist wie das "ñ" in foo.txt.
Auch wenn ich ein "ñ" der Datei drucke, erscheint ein Fragezeichen, aber wenn ich es so print "ñ"; drucke, funktioniert es.
Wie kann ich es funktionieren lassen?

+2

Wahrscheinlich Ihre „ñ“ s nicht gleich sind: Die eine ist ein einziges „ñ“ Symbol und ein anderer ist [aus zwei Zeichen kombiniert] (http://en.wikipedia.org/wiki/Unicode#Combining_characters). –

+0

Nein, das ist nicht der Fall. Spanische Tastaturen haben einen ñ-Schlüssel und schreiben ein einzelnes Zeichen. –

Antwort

10

Wenn Sie Windows ausführen, speichert das Betriebssystem keine Dateien in UTF-8, aber in cp1251 (oder etwas ...) müssen Sie die Datei standardmäßig in diesem Format speichern oder jede Zeile zuvor in utf8_encode() ausführen Ihren Scheck durchführen. D.h .:

$line=utf8_encode(fgets($f)); 

Wenn Sie sicher sind, dass die Datei UTF-8 codiert sind, ist Ihre PHP-Datei auch UTF-8 kodiert?

Wenn alles UTF-8, dann ist es das, was Sie brauchen:

foreach(preg_split("//u",$line,-1,PREG_SPLIT_NO_EMPTY) as $letter){ 
    // ... 
} 

(anhängen u für Unicode-Zeichen)

Aber lassen Sie mich noch schneller Weg schlagen Sie uns Ihre ausführen Check:

$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); 

(Raum Zeichen in den Raum Zeichen erlauben auch, und entfernen Sie die rtrim($line))

+0

Woha, woaha woaha !!! Das hat funktioniert!!! (Anhängen der "u", ich betreibe Linux). Vielen Dank! –

0

Es klingt, als hätten Sie Ihre Antwort bereits erhalten, aber es ist wichtig zu erkennen, dass Unicode-Zeichen auf verschiedene Arten gespeichert werden können. Unicode-Normalisierung * ist ein Prozess, der dazu beitragen kann, dass die Vergleiche wie erwartet funktionieren.

2

in UTF-8, wird ñ als zwei Bytes codiert. Normalerweise sind in PHP alle String-Operationen bytebasiert. Wenn Sie also die Eingabe preg_split eingeben, teilt sie das erste Byte und das zweite Byte in separate Array-Elemente auf. Weder das erste Byte allein noch das zweite Byte selbst werden beide Bytes zusammenpassen, wie in $allowed_letters gefunden, so dass es niemals ñ entspricht.

Wie Yanick posted, ist die Lösung, den u Modifizierer hinzuzufügen. Dies bewirkt, dass die PHP-Regex-Engine sowohl das Muster als auch die Eingabezeile als Unicode-Zeichen anstelle von Bytes behandelt. Es ist ein Glück, dass PHP hier spezielle Unicode-Unterstützung hat; An anderer Stelle ist die Unicode-Unterstützung von PHP extrem fleckig.

Ein einfacherer und schnellerer Weg als das Teilen wäre der Vergleich jeder Zeile mit einem Zeichengruppen-Regex.Auch dies muss ein u Regex sein.

if(preg_match('/^[aoeuñpyf]+$/u', $line)) 
    $lines[]= $line; 
+0

+1 für eine gute Lösung mit preg_match() –