Подсчет байтов в текстовой области с использованием JavaScript - PullRequest
19 голосов
/ 17 мая 2010

Мне нужно посчитать, сколько в байтах текстовой области, когда UTF8 кодируется с использованием JavaScript Есть идеи, как мне это сделать?

спасибо!

Ответы [ 10 ]

18 голосов
/ 17 мая 2010
encodeURIComponent(text).replace(/%[A-F\d]{2}/g, 'U').length
17 голосов
/ 31 августа 2012

Объединяя различные ответы, следующий метод должен быть быстрым и точным и избегать проблем с недопустимыми суррогатными парами, которые могут вызвать ошибки в encodeURIComponent ():

function getUTF8Length(s) {
  var len = 0;
  for (var i = 0; i < s.length; i++) {
    var code = s.charCodeAt(i);
    if (code <= 0x7f) {
      len += 1;
    } else if (code <= 0x7ff) {
      len += 2;
    } else if (code >= 0xd800 && code <= 0xdfff) {
      // Surrogate pair: These take 4 bytes in UTF-8 and 2 chars in UCS-2
      // (Assume next char is the other [valid] half and just skip it)
      len += 4; i++;
    } else if (code < 0xffff) {
      len += 3;
    } else {
      len += 4;
    }
  }
  return len;
}
14 голосов
/ 14 ноября 2011

Если в вашей строке есть не-bmp символы, это немного сложнее ...

Поскольку javascript кодирует UTF-16, а «символ» представляет собой 2-байтовый стек (16 бит), все многобайтовые символы (3 и более байтов) не будут работать:

    <script type="text/javascript">
        var nonBmpString = "foo€";
        console.log( nonBmpString.length );
        // will output 5
    </script>

Символ "€" имеет длину 3 байта (24 бита). Javascript интерпретирует его как 2 символа, потому что в JS символ представляет собой 16-битный блок.

Таким образом, чтобы правильно получить байтовый размер смешанной строки, мы должны кодировать нашу собственную функцию fixedCharCodeAt ();

    function fixedCharCodeAt(str, idx) {
        idx = idx || 0;
        var code = str.charCodeAt(idx);
        var hi, low;
        if (0xD800 <= code && code <= 0xDBFF) { // High surrogate (could change last hex to 0xDB7F to treat high private surrogates as single characters)
            hi = code;
            low = str.charCodeAt(idx + 1);
            if (isNaN(low)) {
                throw 'Kein gültiges Schriftzeichen oder Speicherfehler!';
            }
            return ((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000;
        }
        if (0xDC00 <= code && code <= 0xDFFF) { // Low surrogate
            // We return false to allow loops to skip this iteration since should have already handled high surrogate above in the previous iteration
            return false;
            /*hi = str.charCodeAt(idx-1);
            low = code;
            return ((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000;*/
        }
        return code;
    }

Теперь мы можем считать байты ...

    function countUtf8(str) {
        var result = 0;
        for (var n = 0; n < str.length; n++) {
            var charCode = fixedCharCodeAt(str, n);
            if (typeof charCode === "number") {
                if (charCode < 128) {
                    result = result + 1;
                } else if (charCode < 2048) {
                    result = result + 2;
                } else if (charCode < 65536) {
                    result = result + 3;
                } else if (charCode < 2097152) {
                    result = result + 4;
                } else if (charCode < 67108864) {
                    result = result + 5;
                } else {
                    result = result + 6;
                }
            }
        }
        return result;
    }

Кстати ... Вы не должны использовать метод encodeURI, потому что это встроенная функция браузера;)

Больше вещей:


Приветствия

frankneff.ch / @frank_neff
14 голосов
/ 16 февраля 2011

edit: как указывал didier-l, эта функция неправильно считает суррогатные символы.

ответ брофы должен правильно подсчитывать суррогатов, см. https://stackoverflow.com/a/12206089/274483.

Я протестировал здесь две предложенные версии, а также простую реализацию:

 getUTF8Length: function(string) {
    var utf8length = 0;
    for (var n = 0; n < string.length; n++) {
        var c = string.charCodeAt(n);
        if (c < 128) {
            utf8length++;
        }
        else if((c > 127) && (c < 2048)) {
            utf8length = utf8length+2;
        }
        else {
            utf8length = utf8length+3;
        }
    }
    return utf8length;
 }

В результате моя версия немного быстрее в Firefox и значительно быстрее в Chrome (~ 30x), чем опубликованные здесь версии.

2 голосов
/ 29 октября 2012

Добавить функцию подсчета длины байта в строку

String.prototype.Blength = function() {
    var arr = this.match(/[^\x00-\xff]/ig);
    return  arr == null ? this.length : this.length + arr.length;
}

тогда вы можете использовать .Blength () , чтобы получить размер

1 голос
/ 29 апреля 2013

Как насчет простого:

unescape(encodeURIComponent(utf8text)).length

Хитрость в том, что encodeURIComponent работает с символами, а unescape работает с байтами.

0 голосов
/ 09 октября 2016

набор meta UTF-8 просто и все нормально!

<meta charset="UTF-8">
<meta http-equiv="content-type" content="text/html;charset=utf-8">

и js:

if($mytext.length > 10){
 // its okkk :)
}
0 голосов
/ 19 января 2014

Попробуйте следующее:

function b(c) {
     var n=0;
     for (i=0;i<c.length;i++) {
           p = c.charCodeAt(i);
           if (p<128) {
                 n++;
           } else if (p<2048) {
                 n+=2;
           } else {
                 n+=3;
           }
      }return n;
}
0 голосов
/ 02 сентября 2012
encodeURI(text).split(/%..|./).length - 1
0 голосов
/ 04 октября 2010

Я спрашивал себя об одном и том же. Это лучший ответ, на который я наткнулся:

http://www.inter -locale.com / демки / countBytes.html

Вот фрагмент кода:

<script type="text/javascript">
 function checkLength() {
    var countMe = document.getElementById("someText").value
    var escapedStr = encodeURI(countMe)
    if (escapedStr.indexOf("%") != -1) {
        var count = escapedStr.split("%").length - 1
        if (count == 0) count++  //perverse case; can't happen with real UTF-8
        var tmp = escapedStr.length - (count * 3)
        count = count + tmp
    } else {
        count = escapedStr.length
    }
    alert(escapedStr + ": size is " + count)
 }

но ссылка содержит живой пример того, с чем можно поиграть. «encodeURI (STRING)» является здесь строительным блоком, но также посмотрите на encodeURIComponent (STRING) (как уже указано в предыдущем ответе), чтобы увидеть, какой из них соответствует вашим потребностям.

Привет

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...