Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (GNU/Linux, *NIX, *BSD und Co) » UTF-8 ausgeben?

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 <
000
06.05.2011, 22:29 Uhr
~Ellaau
Gast


Hi,

ich bin realtiv neu in C++ und hab hier nun Text aus .html Dateien die ich einlesen, den HTML-Kramm entferne und das ganze ausgeben will.

Am liebsten in UTF-8. Nun fehlt mir leider etwas die Orientierung in den Standard(?)-Bibliothek ob/wie so etwas geht. Daher die Frage, wie krieg ich meine Daten im UTF-8 Format weggeschrieben.

Derzeit nehm ich einfach eine std::ofstream, die gibt mir leider kein UTF-8 aus. Kann mir wer nen Tip/Link/info geben, wie ich UTF-8 Dateien erstellen kann?

Falles einen Unterschied macht, ich verwende OS-X.

Gruß und Danke für Info
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
06.05.2011, 23:58 Uhr
0xdeadbeef
Gott
(Operator)


Strings in C++ sind einfache Byte-Strings. Wenn dieser UTF-8-kodierten Text enthält, wird der ganz normal behandelt. Beispiel:

C++:
#include <iostream>

int main() {
  std::cout <<
    "Wenn F\xc3\xa4hrmann Hermann F\xc3\xa4hre f\xc3\xa4hrt,"
    "f\xc3\xa4hrt F\xc3\xa4hrmann Herrmann F\xc3\xa4hre.\n";
}


Jetzt ist diese Art der Umschrift natürlich ziemlich umständlich. Wenn es dir nur um die Ausgabe von String-Konstanten geht, ist die einfachste Methode, den Text ganz gehabt hinzuschreiben und den Code in UTF-8 zu speichern - dann wir der Compiler die in UTF-8 kodierten String-Konstanten 1:1 übernehmen.

Wenn ich das richtig lese, kriegst du aber Eingabedaten aus dem Netz und musst diese konvertieren. Glücklicherweise gibt es dazu in POSIX eine Schnittstelle: iconv.

Das funktioniert wie folgt (zunächst nacktes C):

C++:
#include <iconv.h>

#include <stdio.h>
#include <string.h>

int main(void) {
  char in[] = "Wenn Fährmann Hermann...", out[100];
  char *pin, *pout;
  size_t in_n, out_n;
  iconv_t convert;

  size_t test;

  pin = in;
  pout = out;

  out_n = 100;
  in_n = strlen(in) + 1;

  convert = iconv_open("UTF-8", "ISO-8859-15");

  test = iconv(convert,
           &pin , & in_n,
           &pout, &out_n);

  iconv_close(convert);

  puts(out);

  printf("%d\n", test);

  return 0;
}


Ich hab das hier noch schön in C++ verpackt rumliegen:

C++:
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include <iconv.h>

#include <cerrno>
#include <cstddef>
#include <iostream>
#include <string>
#include <stdexcept>
#include <vector>

struct iconv_error : public std::logic_error {
  iconv_error(std::string const &message)
    : std::logic_error(message) { }
};

struct iconv_open_error : public iconv_error {
  iconv_open_error(std::string const &tocode, std::string const &fromcode)
    : iconv_error("iconv_open fehlgeschlagen: Umwandlung von " + fromcode + " nach " + tocode + "nicht möglich") { }
};

class iconverter {
public:
  iconverter(std::string const &tocode, std::string const &fromcode)
    : converter_(iconv_open(tocode.c_str(), fromcode.c_str())) {
    if(converter_ == iconv_t(-1)) {
      throw iconv_open_error(tocode, fromcode);
    }
  }

