Prosíme přihlašte se nebo zaregistrujte.

Přihlašte se svým uživatelským jménem a heslem.
Vaše pomoc je stále potřeba!

Autor Téma: Apache, PHP, UTF-8  (Přečteno 5687 krát)

josef_m

  • Host
Apache, PHP, UTF-8
« kdy: 22 Října 2009, 17:37:31 »
Zdravím,

často zpracovávám soubory (prostý text, UTF-8) pomocí PHP skriptu, výsledek se ukládá do dalšího .txt souboru (UTF-8). Aniž bych něco měnil v nastavení Apache (kromě umístění složky pro localhost), "najednou" mi to výsledný soubor ukládá ve Windows CP1250, takže výsledek nepoužitelný. Nenapadá mě nic jiného, než souvislost s nějakou aktualizací Ubuntu? Má někdo podobný problém? Tip jak z toho ven?

V souboru "/etc/apache2/conf.d/charset" jsem zrušil komentář pro řádek "AddDefaultCharset UTF-8", restart Apache a nic...

Soubor "/etc/apache2/httpd.conf" je prázdný.

Měnil jsem jen umístění výchozí složky pro "localhost", ale to mám tak nastavené od začátku a vždy to jelo

Šuohob

  • Závislák
  • ***
  • Příspěvků: 2171
Re: Apache, PHP, UTF-8
« Odpověď #1 kdy: 22 Října 2009, 18:17:22 »
Je ten skript vytvořen také v kódování UTF-8?
Tak dlouho se vrzá s Acerem, až se displej utrhne.

josef_m

  • Host
Re: Apache, PHP, UTF-8
« Odpověď #2 kdy: 23 Října 2009, 10:04:44 »
ano, v PSpadu jsem kontroloval jak výchozí soubor, tak i skript. Na netu jsem pár podobných problémů našel, ale pokud jsem dobře rozumněl, tak šlo o HTML dokumenty a tím pádem nutno upravovat hlavičku, ale u mě se jedná o "plaintext" soubory.

mka

  • Závislák
  • ***
  • Příspěvků: 1907
  • Chybovat je moje.
    • Příložany Cé Zet
Re: Apache, PHP, UTF-8
« Odpověď #3 kdy: 23 Října 2009, 10:18:06 »
A jaké funkce používáš pro práci s textovými řetězci? obyčejné nebo multibyte?

josef_m

  • Host
Re: Apache, PHP, UTF-8
« Odpověď #4 kdy: 23 Října 2009, 10:33:05 »
Tos mě překvapil, já jsem netušil, že se to ještě nějak dělí.

Pro zajímavost skript připojuji níže; cíl skriptu: prostý textový soubor je zpracován tak, aby byl každý záznam (slovo, číslo či interpunkce) na novém řádku, a tím se získá výchozí dokument pro další zpracování (komentáře jsou ale německy, protože se jedná o česko-německý projekt)

Protože všechno donedávna fungovalo, tak mě nenapadlo hledat chybu ve skriptu, spíš Apache vs. aktualizace Ubuntu (?)

Kód: [Vybrat]
<?php
header
('content-type: text/html; charset=utf-8');
print <<<EndOfHtml
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
  <title>W-liste-GR-de</title>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
EndOfHtml;

// die zu bearbeitende Quelldatei - darf nicht geändert werden
// die Quelldatei für Wortliste wurde mit XSLT gewonnen als Plaintext File

//$startdatei = "grass_de_plaintext.txt";
$startdatei "grass_de_ohne.txt";

$zieldatei "grass_wortliste_ziel.txt";
if ( 
file_exists ($zieldatei)) {
unlink ($zieldatei);
}

////////////////////////// Start der Bearbeitung //////////////////////////////
if (! file_exists($startdatei)) {
    echo 
"<b>Die Datei</b> \"$startdatei\" <b>existiert <font size=\"+1\" color=\"red\">NICHT</font></b><br /><br /><br />";
    exit;
} else {
$fp fopen $startdatei'r' );       // Name der Datei wird in die Variable $fp platziert - Pointer

