Autor Zpráva
joe
Profil
Zdravím,

jsem si vědom toho, že to sem nepatří, ale myslím si, že pár lidí by mi odtud mohlo pomoci s následujícím problémem.

Snažim se rozpoznat kódování souboru, a postupuju tak, že načtu první dva bajty souboru - pokud jsou a ty porovnávám. Poznám tak UTF-16 Big Endian, UTF-16 Little Endian, UTF-8 s BOM. Když nic nespadá do podmínek, může být soubor buď ANSI nebo UTF-8 bez BOM a to potřebuju rozeznat.

Potřebuju nějakým způsobem zjistit, zde to je uložené jako UTF-8 bez BOMu nebo jako ANSI. Stačí pokud mě nějak navedete (úvaha o postupu apod.). Chci to provést vlastním kódem, ne nějakou funkcí - stejně jsem na to žádnou nenašel.

Díky moc za jakoukoli pomoc.
Alphard
Profil
co tohle?
http://latrine.dgx.cz/autoczech-aneb-automaticka-detekce-kodovani
joe
Profil
Alphard
Pěkné, díky. Zapomněl jsem, že to nechci udělat v PHP, ale v historickém VB :-)
Alphard
Profil
To mě napadlo, když jste to nevložil do PHP sekce.
Celý script je založený na regulárech, takže by snad neměl být problém přepsat to do jiného jazyka. (VB neznám)
_es
Profil
joe
Nie je možné to spoľahlivo rozlíšiť.
Na rozlíšenie slúži extra informácia o kódovaní mimo vlastného textu.
Ani rozlišovanie pomocou BOM nie je celkom isté.
Prečo by nemohli byť napríklad v nejakom 8 bitovom kódovaní prvé dva znaky 239 a 187 z danej tabuľky znakov - no podľa teba by to malo byť jednoznačne UTF-8.
Ak miesto ANSI myslíš ASCII, tak to pri zakódovaní do UTF-8 sú použité len znaky 0 až 127, a výsledok je rovnaký ako keby sa použilo kódovanie ASCII.
UTF-8 sa dá vylúčiť, ak sa v texte nachádzajú bajty 0xFF alebo 0xFE, alebo postupnosť bajtov odporujúca definícii kódovania UTF-8.
joe
Profil
Alphard
Už mi to taky došlo, že to bylo myšleno nejen pro PHP.
Zahledal jsem a ve VB (Visual Basic) se dají i RE použít, ale... V článku se píše

ověříme, zda text odpovídá normě UTF-8 a obsahuje nějaký „korektní“ znak. Pokud ano, jde o UTF-8

Nevím přesně jaké znaky se hledají tady
preg_match('#[\x80-\x{1FF}\x{2000}-\x{3FFF}]#u', $s)
Aby mi vše fungovalo tak jak chci, tak v textu musí být nějaký znak jen z UTF-8, jinak to není rozeznatelné. To ale může trvat dost dlouhou dobu, než bych to našel v obsáhlém dokumentu.

Vyzkoušel jsem jak funguje ta funkce z těch stránek a ta se mi zdá nepříliš funkční. Pokud uložím text jako UTF-8, který bude obsahovat třeba jen



pak dostanu výsledek, že kódování je ISO-8859-2 a přitom je to jasné UTF-8 s BOM, jenže v tomhle případě to je asi jedno.
joe
Profil
_es
Mohly by tam být, ale kdo by je tam dával, pro moje potřeby to je jednoznačně určující. Ale jasně, mohlo by jít i o soubor v jiném kódování. Asi budu rozeznávat jen podle těch sekvencí bajtů a všechno ostatní dám jako ANSI. Ukládat pak defaultně budu jako utf8 bez BOM. Jiné řešení mě nenapadá...

Díky za reakce.
_es
Profil
joe
Môžem len zopakovať to, čo predtým, inými slovami:
Informáciu o kódovaní textu nezistíš so 100% istotou len zo samotného textu.
Ak chceš text ukladať, musíš dať k nemu informáciu, v akom je kódovaní.
Ak chceš text čítať, musíš mať k nemu informáciu v akom je kódovaní.
Ak tú informáciu nemáš, tak to môžeš len hádať, alebo odhadnúť s istou pravdepodobnosťou.
Ani to vylúčenie UTF-8, čo som spomínal, nemusí byť celkom isté,
ak sa niekto spoľahne na to, ako norma požaduje spracovanie nepovolených postupností bajtov.
joe
Profil
_es
Jasné, díky. Neříkám, že nemáš pravdu. Ale k tomu, k čemu to potřebuju si myslím, že mi taková pravděpodobnost bude stačit.
Chamurappi
Profil
Reaguji na joa:
Jak to dělá Notepad, že UTF-8 rozpoznává? Používá funkci IsTextUnicode z Advapi32.dll. Na tvém místě bych ji použil také a víc se o to nestaral.
_es
Profil
Chamurappi
Len ako uložiť v Notepade súbor s týmto textom:
 Prvé tri znaky tohoto súboru sú v niektorých systémoch použité na identifikáciu kódovania UTF-8
Alebo:
ţ˙ Toto sú posledné 2 znaky znakovej sady Windows-1250.
tak, aby ho potom notepad sám po sebe prečítal?
Nie je aj toto tiež podobné prirovnaniu kľúč od truhly do truhly?
Chamurappi
Profil
Reaguji na _es:
A pointa tvých úvah je jaká? Že je lepší nedělat vůbec žádnou autodetekci, protože hrozí, že se v jednom z miliardy případů provede špatně? Pokud vím, tak joe programuje editor webových stránek a ne naváděcí systém nukleární střely.
_es
Profil
Chamurappi
A pointa tvých úvah je jaká? Že je lepší nedělat vůbec žádnou autodetekci, ...?
Áno, najlepšie je to bez autodetekcie, zisťovať kódovanie mimo textu.
Tvoj príspevok o Notepade mohol vyvolať dojem, že používa nejakú veľmi spoľahlivú metódu detekcie.
joe píše že: „buď ANSI nebo UTF-8 bez BOM a to potřebuju rozeznat. “ a tou funkciou to asi nerozozná.
No mohla by sa mu tá funkcia alebo podobná snáď hodiť na vylúčenie nepovoleného kódovania UTF-8.
joe
Profil
Chamurappi
Díky, trošku jsem se na ní podíval. Ale nenašel jsem na ní moc dobré doporučení. Už jsem to vyřešil jinak.
Detekuju kódování pro UTF z BOMu, pokud není v souboru, pak se jedná buď o ANSI nebo UTF-8 bez něj. Vezmu několik set znaků a z toho rozpoznám, jestli se jedná o unicode. Když ne, je to ANSI, když jo, je to UTF-8. Myslim, že tohle by mohlo stačit.
joe
Profil
Chamurappi
Věděl bys jak použít tu API IsTextUnicode? Zdá se mi, že vrací pořád nesmysly.
Chamurappi
Profil
Reaguji na joe:
Nevěděl. Ukaž svůj kód.

Zkusil bych to napsat asi takhle:
Private Const IS_TEXT_UNICODE_STATISTICS = &H2
Private Declare Function IsTextUnicode Lib "advapi32" (ByVal lpv As Long, ByVal iSize As Long, lpiResult As Long) As Long

Private Function JeUnicode(vstup As String) As Boolean
  JeUnicode = CBool(IsTextUnicode(StrPtr(vstup), Len(vstup), IS_TEXT_UNICODE_STATISTICS))
End Function
Ale nejsem si vůbec jistý, už pár let jsem ve VB6 nic normálního nepsal.
joe
Profil
Chamurappi
Víceméně to mám stejně. Po dlouhém hledání jsem narazil na příklad.

Jen si nejsem jistý, co dosadit v tvém případě za vstup do té funkce. Problém je v tom, že po přiřazení do string proměnné si VB konvertuje. Obejít se to dá použitím bajtového pole, ale ani pak mi to nechce fungovat.

Zkoušel jsem i použít StrPtr jak máš v kódu, ale to taky "nefunguje".

Option Explicit

Private Const IS_TEXT_UNICODE_STATISTICS = &H2
Private Const IS_TEXT_UNICODE_SIGNATURE = &H8
Private Const IS_TEXT_UNICODE_UNICODE_MASK = &HF

'Private Declare Function IsTextUnicode Lib "advapi32" (ByVal lpv As Long, ByVal iSize As Long, lpiResult As Long) As Long

Private Declare Function IsTextUnicode Lib "advapi32" (ByVal lpBuffer As String, ByVal cb As Long, lpi As Long) As Long

Private Declare Function IsTextPointerUnicode Lib "advapi32" Alias "IsTextUnicode" (ByVal lpBuffer As Long, ByVal cb As Long, lpi As Long) As Long

Private Function IsUnicode(ByRef strText As String) As Boolean
    IsUnicode = CBool(IsTextUnicode(strText, Len(strText), IS_TEXT_UNICODE_STATISTICS))
End Function

Private Sub Form_Load()
    
    Dim strFileName As String
    
    strFileName = "C:\utf8-UTF8.txt"
    
    Dim buffer() As Byte
    Dim strText As String
    
    Open strFileName For Binary As #1
        ReDim buffer(LOF(1) - 1)
        Get #1, , buffer
    Close #1
    
    strText = buffer
    
    Debug.Print IsUnicode(strText)
    
End Sub
joe
Profil
Chamurappi
Ona hlavně ta API nedělá vůbec to co chci...

Vaše odpověď

Mohlo by se hodit

Příspěvky nesouvisející s webem budou odstraněny.

Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: