Обсуждение:UTF-8

Материал из Википедии — свободной энциклопедии
Перейти к: навигация, поиск

Проект:Информационные технологии     (Уровень 2, Важность «средняя»)

💻

Эта статья тематически связана с Проектом:Информационные технологии, целью которого является создание качественных и информативных статей на темы, связанные с информационными технологиями. Если вы хотите помочь проекту, то можете отредактировать статью, к которой относится это обсуждение, или посетить страницу проекта, где сможете, помимо прочего, присоединиться к проекту и принять участие в его обсуждении.

Написать сообщение на форум проекта

◕
(развитая)
Эта статья по шкале оценок статей Проекта:Информационные технологии имеет 2 уровень.

Средняя

Важность этой статьи для проекта Информационные технологии: средняя

Ошибки в табличке[править вики-текст]

Мне показалось, что в схеме, в общем-то очень хорошо и наглядно составленной, есть ошибка. А именно (цитирую):
"На схеме в скобках первое «приглушённое» значение представлено в шестнадцатиричном значении и представляет из себя инвертированную битовую маску. Такие маски удобно и оптимально применять на платформах вроде x86 с инструкциями «test» и «and» с флагом ZF для проверки вхождения в диапазон".
Т. е. речь идет о битовой маске, позволяющей проверить, что некоторое число не укладывается в диапазон, соответствующий данной инвертированной битовой маске, а следовательно это число не может быть представлено в кодировке UTF-8 цепочкой соответствующего типа и соответствующей длины и нужна более длинная цепочка. В "псевдокоде" можно так записать
wchar_t c;
wchar_t mask_i;
if(c & mask_i) {<Число невозможно представить цепочкой длиной i байт, нужно использовать более длинную цепочку>}
Если я, конечно, правильно понял смысл этой битовой маски.
Но в таком случае для первой и второй битовой маски вроде бы указаны неправильные шестнадцатиричные значения.
Указано
1) FF.FF.FF.F8
2) FF.FF.FF.80
Должно быть соответственно
1) FF.FF.FF.80
2) FF.FF.F8.00
Для остальных битовых масок у меня все сошлось, там вроде ошибок нет. Или я ошибаюсь? Проверьте, если ошибка есть, возможно удастся переделать, слегка подправить табличку.

188.123.241.56 12:09, 18 мая 2013 (UTC)
По моему, Вы правы, автор схемы 21 марта внёс не те исправления в схему - вместо убирания лидирующих F убрал завершающие 0. Поправил.--SEA99 21:25, 18 мая 2013 (UTC)
Спасибо!
188.123.241.56 13:06, 19 мая 2013 (UTC)


Про кирилицу - кирилический символ представляется двумя байтами, а не одним. Если я не заблуждаюсь, исправте. 129.199.122.205 19:56, 16 февраля 2009 (UTC)

Вы абсолютно правы. С уважением, Animist обс. 08:11, 17 февраля 2009 (UTC)

неплохо бы в таблице сравнения юникода и утф-8, написать что вторая записана побайтно в двоичной системе исчисления, а то это не совсем очевидно 77.66.210.145 23:38, 17 февраля 2009 (UTC)

где взаимосвязь Plan-9 и UTF-8[править вики-текст]

Почему эта статья входит в категорию Plan_9? ShCoder 07:42, 19 сентября 2008 (UTC)

Потому что «Формат UTF-8 был изобретён 2 сентября 1992 года Кеном Томпсоном и Робом Пайком и реализован в Plan 9» Chamie 14:37, 29 октября 2008 (UTC)

Не верно: В отличие от UTF-16, UTF-8 является самосинхронизирующейся кодировкой (англ.)[править вики-текст]

UTF-16 так-же является самосинхронизирующейся кодировкой.

79.164.33.234 12:58, 4 марта 2012 (UTC) K.Tishin

Если рассматривать UTF-16 как поток 16-битных блоков, то она самосинхронизирующаяся. Если же её рассматривать как поток байтов, то она несамосинхронизирующаяся, поскольку если у неё отрезать нечётное число байтов в начале, то дальше будут одни крокозябры. — Monedula 15:16, 4 марта 2012 (UTC)

Меня корёжит текстовое описание[править вики-текст]

Я работал с кодировкой UTF-8 не один раз. Писал различные кодировщики и раскодировщики на разных языках программирования. Видел что статья не полная и не один день пытался текстом нормально описать её, но это ебанистика какая-то. Сознательно вырезал его, так как для работы мне достаточно графической штуки, которую я сделал. Может быть есть люди, которые текст лучше воспринимают, но для меня это так же не удобно как объяснять в деталях как нормально построить мост — проще человеку чертёж показать. Поэтому оставил всё в наглядном табличном и графическом виде, так как сама кодировка тупо раскладывает биты по нужным ячейкам. Нужен будет текст — пишите если прёт. Callidus 15:26, 19 декабря 2012 (UTC)

И совершенно напрасно. Хорошое текстовое описание было бы как нельзя кстати. Знаю, что такие вещи ОЧЕНЬ сложно описывать словесно, очень тяжело добиться того, чтобы это был не набор каких-то непонятных трудночитаемых слов, а действительно связный понятный красивый и легкий для прочтения текст. Но если автору удалось хорошо описать такую кодировку словесно - польза для читающего будет огромная. Самое лучшее описание сначала подробное словесное (тут, наверное, нужно написать о том, что для 7-битных символов признаком конца цепочки является 0 в 8-ом разряде, символом продления цепочки является 10 в старших, т. е. 7-ом и 8-ом, битах, а символом завершения цепочки единички в старших битах, число которых равно числу использованных в цепочке байт, после которых стоит 0, т. е. что-то вроде 11...10), потом формализованное, изложенное через побитовые операции (&, AND, TEST), а потом графическая схема, после которой наступает окончательная ясность. Мне лично так кажется. Схема Ваша хорошая, мне понравилась, но вроде есть в ней ошибка (хотя не знаю, я тут не профи). Думаю, что словесное описание этой кодировки и описание с использованием побитовых логических операций должно быть в каких-то популярных учебниках по программированию, в которых эта кодировка рассматривается. 188.123.241.56 11:21, 18 мая 2013 (UTC)

Не пишите под принципом кодирования ничего (пилюля для трезвости)[править вики-текст]

Я сам пытался написать какой-то вменяемый текст, но только месово получалось (толи из-за самосинхронизацаии или из-за поддежки ASCII — исключение же; но в сознании это превращалось в кашу). При этом всегда с лёту могу написать енкодер и декодер. И схему я нарисовал так же (прошу прощения за ошибки — вторую правку делал пьяным в полусознательном состоянии и еле-еле рассчитал все диапазоны попутно добавив две таблицы снизу). Это я к тому что текст не всё может передать. Попробуйте описать текстом точные движения танца. Поверни правую ногу запястьем на угол блин, сферический (12° по X и 37° по Z; я даже сам растеряюсь). Другое дело если тот самый смысл передать через видео.

Думал про UTF-8 как помешанный и в итоге нагенерил с десяток кодировок в Экселе, а потом отобрал лучшие чтобы не зря день прожить. Если ты умеешь программировать, то сумееешь раскидать биты и здесь:

Кароче не пишите больше под принципом действия трактатов на вроде «старший бит нужен для отличия ASCII-символов от остальных». Человеческий глаз 90 % (я приуменьшил) информации воспринимает и там самый быстрый анализатор. Если я вижу что эти биты нужно поместить туда, а эти должны быть выставлены в 1, то это плёвая задача про программиста (если ты на каком-нить Basic программируешь, то же самое арифметически можно сделать — вспомни что в школе делали с двоичной системой счисления в перемешку с десятичной).

Пишите только во введениии и «Интересные факты». Ей богу это как статья на тему как перегнать 100 % в 255 значений байта или как яийца пожарить имея яйца и нож?. Там битовые сдвиги (в обе стороны), And и Or хватит (на x86 с помощью BTR ещё можно изящно выкрутится).

PS: И на статью про HTTP хоть подрочите. Меня одного чтоли в России этот протокол интесует что каждый байт разобрал. Как точно If-Modified-Since передаётся по всем спецификациям? Перед запятой можно пробельный символ лепить или нет. Просто жалко.

Callidus 05:07, 7 июня 2013 (UTC)

Третий вариант[править вики-текст]

Я тут задрочился на процедуру раскодирования и у меня сердце кровью обливалось когда видел как UTF-16 и двухбайтовые UTF-8 декодируются (кириллица в основном). Подогнал раскладку бит в итоге под инструкцию BSWAP. Это её основной смысл.

Пример на C[править вики-текст]

// Нужно было перекодировать текст из 1251 в UTF-8
// Обратно пока нет.

#include <string.h>
#include <errno.h>

#define ONE_BYTE_TABLE_SIZE (8*16) //0x80...0xFF

/* Windows-1251 to UTF-8 confersion table */
static unsigned long cp1251_utf8 [ONE_BYTE_TABLE_SIZE] = {
     /*  .0     .1     .2     .3     .4     .5     .6     .7     .8     .9     .A     .B     .C     .D     .E     .F */
/*8.*/ 0x0402,0x0403,0x201A,0x0453,0x201E,0x2026,0x2020,0x2021,0x20AC,0x2030,0x0409,0x2039,0x040A,0x040C,0x040B,0x040F,
/*9.*/ 0x0452,0x2018,0x2019,0x201C,0x201D,0x2022,0x2013,0x2014,0x0098,0x2122,0x0459,0x203A,0x045A,0x045C,0x045B,0x045F,
/*A.*/ 0x00A0,0x040E,0x045E,0x0408,0x00A4,0x0490,0x00A6,0x00A7,0x0401,0x00A9,0x0404,0x00AB,0x00AC,0x00AD,0x00AE,0x0407,
/*B.*/ 0x00B0,0x00B1,0x0406,0x0456,0x0491,0x00B5,0x00B6,0x00B7,0x0451,0x2116,0x0454,0x00BB,0x0458,0x0405,0x0455,0x0457,
/*C.*/ 0x0410,0x0411,0x0412,0x0413,0x0414,0x0415,0x0416,0x0417,0x0418,0x0419,0x041A,0x041B,0x041C,0x041D,0x041E,0x041F,
/*D.*/ 0x0420,0x0421,0x0422,0x0423,0x0424,0x0425,0x0426,0x0427,0x0428,0x0429,0x042A,0x042B,0x042C,0x042D,0x042E,0x042F,
/*E.*/ 0x0430,0x0431,0x0432,0x0433,0x0434,0x0435,0x0436,0x0437,0x0438,0x0439,0x043A,0x043B,0x043C,0x043D,0x043E,0x043F,
/*F.*/ 0x0440,0x0441,0x0442,0x0443,0x0444,0x0445,0x0446,0x0447,0x0448,0x0449,0x044A,0x044B,0x044C,0x044D,0x044E,0x044F
} ;

typedef struct utf8_struct {
  int nb ; //Количество байтов UTF-8
  char c[6] ; //Байты UTF-8 в обратном порядке
} utf8_t;

//Готовая таблица перекодировки здесь
static utf8_t _tab[256] ;

//Подготовить преобразование для 1 символа
static int _c2u( unsigned long *cp, char c, utf8_t *u ) {
  int i ;
  unsigned long u8 ;
  unsigned long databits = 0x3F ; //6 бит
  unsigned long headbits = 0x80 ;

  //До кода 0x80 символы не перекодируются
  if( (unsigned char)c < 0x80 ) {
    u->nb = 1 ;
    u->c[0] = c ;
    return 0 ;
  }

  u8 = cp[(unsigned char)c - 0x80] ;
  for( i = 0 ; u8 != 0 && i < 6 ; ++i ) {
    if( (u8 & ~databits) == 0 ) {
      //Последний байт
      u->c[i] = (char)(u8 & databits) | headbits ;
      u8 = 0 ;
    } else {
      u->c[i] = (char)(u8 & 0x3F) | 0x80 ;
      u8 >>= 6 ;
      databits >>= 1 ;
      headbits |= (headbits >>1) ;
    }
  }
  u->nb = i ;
  if( u8 == 0 )
    return 0 ;
  else {
    errno = EDOM ;
    return -1 ;
  }
}

//Подготовить таблицу
int c2u_prepare( const char *cp_name ) {

  int i, j ;

  static struct c2u_struct {
    char *name ;
    unsigned long *cp ;
  } c2u[] = {
    { "windows-1251", cp1251_utf8 },
    { "cp1251", cp1251_utf8 },
    //... и так далее
    //Конец
    { NULL, NULL }
  };

  for( i = 0 ; c2u[i].name != NULL ; ++i  ) {
    if( strcmp(c2u[i].name,cp_name) == 0 ) {
      for( j = 0 ; j < 256 ; ++j ) {
        if( _c2u( c2u[i].cp, (char)j, &_tab[j] ) == -1 ) {
          //Ошибка преобразования символа
          return -1 ;
        }
      }
      //Всё в порядке.
      return 0 ;
    }
  }
  //Нет такой таблицы
  errno = EINVAL ;
  return -1 ;
}

//Длина одного символа UTF-8
int c2u_char_len( char c ) {
  return _tab[(unsigned char)c].nb ;
}

//Длина строки UTF-8
int c2u_str_len( const char *src ) {

  int i, n ;

  for( n = 0 ; *src != 0 ; n += i, ++src ) {
    i = c2u_char_len( *src ) ;
  }
  return n+1 ;
}

//Преобразование 1 символа в UTF-8
int c2u_char( char c, char *buf, int len ) {

  utf8_t *u8 = &_tab[(unsigned char)c] ;
  int n = u8->nb ;
  int i, j ;

  if( len >= n ) {
    for( i = 0, j = n-1 ; i < n ; ++i, --j ) {
      buf[i] = u8->c[j] ;
    }
    return n ;
  }
  return 0 ;
}

//Преобразование строки в UTF-8
int c2u_str( const char *src, char *dst, int dstlen ) {

  int n, i, j ;

  for( j = n = 0 ; *src != 0 && dstlen > 1 ; dstlen -= i, n += i, ++j ) {
    i = c2u_char( *src, dst+n, dstlen ) ;
    if( i == 0 )
      break ;
    ++src ;
  }
  if( dstlen > 0 ) {
    dst[n] = 0 ;
  }
  return j ;
}
//Конец. Ругайте.
83.142.167.58 09:36, 18 июня 2013 (UTC)
83.142.167.58 09:33, 18 июня 2013 (UTC)
83.142.167.58 09:26, 18 июня 2013 (UTC)