$datei_inhalt fread $fpfilesize $startdatei ) );  // die Datei wird eingelesen
fclose $fp );
}

    
$muster="/[  ]/";
    
$replace=" ";
    
$datei_inhalt preg_replace($muster,$replace,$datei_inhalt);
    
    
$muster="/[\r\n]?[\r\n]?[\?|\!|\.|,|:|;|«|»|‹|›|„|“|…|\(|\)|\/|´|'|&|\"]/";
    
$replace="";
    
$erg preg_replace($muster,$replace,$datei_inhalt);

///////////////////////////////////////////////////////////
// das folgende Ziel ist: die Wortgrenze wird durch einen Stern gekennzeichnet

$muster="/[\r\n][\r\n]|[\r\n]/";   // löscht die Leerzeilen
$replace=" ";
$erg preg_replace($muster,$replace,$erg);   

$erg preg_replace("/    |   |  /"," ",$erg);  // mehrere Leerzeichen zu einem

$erg preg_replace("/\ /"," *",$erg);  
// Wortende: 'Blank+Stern' - muss nicht sein, aber Stern wird bei Array Erstellung/Auflösung verwendet und Blank bleibt als Wortgrenze erhalten

//$erg = strtolower($erg);   // wegen der Sortierung werden alle Anfangsbuchstaben kleingesetzt

///////////////////////////////////////////////////////////////
// Ziel hier: Array bilden

$array split "\*"$erg );

//$element1 = array_shift ( $array ); // das erste Array-Element wird rausgenommen
sort $array );  // das Array wird alphabetisch sortiert

///////////////////////////////////////////////////////////////
// Ziel: sortierter Inhalt 

$zaehle array_count_values $array );   // berechnet, wie oft ein jeweiliges Wort vorkommt

while ( list ( $key$val ) = each $zaehle ) )
{
    
$laenge strlen $val );  // wegen Sortierung: misst die Länge von Inhalt der Variable $val

    
if ( $laenge == ) {     // wegen Sortierung: überprüft die Länge von $val, wenn 1, fügt drei Nullen hinzu
      
$val = ("000".$val);
    }
    
    if ( 
$laenge == ) {     // wegen Sortierung: überprüft die Länge von $val, wenn 2, fügt zwei Nullen hinzu
      
$val = ("00".$val);
    }
    
    if ( 
$laenge == ) {     // wegen Sortierung: überprüft die Länge von $val, wenn 1, fügt eine Null hinzu
      
$val = ("0".$val);
    }
    
    
$erg_sortiert .=  "$val " $key *";  // die zwei Ausgabewerte werden in eine Variable gesteckt
}

///////////////////////////////////////////////////////////////
// Ziel: sortiertes Ergebnis von Nummerieren weiter bearbeiten

$array_d_inhalt split "\*"$erg_sortiert ); // erneut wird ein Array gebildet
//$element2 = array_shift ( $array_d_inhalt ); // das erste Array-Element wird rausgenommen
sort $array_d_inhalt );  // Sortierung des Arrays

foreach ( $array_d_inhalt as $array_d_zeilen ) {  // das Array wird in Einzelementen gezeigt
            
    
$muster="/(?<=[0-9]{4})( )( )?/";
    
$replace="\t";
    
$array_d_zeilen preg_replace($muster,$replace,$array_d_zeilen);
    
    
$zusammen .= "$array_d_zeilen"\r\n";
        
    
$muster="/( )( )?(?=[\r\n])/";
    
$replace="";
    
$zusammen preg_replace($muster,$replace,$zusammen);
    }

/////// ----------------------------

$fp fopen $zieldatei'a+' );   
  
fwrite $fp$zusammen );        // schreibt den Inhalt von $erg in die neue Datei
  
fclose $fp );  // die Datei $wlnmrt wird geschlossen, erst hier, damit sie nicht nach jedem Eintrag getrennt geöffnet und geschlossen werden muss

?>

</body>
</html>


EDIT: promiňte, popis skriptu je zde špatně, to je předchozí krok, tento skript vychází z textového souboru, kde: co záznam to nový řádek. Cíl: abecední seznam slov (plaintext file), a u těch, která se opakují bude vypsáno, kolikrát se v textu vyskytují.
« Poslední změna: 23 Října 2009, 20:29:56 od josef_m »

mka

  • Závislák
  • ***
  • Příspěvků: 1907
  • Chybovat je moje.
    • Příložany Cé Zet
Re: Apache, PHP, UTF-8
« Odpověď #5 kdy: 23 Října 2009, 10:51:42 »
Řekl bych, že tvoje cesta vede přes PHP manuál, kapitola Multibyte String Functions. Nicméně preg_ funkce nepoužívám, použímám mb_ereg_, takže netuším, v čem jsou ty preg_ jiné...

Iljusin

  • Aktivní člen
  • *
  • Příspěvků: 347
Re: Apache, PHP, UTF-8
« Odpověď #6 kdy: 23 Října 2009, 16:36:59 »
Multibyte funkce s tím nemají dle mého soudu nemá nic společnýho. Ty jsou dobrý pro případ, že už pracuješ s nějakým multibyte řetězcem a ten ty zatím nemáš.
Spíš se zkus podívat do php.ini zda tam máš direktivu:
Kód: [Vybrat]
default_charset = "UTF-8"

Šuohob

  • Závislák
  • ***
  • Příspěvků: 2171
Re: Apache, PHP, UTF-8
« Odpověď #7 kdy: 23 Října 2009, 16:49:40 »
kazdy "plaintext" je nejak kodovan... zkus se podivat jeste jinym editorem nez pspadem, ze ten PHP skript je skutecne v UTF-8. Napriklad geditem, phpeditem atd...
Tak dlouho se vrzá s Acerem, až se displej utrhne.

Iljusin

  • Aktivní člen
  • *
  • Příspěvků: 347
Re: Apache, PHP, UTF-8
« Odpověď #8 kdy: 23 Října 2009, 17:18:04 »
Samozřejmě, že každý plaintext je nějak kódován, já jsem také netvrdil, že ne. Ale multibyte funkce ti přeci nemění vstupní a výstupní kódování, takže jejich nasazením si nepomůžeš. Zmíněný php script otevře a přečte soubor $startdatei chybně v kódování CP1250 (tudíž ne multibyte) a ve stejném kódování jej pak zpracovaný i uloží. Je potřeba zajistit aby vstupní soubor byl již přečten v UTF-8 (a ve stejném pak i uložen). O to tu běží.

Je samozřejmě pravda, že když je předpoklad toho, že se bude pracovat s UTF, bylo by vhodné multibyte funkce používat, ale to není řešení stávajícího problému. Si myslim.

josef_m

  • Host
Re: Apache, PHP, UTF-8
« Odpověď #9 kdy: 23 Října 2009, 18:59:29 »
Bohouš: např. Geany ukazuje taky UTF-8

Iljusin: v php.ini jsem mel
Kód: [Vybrat]
;default_charset = "iso-8859-1"zmenil jsem to na
Kód: [Vybrat]
default_charset = "UTF-8"ale (i po restartu Apache) je to pořád stejné, tzn. cílový dokument má změněno kódování a já se nemůžu hnout z místa

Iljusin

  • Aktivní člen
  • *
  • Příspěvků: 347
Re: Apache, PHP, UTF-8
« Odpověď #10 kdy: 23 Října 2009, 19:32:46 »
Když si vypíšeš $datei_inhalt na obrazovku, je to ve správném kódování?
Když si vypíšeš $zusammen na obrazovku, je to ve správném kódování?
Když si dáš phpinfo(), vypíše ti to tam někde něco s 1250 (CP1250, Win1250, Win-1250) nebo nějakým ISO-8859?

josef_m

  • Host
Re: Apache, PHP, UTF-8
« Odpověď #11 kdy: 23 Října 2009, 21:00:40 »
Po vypsání obsahu uvedené proměnné na obrazovku:

- "$datei_inhalt" - všechny znaky v pohodě
(
- první problém u "$erg" (tj. po odstranění diakritiky) je špatně interpretováno přehlasované "u" ("ü") - malé i velké, jen na začátku slova, např. uprostřed slova je "ü" v pořádku (!), ostatní přehlásky jsou ok
(vyřazením tohoto kroku kupodivu skript text již nevidí, vypíše jen, že v celém textu je jen jednou "nic"; když bych místo vypsání všech těch interpunkčních znaků zadal "\W", tak to smaže i znak konce řádku, ale ten je tam ještě zapotřebí, proto jsem ty znaky vypisoval)
)
- "$zusammen" - stejně jak v předchozím kroku, tj. vše ok až na některé výskyty "ü"

- phpinfo() - na výstupu:
-> "1250" - nikde
-> ISO-8859 tady:
Kód: [Vybrat]
Apache Environment
HTTP_ACCEPT_CHARSET ISO-8859-2,utf-8;q=0.7,*;q=0.7

HTTP Headers Information
Accept-Charset ISO-8859-2,utf-8;q=0.7,*;q=0.7

iconv
Directive             Local Value   Master Value
iconv.input_encoding ISO-8859-1 ISO-8859-1
iconv.internal_encoding ISO-8859-1 ISO-8859-1
iconv.output_encoding ISO-8859-1 ISO-8859-1


PHP Variables
_SERVER["HTTP_ACCEPT_CHARSET"] ISO-8859-2,utf-8;q=0.7,*;q=0.7

Iljusin

  • Aktivní člen
  • *
  • Příspěvků: 347
Re: Apache, PHP, UTF-8
« Odpověď #12 kdy: 23 Října 2009, 21:38:16 »
Takže problém bude opravdu nejspíš v tom, že nepoužíváš mb funkce. Ty jsi psal, že výsledný soubor je v CP1250, ale asi to tak není, když se ti znaky (až na výjimky) zobrazují správně. Jak jsi vůbec přišel na to že je to v CP1250?
Dej na začátek skriptu
Kód: [Vybrat]
mb_internal_encoding("UTF-8");a pak používej mb_ prefix u stringových funkcí (mb_preg_replace, mb_strlen, ...) Uvidíš jestli to pomůže

josef_m

  • Host
Re: Apache, PHP, UTF-8
« Odpověď #13 kdy: 24 Října 2009, 07:45:48 »
Když si dám vypsat obsah proměnných na obrazovku, tak to je vlastně pořád výchozí soubor, byť upravený. Cílový soubor vzniká až v posledním kroku skriptu a na obrazovce nic není. Když otevřu cílový soubor (např. v PSpadu), tak je kódování zvláštních znaků totálně rozhozené a v liště je vidět, že se jedná o CP1250.
Ty mb funkce hned vyzkouším.

Iljusin

  • Aktivní člen
  • *
  • Příspěvků: 347
Re: Apache, PHP, UTF-8
« Odpověď #14 kdy: 24 Října 2009, 10:32:02 »
Citace
... tak je kódování zvláštních znaků totálně rozhozené a v liště je vidět, že se jedná o CP1250
No a to je právě chybný úsudek. Pakliže na začátku plaintextu není značka která by natvrdo řekla o jaké jde kódování (BOM), tak PSpad jeho kódování pouze odhadne. V případě tvého souboru to odhadl špatně (kvůli některým "rozbitým" znakům) a otevřel jej jako CP1250. Kdybys mu vnutil otevřít to jako UTF8, předpokládám, že se ti obsah zobrazí stejně jako když si výstup vyplivneš v PHP scriptu rovnou na obrazovku, tj., že většina znaků je správně. Tím chci říct, že tvůj výstupní soubor je stále v UTF8, ale díky tomu, že jsi nepoužil mb funkce, tak ti to některé znaky rozbilo (a PSPad je z toho zmatený).

 

Provoz zaštiťuje spolek OpenAlt.