[PHP] Unicode/charset problemen in uitlezen .txt

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Allen,

Ik zit met een probleem waar ik al een hele ochtend mee bezig ben en inmiddels de bomen niet meer kan zien door het bos. Het gaat, in het kort, om een PHP-script dat uiteindelijk een dir doorloopt en alle files die erin staan uitleest en de inhoud ervan in een database propt. De bestanden in die dir zijn SMS-berichten die ik via Nokia PC Suite uit mijn telefoon heb gehaald. Dat programma maakt .vmg-bestanden aan maar zijn feitelijk plain-text; zij het in een bepaalde characterset/codering. En daar begint het probleem.

Allereerst het txt-file; dat is gewoon het .vmg bestand hernoemd naar .txt. De inhoud van het bericht wordt in Notepad goed weergegeven, alleen de newlines worden door []-hokjes vervangen. De TXT staat hier: http://schellevis.org/sms/Testbericht.txt (Save as...)

Dan nu PHP: wanneer ik de inhoud van het bestand uitlees en in een variabele plak gaat dit allemaal goed, de verdere verwerking van de string echter niet. Het probleem is dat er tussen elk teken in het bestand een soort 'spatie' of ander teken staat waardoor een str_replace op 'testbericht' bijvoorbeeld niets oplevert. Als je de source in IE bekijkt maakt hij er ook het volgende van:

code:
1
T e s t b e r i c h t


De gewone output die je in IE ziet is echter wél goed leesbaar, daar zie je niks aan af: http://schellevis.org/readsms.php

Nu heb ik al veel uitgezocht en ik weet dat ik het in de hoek van Unicode/charset achtige dingen moet zoeken. Namelijk:
- Wanneer ik de .txt in Word probeer te openen vraagt hij welke encoding het is: alléén bij 'Unicode' (dus geen UTF-8) laat Word het bericht goed zien, bij elke andere encoding zet Word er ook [] tussen.
- Wanneer ik met mb_detect_encoding de uitgelezen .txt analyseer zegt hij dat het ASCII is
- Wanneer ik de platte tekst (zoals IE output) hard als value in mijn script plak werkt mijn verwerking van de string wél
- Wanneer ik een Windows-tooltje gebruik om de codering naar UTF-8 te converteren van ISO-8859-1 dan krijg ik netjes de goede tekst
- Wanneer ik het .txt-bestand open en opnieuw opsla als .txt krijg ik ook een goede tekst
- unicode_encode en _decode zijn experimental in PHP, met utf8_encode en _decode kan ik volgens mij niks

Kort samengevat kan ik dus concluderen dat het in Unicode (niet UTF-8 of -16) of een andere vage codering is die PHP niet kan verwerken. Dit kan ik handmatig aanpassen, het doel is juist om dit geautomatiseerd te kunnen. Is er iemand die een idee heeft hoe ik deze string met PHP kan converteren naar een gewone UTF-8 codering? Of hoe ik erachter kan komen wat voor teken het is en hoe ik deze eruit kan slopen? Alvast heel erg bedankt! :)



Voor de volledigheid de PHP-code, waarbij ik vooralsnog maar één ding met die string wil: exploden bij 'X-NOK-DT'. Omdat hij dat deel niet kan vinden (de string bevat namelijk eigenlijk iets als 'X - N O K - D T') zet hij de hele string onder de eerste value van het array.

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?php

$dir_handle = opendir($sms_dir);

while ($file_name = readdir($dir_handle))   {

    if ($file_name != "." && $file_name != "..")    {
    
        $file_path = $sms_dir . $file_name;
    
        $file_handle = fopen($file_path, 'rw');
        
        $string = fread($file_handle, filesize($file_path));
        
        fclose($file_handle);
        
        $explode = explode('X-NOK-DT',$string);
        
        print_r($explode);  
    
        echo "<BR>";
    
    }
    
}

closedir($dir_handle);

?>

Acties:
  • 0 Henk 'm!

  • DanielG
  • Registratie: Oktober 2005
  • Laatst online: 08-09 15:36

DanielG

i = 0x5f3759df - (i>>1); ☠₧ℳ🀪❣

Er zit in Testbericht.txt (als je kijkt met Wordpad) een blokje na elk teken, dus het is niet zomaar een "plain text" bestand.
Als je het bestand met een hex editor opent zie je na elk 'normaal' teken een NULL byte (hex: 00).

Ik zou dat er maar eerst uit filteren.

http://xyproblem.info/


Acties:
  • 0 Henk 'm!

  • Johnny
  • Registratie: December 2001
  • Laatst online: 14:39

Johnny

ondergewaardeerde internetguru

Verwijderd schreef op maandag 07 juli 2008 @ 13:36:
Als je de source in IE bekijkt maakt hij er ook het volgende van:

code:
1
T e s t b e r i c h t
Met welke encoding kijk je er dan naar? Als er geen encoding wordt meegestuurd zal IE zelf een beetje gaan raden wat er soms toe leidt dat hij de verkeerde kiest. Kijk in het menu welke encoding wordt gebruikt en stel handmatig een andere in om er achter te komen welke er wel goed werkt.
Kort samengevat kan ik dus concluderen dat het in Unicode (niet UTF-8 of -16) of een andere vage codering is die PHP niet kan verwerken. Dit kan ik handmatig aanpassen, het doel is juist om dit geautomatiseerd te kunnen. Is er iemand die een idee heeft hoe ik deze string met PHP kan converteren naar een gewone UTF-8 codering? Of hoe ik erachter kan komen wat voor teken het is en hoe ik deze eruit kan slopen? Alvast heel erg bedankt! :)
Het gaat hier om een multibyte string (2 bytes per karakter), in PHP zitten een heleboel mb_ functies zoals http://nl.php.net/manual/en/function.mb-convert-encoding.php die waarschijnlijk beter werken.

Aan de inhoud van de bovenstaande tekst kunnen geen rechten worden ontleend, tenzij dit expliciet in dit bericht is verwoord.


Acties:
  • 0 Henk 'm!

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 06-09 00:37

curry684

left part of the evil twins

Dat is UTF-16 als ik het zo zie,en dat zou je moeten kunnen converteren met:
PHP:
1
$output = iconv("utf-16", "iso-8859-1", $str);

iconv installen kan wat kut zijn though. PHP heeft verder weinig UTF-16 support.

UTF-16 hoort overigens ook een marker in het begin te hebben, daardoor lezen Wordpad en Notepad hem niet correct. Als je het bestand prefixt met 0xFFFD zouden zij het alweer goed moeten lezen. Onder bepaalde NT-notepads kun je het geloof ik ook bij Open/Save dialogs ingeven.

Professionele website nodig?


Acties:
  • 0 Henk 'm!

  • MarCreative
  • Registratie: Februari 2008
  • Laatst online: 18-06 14:47
Een goede gewoonte is om files binairy te openen, dit kan het probleem al oplossen. Lees hiervoor www.php.net/fopen. In feite zet je er gewoon een b achter. Je krijgt dan:
code:
1
fopen($file_path, 'rb');


Ten tweede kun je de "vreemde tekens" er uit filteren met een reguliere expressie. Ik hoop je hier mee op weg te helpen.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
curry684 schreef op maandag 07 juli 2008 @ 14:04:
Dat is UTF-16 als ik het zo zie,en dat zou je moeten kunnen converteren met:
PHP:
1
$output = iconv("utf-16", "iso-8859-1", $str);

iconv installen kan wat kut zijn though. PHP heeft verder weinig UTF-16 support.
Thanks, dat was hem! Even converteren en nu kan ik hem verder als string verwerken. Allemaal super bedankt voor de hulp! :*

Acties:
  • 0 Henk 'm!

  • TeeDee
  • Registratie: Februari 2001
  • Laatst online: 19:47

TeeDee

CQB 241

MarCreative schreef op maandag 07 juli 2008 @ 14:04:
Ten tweede kun je de "vreemde tekens" er uit filteren met een reguliere expressie. Ik hoop je hier mee op weg te helpen.
Een Regex op een string los laten puur en alleen maar omdat de in- en output encoding niet matchen is een beetje een vreemde oplossing imo.

Heart..pumps blood.Has nothing to do with emotion! Bored


Acties:
  • 0 Henk 'm!

  • Icelus
  • Registratie: Januari 2004
  • Niet online
Verwijderd schreef op maandag 07 juli 2008 @ 14:20:
[...]

Thanks, dat was hem! Even converteren en nu kan ik hem verder als string verwerken. Allemaal super bedankt voor de hulp! :*
Houd er rekening mee dat je hiermee wel tekens verliest die niet in 8859-1 voorkomen; bijvoorbeeld het euroteken.

Developer Accused Of Unreadable Code Refuses To Comment


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ja, dat had ik inderdaad ook al bedacht. Is niet zo erg omdat het om SMS-berichten gaat. Daar zijn mensen meestal niet zo scheutig met vreemde tekens ;)

Acties:
  • 0 Henk 'm!

  • TeeDee
  • Registratie: Februari 2001
  • Laatst online: 19:47

TeeDee

CQB 241

Verwijderd schreef op maandag 07 juli 2008 @ 15:08:
Ja, dat had ik inderdaad ook al bedacht. Is niet zo erg omdat het om SMS-berichten gaat. Daar zijn mensen meestal niet zo scheutig met vreemde tekens ;)
Kan je het e.e.a. niet meteen naar 8859-15 converteren? Daar zit afaik wel gewoon een euroteken in.

Heart..pumps blood.Has nothing to do with emotion! Bored


Acties:
  • 0 Henk 'm!

  • Icelus
  • Registratie: Januari 2004
  • Niet online
TeeDee schreef op maandag 07 juli 2008 @ 15:10:
[...]

Kan je het e.e.a. niet meteen naar 8859-15 converteren? Daar zit afaik wel gewoon een euroteken in.
Inderdaad.
Als je per se 8859-1 nodig hebt kun je de codering ook wijzigen in ‘8859-1//translit’; iconv probeert dan niet-bestaande tekens om te zetten. Een € wordt dan omgezet in ‘EUR’.

Developer Accused Of Unreadable Code Refuses To Comment


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:42

.oisyn

Moderator Devschuur®

Demotivational Speaker

curry684 schreef op maandag 07 juli 2008 @ 14:04:
UTF-16 hoort overigens ook een marker in het begin te hebben, daardoor lezen Wordpad en Notepad hem niet correct. Als je het bestand prefixt met 0xFFFD zouden zij het alweer goed moeten lezen. Onder bepaalde NT-notepads kun je het geloof ik ook bij Open/Save dialogs ingeven.
FF FE (op little endian machines) ;)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • LoBbY_1
  • Registratie: Juli 2002
  • Laatst online: 17-09 20:43
Let even op de smsjes die je hebt ingelezen!!! Zo kan iedereen nu zien wat je hebt ontvangen, ik denk niet dat het de bedoeling is dat mensen dat lezen :P Als het test smsjes zijn dan heb je iig wel humor :P

Een echte golver is nooit uitgeput


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:42

.oisyn

Moderator Devschuur®

Demotivational Speaker

Icelus schreef op maandag 07 juli 2008 @ 15:13:
[...]
Inderdaad.
Als je per se 8859-1 nodig hebt kun je de codering ook wijzigen in ‘8859-1//translit’; iconv probeert dan niet-bestaande tekens om te zetten. Een € wordt dan omgezet in ‘EUR’.
Ik zou gewoon UTF-8 aanhouden, dan heb je geen probleem met missende tekens en je kunt naar hartelust str_replace() aanroepen en het in databases stoppen. Als je vreemde tekens in je PHP source hebt staan is het wel handig dat die source ook in UTF-8 is.

[ Voor 12% gewijzigd door .oisyn op 07-07-2008 15:49 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.

Pagina: 1