Christian Kruse: Alle komischen Zeichen finden

Beitrag lesen

你好 Raucherkrebs,

wie kann man in einer Datenbank alle Zeichen finden, die nicht im
UTF-8 Format kodiert sind. Auf der Webseite erscheinen sie als
schwarzer Kasten mit einem Fragezeichen drin. Ebenso in phpmyadmin.
Ich muss die noch per Hand in UTF-8 umwandeln. Aber wie finden?
Die DB hat ein paar tausend Zeilen und etliche Tabellen.

Da wird dir nichts anderes uebrig bleiben als alle DB-Eintraege
auszulesen, zu validieren und ggf. zu melden. Als Validierungsfunktion
kannst du vielleicht das hier von C nach PHP portieren (keine Angst,
sieht komplizierter aus als es ist):

int utf8_to_unicode(const u_char *s,size_t n,u_int32_t *num) {
  u_char c = s[0];

if(c < 0x80) {
    *num = c;
    return 1;
  }
  else if(c < 0xc2) return EILSEQ;
  else if(c < 0xe0) {
    if(n < 2) return EILSEQ;

if(!((s[1] ^ 0x80) < 0x40)) return EILSEQ;
    *num = ((u_int32_t)(c & 0x1f) << 6) | (u_int32_t)(s[1] ^ 0x80);
    return 2;
  }
  else if(c < 0xf0) {
    if(n < 3) return EILSEQ;
    if(!((s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40 && (c >= 0xe1 || s[1] >= 0xa0))) return EILSEQ;

*num = ((u_int32_t)(c & 0x0f) << 12) | ((u_int32_t)(s[1] ^ 0x80) << 6) | (u_int32_t)(s[2] ^ 0x80);
    return 3;
  }
  else if(c < 0xf8) {
    if(n < 4) return EILSEQ;
    if(!((s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40 && (s[3] ^ 0x80) < 0x40 && (c >= 0xf1 || s[1] >= 0x90))) return EILSEQ;

*num = ((u_int32_t)(c & 0x07) << 18) | ((u_int32_t)(s[1] ^ 0x80) << 12) | ((u_int32_t)(s[2] ^ 0x80) << 6) | (u_int32_t)(s[3] ^ 0x80);
    return 4;
  }
  else if(c < 0xfc) {
    if(n < 5) return EILSEQ;
    if(!((s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40 && (s[3] ^ 0x80) < 0x40 && (s[4] ^ 0x80) < 0x40 && (c >= 0xf9 || s[1] >= 0x88))) return EILSEQ;

*num = ((u_int32_t)(c & 0x03) << 24) | ((u_int32_t)(s[1] ^ 0x80) << 18) | ((u_int32_t)(s[2] ^ 0x80) << 12) | ((u_int32_t)(s[3] ^ 0x80) << 6) | (u_int32_t)(s[4] ^ 0x80);
    return 5;
  }
  else if(c < 0xfe) {
    if(n < 6) return EILSEQ;
    if(!((s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40 && (s[3] ^ 0x80) < 0x40 && (s[4] ^ 0x80) < 0x40 && (s[5] ^ 0x80) < 0x40 && (c >= 0xfd || s[1] >= 0x84))) return EILSEQ;

*num = ((u_int32_t)(c & 0x01) << 30) | ((u_int32_t)(s[1] ^ 0x80) << 24) | ((u_int32_t)(s[2] ^ 0x80) << 18) | ((u_int32_t)(s[3] ^ 0x80) << 12) | ((u_int32_t)(s[4] ^ 0x80) << 6) | (u_int32_t)(s[5] ^ 0x80);
    return 6;
  }
  else return EILSEQ;
}

int is_valid_utf8_string(const u_char *str,size_t len) {
  register u_char *ptr = (u_char *)str;
  int x;
  int ret;

for(;*ptr && len > 0;) {
    if((ret = utf8_to_unicode(ptr,len,&x)) == EILSEQ) {
      return -1;
    }

ptr += ret;
    len -= ret;
  }

return 0;
}

再见,
 CK

--
Fortune: "The Computer made me do it."
http://wwwtech.de/