  std::string operator()(std::string const &text) {
    std::size_t n_in = text.size() + 1, n_out = text.size() + text.size() / 5 + 1; // Grobe Abschätzung
    std::vector<char> outbuffer(n_out);
    std::vector<char> inbuffer;
    char *p_in, *p_out;
    size_t n_converted;

    inbuffer.reserve(n_in);
    inbuffer.assign(text.begin(), text.end());
    inbuffer.push_back('\0');

    p_in  = & inbuffer[0];
    p_out = &outbuffer[0];

    for(;;) {
      errno = 0;
      n_converted = iconv(converter_,
                          &p_in , &n_in,
                          &p_out, &n_out);

      if(n_converted != size_t(-1)) {
        break;
      } else if(errno == E2BIG) {
        size_t n_out_old = p_out - &outbuffer[0];
        n_out += outbuffer.size();
        outbuffer.resize(outbuffer.size() * 2);
        p_out = &outbuffer[n_out_old];
      } else if(errno == EILSEQ) {
        throw iconv_error("Ungültige Multibyte-Sequenz in Eingabe");
      } else if(errno == EINVAL) {
        throw iconv_error("Unvollständige Multibyte-Sequenz in Eingabe");
      } else {
        throw iconv_error("Unbekannter Umwandlungsfehler");
      }
    }

    return std::string(outbuffer.begin(), outbuffer.begin() + outbuffer.size() - n_out - 1);
  }

  ~iconverter() {
    iconv_close(converter_);
  }
private:
  iconv_t converter_;
};

int main() {
  iconverter utf8_convert("UTF-8", "ISO-8859-15");
  std::cout << '"' << utf8_convert("ÄÖÜäöü߀") << '"' << std::endl;
}


Natürlich musst du den fromcode für deine Eingabedaten passend setzen. Die Implementation ist nicht besonders performant, aber wenn das ein Problem ist, darfst du das selbst richten.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra

Dieser Post wurde am 07.05.2011 um 00:02 Uhr von 0xdeadbeef editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
07.05.2011, 15:45 Uhr
Pablo
Supertux
(Operator)


wieso denn so kompliziert? Wenn das Terminal kein UTF-8 unterstützt, dann kann man so viel iconv nutzen, wie man will, es wird nie gehen. Am einfachsten: Datei in UTF-8 speichern:


C++:
#include <iostream>

int main(void)
{
    std::cout << "ÄÖÜäöü߀日本語が好きだ" << std::endl;
    return 0;
}




Code:
$ $ g++ a.cpp -oa
$ ./a
ÄÖÜäöü߀日本語が好きだ


--
A! Elbereth Gilthoniel!
silivren penna míriel
o menel aglar elenath,
Gilthoniel, A! Elbereth!

Dieser Post wurde am 11.05.2011 um 01:55 Uhr von Pablo editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
07.05.2011, 16:07 Uhr
0xdeadbeef
Gott
(Operator)


Wenn ich richtig verstehe, worum es bei der ganzen Sache geht, dann holt er sich HTML-Dateien einer bestimmten Kodierung aus dem Netz und muss diese in Teilen nach UTF-8 umwandeln. Wenn die Eingabedaten erst zur Laufzeit kommen, kann man sie nicht zur Compilezeit einkompilieren.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
11.05.2011, 01:56 Uhr
Pablo
Supertux
(Operator)


ich muss gestehen, ich hab den Text vom OP nicht wirklich durchgelesen
--
A! Elbereth Gilthoniel!
silivren penna míriel
o menel aglar elenath,
Gilthoniel, A! Elbereth!
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
04.06.2011, 20:54 Uhr
~GibsZu
Gast


Du wolltest nur sagen das du Japanisch sprichst ;-), gibts zu.....
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
04.06.2011, 23:00 Uhr
Pablo
Supertux
(Operator)


ne, es gibt schon hier Leute, die das wissen.
--
A! Elbereth Gilthoniel!
silivren penna míriel
o menel aglar elenath,
Gilthoniel, A! Elbereth!
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
05.06.2011, 22:31 Uhr
mugg



Meine Empfehlung ist die HTML-Datei beim Einlesen erstmal von der entsprechenden Kodierung in UTF-16 (interne OS-X Standardkodierung) zu wandeln und in einem wchar_t oder wstring zu speichern. Dann kommt die Bearbeitung (HTML-Kramm entfernen) und anschließend zur Ausgabe (Konsole oder Datei) in die gewünschte Kodierung umwandeln. Bei der Konsole ist das die eingestelle "Locale", z.B. UTF-8.

Für die Umwandlung der Kodierung braucht man irgend eine Bibliothek. Welche für OS-X die optimalste ist, weiß ich nicht. iconv, boost, ... ?
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 <     [ C / C++ (GNU/Linux, *NIX, *BSD und Co) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: