C++ többnyelvű és karakterkódolású fájl feldolgozása gyorsan

C++ többnyelvű és karakterkódolású fájl feldolgozása gyorsan
2022-02-01T07:40:23+01:00
2022-02-02T17:41:26+01:00
2022-10-15T21:21:37+02:00
Zserigta
Sziasztok,

Szeretnék írni egy MBOX (komplett levelezés mentés) fájl feldolgozó programot.
A problémám, hogy mivel emailekről van szó, különböző nyelvek találhatóak benne, ami lehet kínai, orosz, angol....
A fájlban ugye ez nem okoz gondot, mivel a legtöbb tartalom Base64 vagy QuotedPrintable kódolással van mentve és ezek mellett szerepel az adott karakterkódolás is (UTF-8, iso-8859-2....)

A Microsoft (és köztük sok egyéb oldal) is azt ajánlja, hogy többnyelvű programnál a wide chars-t, tehát a wchar_t-t vagy wstring-et használjuk.

A problémám, hogy ha char helyett wchar_t-t használok, az rendkívül lelassítja az egész programot.

LPCSTR File = "d:\test.mbox"; void Test1() { //1.3 sec std::ifstream infile(File, std::ifstream::in); std::string line; while (std::getline(infile, line)) {} } void Test2() { //10.5 sec std::wifstream infile(File, std::wifstream::in); std::wstring line; while (std::getline(infile, line)) {} } void Test3() { //0.9 sec char line[1024]; FILE *fp = fopen(File, "r"); while (fgets(line, 1024, fp)) {} } void Test4() { //7.3 sec wchar_t line[1024]; FILE *fp = fopen(File, "r"); while (fgetws(line, 1024, fp)) {} }
Mint látható a példakódomban, ez kb 10x-es lassulást eredményez.
Az MBOX fájl 168 MB-os és 2.5 millió sort tartalmaz.

Így a kérdésem, hogy van e rá lehetőség, hogy sokkal gyorsabban beolvassam a sorokat wchar_t típusú változóba?

A fájl SSD-n van és a másolása a másodperc töredék ideje alatt megtörténik, tehát nem a fájl elérés a szűk keresztmetszet, de még csak a CPU sem terhelődik különösen (10% fölé nem megy, és mindegyik magot egyformán használja ránézésre) a fenti folyamatok során.

VS2015 C++ Win32, külső könyvtár nem jöhet szóba.
Mutasd a teljes hozzászólást!

  • 10% fölé nem megy, és mindegyik magot egyformán használja ránézésre

    1. A ütemező egyszer az egyik magon futtatja a programodat, egyszer egy másikon, stb. Ebben nincs semmi rendkívüli. Ha jobb kihasználtságot szeretnél elérni, több szálú verzióra kellene a alakítanod a programodat.

    2. A mérésekhez Debug vagy Release konfigurációban indítottad a programodat?
    Mutasd a teljes hozzászólást!
  • 1. Igazából nem ez a kérdésem lényege, ezt csak mellékesen írtam. Tudom, hogy több szálon gyorsíthatnék rajta, de az esetben is megmaradna, hogy a wchar_t kb 10x lassabb mint a char, csak épp nem értem miért, amikor elvileg csak 2x annyi byteot használ fel, nem 10x annyit.

    2. Release, mivel Debug alatt sokkal tovább tart a folyamat, valószínűleg az optimalizációk miatt, bár ha az optimalizációt debugnál bekapcsolom, akkor is sokkal lassabb mint a release, de ez megint más kérdés.
    Mutasd a teljes hozzászólást!
  • Pontosan most milyen is a karakterkódolása az input fájlodnak?
    Mert ugye nem lehet egyeszerre wide és narrow..

    C++-ban a karakterkódolásokkal sokat lehet szívni, szerencsére legalább nem console-ból/ba dolgozol, ami kicsit talán segít a helyzeten.
    lokáloknak is hatása van arra, hogy hogyan konvertálódnak a karakterek beolvasás és kiiratás során.
    std::locale
    Mutasd a teljes hozzászólást!
  • Igen, tudom, hogy egyszerre csak az egyik lehet, ezért is írtam, "fájlban ugye ez nem okoz gondot" részt.
    A fájl UTF-8. (Narrow ha jól gondolom, mert az UTF-16 lenne a wide, ha nem tévedek.).
    Viszont mind a 4 teszt folyamat ha kiíratom a sorokat, teljesen ugyan azt írja ki, karakterprobléma nélkül. De ugye alapból nincs sem ékezet sem extra betű a tartalomban, köszönhetően a quted printable és a base64 kódolásoknak.

    Kíváncsiságképp kipróbáltam, hogy Notepad++-al átkonvertáltam UTF-16-ra a fájlt, ami így értelemszerűen 2x akkora lett, viszont így is a wide char arányában ugyan olyan lassú.
    Sorrendbe a teszt függvényeim:
    1.3 -> 2.5
    10.5 -> 21.0
    0.9 -> 1.7
    7.3 -> 14.1

    Viszont mivel rengeteg adat quoted-printable kódolással van és azon belül különböző karakterkódolással, így sok esetben szükséges a wide char.
    Legalább is a legtöbb "tárgy" és "body" részt nem igen tudtam sima char-ba átkonvertálni csak wide char-ba, így meg gondoltam, hogy úgy is sokszor kell wchar_t-t használni, akkor már eleve úgy olvasnám be a fájlt és akkor nem kell utána még oda-vissza konvertálgatni.
    Mert amit char-ba tudtam konvertálni azt utána wchar-tbe is áttudtam rakni, de fordítva viszont nem, így gondoltam már az elejétől lehetne a közös nevező a wchar_t, csak sajnos rettentő lassú már a legelején a sorok beolvasásánál.

    Habár találkoztam már a local paranccsal, de még nem használtam eddig, mert szerintem az csak tovább bonyolítana a helyzeten.
    Mindenesetre a fájl soronként beolvasásán nem változat egyik sem ezek közül:

    std::setlocale(LC_ALL, "en_US.UTF-8"); std::setlocale(LC_ALL, "hu_HU.ISO-8859-2");
    Mutasd a teljes hozzászólást!
  • Próbáld meg az egész fájlt beolvasni egybe a memóriába és úgy dolgozni vele.
    (Ha fixen tudod a kódolást és biztos vagy benne, akkor akár binary-ként is csinálhatod, persze akkor elmaradnak a formatted által esetleges konverziók, pl '\n' -> '\r\n' windows-on)
    Mutasd a teljes hozzászólást!
  • Sajnos nem tudom fixen előre a fájl kódolását, nem tudom, hogy minden MBOX fájl UTF-8 e.
    Ráadásul a sortörések nagyon fontosak, hogy megmaradjanak, mert csak az alapján lehet megfelelően szétszedni a különböző tartalmakat.
    Ilyet próbáltam, de nem lett gyorsabb.

    void Test5() { //1.6 sec std::ifstream file(File); std::string content((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>()); } void Test6() { //11.3 sec std::wifstream file(File); std::wstring content((std::istreambuf_iterator<wchar_t>(file)), std::istreambuf_iterator<wchar_t>()); }
    Mutasd a teljes hozzászólást!
  • Szerintem a fájlod vagy ASCII vagy bináris, tehát nem jelent nagy előnyt ez a konverzió. A fájlból kivett részeket majd konvertálhatod X-ből Y-ba, de csak a base64_decode után.
    Mutasd a teljes hozzászólást!
  • Itt az olvasható, hogy az fgetws különbséget tesz szöveges és bináris stream-ek között, vagyis szöveges esetben esetleg jóval bonyolultabb konverziót is csinálhat. Ez magyarázhatja a különbséget, illetve kimérheted bináris stream-ekkel is az időt.

    mbox esetén egyébként ez a megközelítés nem fog neked működni, ott akár az egyes fejléc sorok külön kódolással rendelkezhetnek. Szerintem akár egy soron belül is lehet többféle kódolás. Az mbox fejléceket bájt-soronként kell olvasnod, és utána magát a sort tudod átkonvertálni unicode-dá a feldolgozáshoz. A levél részeket pedig megint egyesével kell konvertálnod, ott az egyes részeknél lehet más-más a kódolás.

    Elég szöszölős feladat az email formátum olvasása épp a mindenféle kódolások, részek, alternative-ok miatt, erősen javasolt inkább valami lib-et keresni hozzá, amibe már beletettek pár hónapnyi ellenőrzést és hibakeresést.
    Mutasd a teljes hozzászólást!
  • Nem teljesen értelek.
    Nem látom értelmét binárisan beolvasni majd átkonvertálni egyesével.
    Jóformán az mbox tartalmának 95%-a kell és konvertálásra fog kerülni.
    Ha mondjuk csak az email címeket vagy tárgyakat szeretném kiszedni belőle akkor jó lenne ez a módszer, de én az emailek tartalmát is ki akarom szedni és olvasható formátumra átkonvertálni, így mindenképp szövegként kell kezelnem már az elejétől a dolgokat, hogy megfelelően elkülöníthessem a leveleket egymástól és azon belül a fejléc bejegyzéseket.

    Vagy te miként oldanád meg a bináris beolvasást és így a levelek és fejlécek elkülönítését?
    Mutasd a teljes hozzászólást!
  • Nem látom értelmét binárisan beolvasni majd átkonvertálni egyesével.

    Itt a válasz, hogy miért lassabb.. A konvertálás nem ingyen van. Csináltam egy gyors benchmarkot másik fordítóval, mint amit te használsz, 'wchat_t'-s verzió nálam is jóval hosszabb ideig fut.  Az idő jó 60%-ban ez a két függvény kocog msvcrt-ből:

    * ___lc_codepage_func
    * ___mb_cur_max_func
    Párhuzamosítani sem tudod könnyen. Megnézném, hogy az iconv könyvtár esetleg miben tud segíteni. Hátha gyorsabb, vagy van multi-threaded konvertálás..
    Mutasd a teljes hozzászólást!
  • Vágott idézet egy valódi email forrásából (az mbox formátumban gyakorlatilag ugyanígy szerepel):

    ... Date: Fri, 3 Dec 2021 18:54:35 +0000 Subject: =?utf-8?B?QmFyaW9uIGhhdmkgc3rDoW1sYWtpdm9uYXQgKDIwMjEuIG5v?= =?utf-8?B?dmVtYmVyKQ==?= Content-Type: multipart/mixed; boundary=--boundary_257749_cdf33fc8-3a76-41fa-9249-6c02bcbc1474 Message-ID: <0102017d81a5f196-b964e1bc-0cd0-4dca-a71b-9071f62cd90c-000000@eu-west-1.amazonses.com> ... X-Google-Group-Id: 915131881244 ----boundary_257749_cdf33fc8-3a76-41fa-9249-6c02bcbc1474 Content-Type: text/html; charset=utf-8 Content-Transfer-Encoding: base64 PCFET0NUWVBFIGh0bWwgUFVCTElDICItLy9XM0MvL0RURCBYSFRNTCAxLjAgVHJhbnNp ...
    Láthatod, hogy pl. a Subject (tárgy) soron inline base64-elt utf-8 kódolás van, aztán a levél tartalma multipart/mixed, amiben (ide nem másoltam be, de van) utf-8-as base64-elt html, meg base64-elt png. A külön nem jelzett részek sima ASCII kódolásúak. Más levelekben egész más kódolások is lehetnek, a mime többfélét megenged.

    Ahhoz, hogy a teljes szöveges információt ki tudd nyerni a levélből, a fentit neked (vagy egy könyvtárnak) fel kell tudnod dolgozni. Ezt egy sima C++-os stream nem fogja megtenni. 

    Amikor meg olyat írsz, hogy az emailek tartalmát is ki akarod szedni, ahhoz a HTML részeket is tudnod kell értelmezni. Ott megint többféle kódolás is előfordulhat, nem beszélve a html escape szekvenciákról, meg nem jelenő részekről (style, script), meg egyéb izgalmakról.

    Ha ezen felül még mondjuk a csatolt pdf-ekbe, vagy docx-ekbe is bele akarsz olvasni, az egy további nagy kalap bonyolultság.

    Vagy te miként oldanád meg a bináris beolvasást és így a levelek és fejlécek elkülönítését?

    Nem írtad, hogy egyszer akarod végigfuttatni a fájlodon a programot, vagy ez egy állandóan változó (bővülő) mbox, amiben pl. keresni akarsz.

    Első esetben keresnék egy jól működő C++-os mime és egy html feldolgozó könyvtárat, és használnám azokat. Nem lepődnék meg, ha ettől a projektem pár (pár tíz?) MB-tal megnőne.

    Ha gyakori keresést akarnék egy bővülő levélhalmazban, akkor kinyerném a szöveges részeket, és külön eltárolnám valamilyen adatbázisba, vagy struktúrába, amiben utána keresek. És azt bővíteném, mikor új levél érkezik. Az mbox nem igazán alkalmas erre.
    Mutasd a teljes hozzászólást!
  • Tudom, hogy épül fel egy email és annak tartalma. Sőt azt is tudom, hogy akár csak a tárgy mező tartalmában is lehet egyszerre többféle kódolás, mert láttam rá példát.
    Ezekhez a Base64 és a Quoted printable dekódolás függvényeim megvannak. Sőt már egy egész összetett Mail osztályom ami szépen szétszabdal mindent és konvertál a megadott helyre.

    A fő bajom, hogy bizonyos esetekben ha ezen konverterek kimenete char akkor értelmezhetetlenek lesznek az ékezetes betűk, viszont wchar_t adattípussal meg nem volt ilyen bajom, így ezért gondoltam, hogy wchar_t legyen az egységes szöveg tároló változótípusom.
    Mert ha a programban hol char hol wchar_t-t használok az egyrészt zavaró másrészt azt jelenti, hogy oda-vissza kell konvertálgatni ami meg idő.

    Ezért szerettem volna már a fájl betöltésnél a wchar_t-t használni, csak sajnos úgy néz ki, hogy így lehet még lassabb a teljes folyamat.

    Nem célom sem a csatolmányok sem a body HTML részének feldolgozása.
    A csatolmányok úgy mint a legtöbb webes email kliensnél elég ha letölthetőek, nem kell tudnia a betekintést.
    A body-ban a HTML mellett tudtommal mindig ott van a nyers szöveg is.
    De a HTML body feldolgozásához meg használhatom az IE beépülő motorját mint ActiveX webbrowser control és így nem kell a HTML tagek feldolgozásával bajlódnom. (Az Outlook is így működött régen, meg lehet most is.)

    A program egyik célja, hogy megnyissa az mbox fájlt és utána a leveleket úgy lehessen megnézni mint szinte bármely webes vagy asztali programban, úgy hogy utána már a fájlhoz ne nyúljon.
    A másik cél és igazából ez a kiinduló, hogy a több ezer email közül kellene egy célzott feladó, adott tárggyal rendelkező emailekből 2 adott sort kimenteni CSV-be.
    Ezek a főbb célok, ezen kívül minden amit még bele sikerül majd tenni.

    Ez VB-en már megoldottam, IMAP kezeléssel együtt (kivétel az adott tartalom kiexportálása CSV-be részt).
    Viszont kíváncsi vagyok, miként lehetne ezt natív C++-ban is megoldani, szintén külső könyvtárak nélkül.

    Csak mint írtam a fő problémám továbbra is, a wide char-ba való fájlbeolvasás és annak sebessége.
    Ha UTF-16-ba konvertálom a fájlt és megnyitom pl egy notepad++-al az akkor is töredékidő alatt megnyitja karakterhelyesen (tehát feltételezhetőleg wide chart használva), ellenben a C++ függvényeimmel, tehát biztos, hogy meglehetne ezt oldani sokkal gyorsabban, csak nem tudom, hogyan.
    Mutasd a teljes hozzászólást!
  • Miért kikötés, hogy nem használsz külső könyvtárat? C++ standard nem támogatja valami jól ezeket a különböző kódolásokat. Általánosságban a nyelv és az STL jó alapokat ad, amire lehet építkezni, de nem célja a nyelvnek, hogy bonyolult specializált könyvtárakat integráljon magába.

    Helyedben ezzel a könyvtárral próbálkoznék: International Components for Unicode
    Vagy kényelmesebb front-end könyvtárat, ami ezt használja back-end ként.. Boost.Locale

    Külső könyvtárak nélkül is megoldható, de csak szivatod vele magad. (szerintem VB-ben sem magadnak implementáltad le a különböző kódolásokat..)

    A fő bajom, hogy bizonyos esetekben ha ezen konverterek kimenete char akkor értelmezhetetlenek lesznek az ékezetes betűk


    Ezt nem teljesen értem. Az std::string-re is simán tekinthetsz úgy, mint sima char-okból, bájtokból álló tömb, akármi is legyen a belső kódolása.
    Arra kell figyelni, hogy ha dolgozol vele, akkor megfelelően használd.
    Amennyiben karaktereket szeretnél megjeleníteni, akkor jön a következő probléma.. Pl a konzolnak is megvan a saját karakter kódolása, ami ha nem stimmel a te programod kimenetének a kódolásával, akkor kriksz-kraksz lesz az eredmény. Ugyanígy külső UI lib használata esetén figyelni kell rá, hogy helyesen add át az adatokat és még akkor sem biztos, hogy a rendszerben elérhetőek lesznek a vizuális megjelenítéshez szükséges grafikai elemek akkor sem, ha helyesen értelmezi, hogy oda amúgy milyen betűnek kellene kerülnie.

    Konklúzió a részemről:
    C++ iostream nem erre lett kitalálva, nincs megfelelő standard support ehhez, használj dedikált könyvtárat!
    Konzolon történő megjelenítéssel is sokat lehet szívni, egyszerűbb lehet egy modern grafikus könyvtárat ( akár beépített karakter kódolással) használni erre a célra is: Qt6
    Mutasd a teljes hozzászólást!
  • Azért nem akarok külső könyvtárat, mert akkor ennyi erővel használhatnám a VB.NET környezetet is, akkor nem igen látnám már a C++ előnyét.
    Pont azért is kezdtem el Native Win32 C++ al foglalkozni, hogy tényleg minden mentesen csak a Windows saját apijait felhasználva készíthessek programokat. (Sok esetben a végeredmény 1db exe ami XP-től kezdve minden Windowson elfut mindenféle kiegészítő nélkül.)
    Nem pénzért és nem is feltétlen nagyközönségnek készítek így programot, főként csak magamnak, gyakorlás és a nyelvvel való ismerkedés céljából. (Vagy mondhatjuk úgy is, hogy sz_p_ssam magam, ha másnak így jobban tetszik.)
    Ezzel az egyik célom annak vizsgálata, hogy ezt is vagy azt is meg tudom e csinálni C++-ben is.
    A másik, hogy ezáltal még jobban belelássak a Windows és a programok működésébe, ami pl .NET keretrendszernél nem igen jön át mert ott nagyon sok mindent a keretrendszer old meg és nem látod, hogy mit csinál a háttérben. (Persze megnézhető a .NET forrása is és szoktam is ott keresgélni, de az akkor sem ugyan az mintha te magad építed fel a programot és érted meg mi mit és miért csinál.)
    Aztán lehetne jönni az assembly-vel, de az meg már az embertelen kategória szerintem.
    De kár ezen rugózni, el kel fogadni, hogy én Native Win32 C++ al külső könyvtárak nélkül akarok megoldani valamit. A kérdés, hogy ebben van e itt olyan valaki aki tud segíteni, vagy nincs.

    Ilyenkor elgondolkodok, hogy a válaszadók vizsgán is meg akarták győzni a tanárt, hogy ezt így meg úgy oldjuk már meg, de semmiképp sem úgy ahogy a feladat szól?


    Külső library-kat csak akkor használok ha tényleg nem igen van rá más mód, mint pl egy SQLite vagy MySQL adatkapcsolat. Vagy spec hardverrel való kommunikáció amely esetében ha nincs hardverhez megfelelő leírás csak egy dll és csak annak leírása, akkor ugye másképp elég nehéz.

    Nem értem ezt a fórumot, hogy mindig meg akarják változtatni az emberek nézőpontját és többnyire nem az adott feladat megoldásával hanem inkább annak megkerülésével foglalkoznak a válaszadók.

    szerintem VB-ben sem magadnak implementáltad le a különböző kódolásokat.

    De VB-ben saját magam oldottam meg a különböző kódolások kezelését. 0 külső library felhasználásával, persze van benne 1-2 copy-paste kód/kódrészlet, amelynek egy részét saját ízlésemre szabtam, de ez csak igen kis részét teszi ki és nincs benne semmilyen külső dll használat a .net-et leszámítva.

    Konzolos megjelenítést nem használok, nem is szoktam.
    Mutasd a teljes hozzászólást!
  • Nem értem ezt a fórumot, hogy mindig meg akarják változtatni az emberek nézőpontját

    Azt hittem, hogy azért vagy itt, hogy segítséget kérj egy probléma megoldásában. Szerintem kutya kötelességünk jelezni, amennyiben nem a megfelelő eszközökkel próbálod megoldani.
    Persze ha te a nehéz utat választod gyakorlásképpen, ahol újra feltalálod a kereket meg a spanyol viaszt, az is teljesen rendben van.

    nem az adott feladat megoldásával hanem inkább annak megkerülésével foglalkoznak

    Épp hogy a probléma egyszerű és gyors megoldásához adtunk útmutatást, ezt nem kötelező elfogadni.

     nincs benne semmilyen külső dll használat a .net-et leszámítva.

    Akkor tényleg low-level kódot írtál (.NET is az ICU könyvtárat használja a fedél alatt.. .NET globalization and ICU)
    Mutasd a teljes hozzászólást!
  • kutya kötelességünk jelezni, amennyiben nem a megfelelő eszközökkel próbálod megoldani.

    Nem kötelességed jelezni, a szabályzatban sincs ilyen.
    Másrészt már a nyitó hsz-ben is kiemeltem, hogy külső könyvtár nélkül akarom megoldani, ehhez képest több hozzászólásban is ajánlgatva van a külső könyvtár.

    Tisztában vagyok én is, hogy egy POCO vagy Chilkat vagy egyéb más könyvtárakkal lényegébe azonnal meg van oldva a feladat, mert kész funkciók vannak erre, de nyilván ha ez játszana akkor azokat használnám és nem írnék ide, de mivel magam szeretném leprogramozni a dolgot, így ezért írtam, hogy libraryk nélkül szeretném megoldani.

    újra feltalálod a kereket

    Csak épp libraryk esetében itt a kerék mellé egy komplett kocsi is jár, még akkor is ha neked csak a kerékre van szükséged.

    Épp hogy a probléma egyszerű és gyors megoldásához adtunk útmutatást..

    Csak épp a feltételeknek ellentmondót. (Feltétel: külső könyvtár nem jöhet szóba)

    Az, hogy a .NET mit használ a fedél alatt az már tényleg lényegtelen az adott topik és az általam írtak szempontjából is szerintem.
    Mutasd a teljes hozzászólást!
  • úgy is sokszor kell wchar_t-t használni, akkor már eleve úgy olvasnám be a fájlt és akkor nem kell utána még oda-vissza konvertálgatni.

    Szerintem itt nézted el a dolgot. Akkor lenne értelme egyből wchar_t-be olvasni, ha az egész fájlnak ugyanaz lenne a kódolása, és így beolvasás közben "letudnád" a konverziót. Mivel a fájlban különféle kódolások szerepelnek, de mind ASCII-kompatibilissé lett téve további kódolás (quoted-printable illetve base64) által, ez a fájl lényegében egy ASCII fájl, aminek egyes részeit további dekódolással wchar_t sztringgé lehet alakítani. Pont hogy az lenne a célszerű megközelítés, hogy egy "szűk" char sztringbe (pufferbe, akármibe) olvasod be az adatot, aztán azokat a részeket, amire tényleg szükséged van, wchar_t sztringgé alakítod a melléjük rakott metaadatok felhasználásával. Másképp mondva lesz majd valahány dekódoló függvényed amibe char sztring (meg esetleg metaadatok) mennek be, és wchar_t sztring jön ki.

    Mivel azt írod, hogy a leveleknek csak egy részhalmaza fog kelleni, ezzel a megközelítéssel el tudod kerülni azoknak a részeknek a konverzióját, amikről már a fejléc alapján tudod, hogy úgysem érdekelnek.

    szerk: Most nézem hogy NevemTeve már leírta ugyanezt, csak tömörebben. Na nem baj, hátha "kicsomagolva" jobban érthető.
    Mutasd a teljes hozzászólást!
  • Beolvasod char-ként, std::regex-el rákeresel a decode-olandó részekre.
    Azokat BASE64 decode-olod, vagy amit kell. (CryptStringToBinaryA function)
    Elvégzed a karakter kódolást a kicsomagolt bájtokon (MultiByteToWideChar)

    A C++ használatának nem az a sava-borsa, hogy platformfüggő alacsonyszintű kódot írunk benne, persze erre is lehet használni, viszont a mai világban kevés helyen fogod hasznát venni a WIN32API ismeretének.

    (A WINAPI hívások akkor nem számítanaka külső könyvtárnak, ha jól értem, pedig igazából nagyobb függőséget jelent, mint egy platform független implementációval rendelkező népszerű könyvtár)
    Mutasd a teljes hozzászólást!
  • Ha ettől nem megy el valaki kedve a manuális konverziótól, külső könyvtár használata nélkül, emelem a kalapom
    Mutasd a teljes hozzászólást!
  • Ezekhez a Base64 és a Quoted printable dekódolás függvényeim megvannak.

    Kanyarodjunk vissza egy kicsit ide. Az "Encoded-Word" résznél ír arról az esetről, mikor pl. egy fejlécben valami valamilyen kódolással szerepel. Ennek valóban része a base64, vagy quoted printable, de van neki egy charset része is, ami elég sok minden lehet. Az mondja meg, hogy hogy lesznek a bájtokból betűk. Azt írja, hogy bármilyen IANA által nyilvántartott kódolás szóba jöhet, itt fel van sorolva pár száz. Gondolom, azok a függvényeid még nincsenek mind meg.

    A fő bajom, hogy bizonyos esetekben ha ezen konverterek kimenete char akkor értelmezhetetlenek lesznek az ékezetes betűk, viszont wchar_t adattípussal meg nem volt ilyen bajom, így ezért gondoltam, hogy wchar_t legyen az egységes szöveg tároló változótípusom.

    Lásd fenn. A base64 és quoted printable bemenete char, és a kimenete is char (más programnyelveken byte). Ezt a bájtsorozatot tudod karakterekké (mondjuk wchar_t) konvertálni a charset ismeretében. Tehát olvasáskor char-t kell használnod (mivel a fájlban bájtok vannak), a többnyelvű feldolgozáshoz pedig wchar_t-t.

    Mert ha a programban hol char hol wchar_t-t használok az egyrészt zavaró másrészt azt jelenti, hogy oda-vissza kell konvertálgatni ami meg idő.

    Nem hiszem, hogy meg lehetne úszni a legalább egyszeri konvertálást. Vissza nem kell konvertálnod sosem.

    A body-ban a HTML mellett tudtommal mindig ott van a nyers szöveg is.

    A gyakorlatban ma már nem így van.

    De a HTML body feldolgozásához meg használhatom az IE beépülő motorját

    Elképzelhető.

    Ha UTF-16-ba konvertálom a fájlt és megnyitom pl egy notepad++-al az akkor is töredékidő alatt megnyitja karakterhelyesen

    Ha az általam bevágott példát UTF-16-ba konvertálod, attól még a Subject sor ugyanaz marad, hogy =?utf-8?B?QmFyaW9uIGhhdmkgc3rDoW1sYWtpdm9uYXQgKDIwMjEuIG5v?= 

    Ahhoz, hogy te a tárgyra szűrni tudj, ahogy írod, ezt először base64-el dekódolnod kell, és a kapott bájtokat utf-8-ként értelmezned, hogy megkapd azt, hogy "Barion havi számlakivonat". Ez utóbbiban ascii-n kívüli karakter is van, az "á". Az ilyenekhez kell neked a wchar_t.

    Egyébként a sebességről is írtam neked, szerintem a szöveges-bináris stream a magyarázat.

    Ha mindenképpen ragaszkodsz a saját megoldáshoz, dönthetsz úgy, hogy a programod csak bizonyos emailekre fog működni. Lehet, hogy a te esetedben elég az, ha a több százféle kódolás közül csak 3-4 van meg, a CSV feldolgozásodnál valószínűleg nem fog hirtelen előjönni más. Az elterjedtebbekre szerintem windows API hívás is van, ha fixen win32 a platform. A html-ből szöveg kinyerésre is lehet emberi erővel írni olyan programot, ami a számodra érdekes leveleknél jól működik.
    Mutasd a teljes hozzászólást!
Tetszett amit olvastál? Szeretnél a jövőben is értesülni a hasonló érdekességekről?
abcd