Количество байтов длины строки

Я ищу некоторые указатели указаний и оптимизации для моей пользовательской функции JavaScript, которая подсчитывает байты в строке, а не только символы. Веб-сайт использует UTF-8, и я хочу поддерживать совместимость с IE8.

/**
 * Count bytes in string
 *
 * Count and return the number of bytes in a given string
 *
 * @access  public
 * @param   string
 * @return  int
 */
function getByteLen(normal_val)
{
    // Force string type
    normal_val = String(normal_val);

    // Split original string into array
    var normal_pieces = normal_val.split('');
    // Get length of original array
    var normal_length = normal_pieces.length;

    // Declare array for encoded normal array
    var encoded_pieces = new Array();

    // Declare array for individual byte pieces
    var byte_pieces = new Array();

    // Loop through normal pieces and convert to URL friendly format
    for(var i = 0; i <= normal_length; i++)
    {
        if(normal_pieces[i] && normal_pieces[i] != '')
        {
            encoded_pieces[i] = encodeURI(normal_pieces[i]);
        }
    }

    // Get length of encoded array
    var encoded_length = encoded_pieces.length;

    // Loop through encoded array
    // Scan individual items for a %
    // Split on % and add to byte array
    // If no % exists then add to byte array
    for(var i = 0; i <= encoded_length; i++)
    {
        if(encoded_pieces[i] && encoded_pieces[i] != '')
        {
            // % exists
            if(encoded_pieces[i].indexOf('%') != -1)
            {
                // Split on %
                var split_code = encoded_pieces[i].split('%');
                // Get length
                var split_length = split_code.length;

                // Loop through pieces
                for(var j = 0; j <= split_length; j++)
                {
                    if(split_code[j] && split_code[j] != '')
                    {
                        // Push to byte array
                        byte_pieces.push(split_code[j]);
                    }
                }
            }
            else
            {
                // No percent
                // Push to byte array
                byte_pieces.push(encoded_pieces[i]);
            }
        }
    }

    // Array length is the number of bytes in string
    var byte_length = byte_pieces.length;

    return byte_length;
}
11 голосов | спросил MonkeyZeus 16 MonEurope/Moscow2013-12-16T20:22:08+04:00Europe/Moscow12bEurope/MoscowMon, 16 Dec 2013 20:22:08 +0400 2013, 20:22:08

3 ответа


10

Было бы намного проще выработать длину самостоятельно, а не интерпретировать результаты encodeURI()

/**
 * Count bytes in a string's UTF-8 representation.
 *
 * @param   string
 * @return  int
 */
function getByteLen(normal_val) {
    // Force string type
    normal_val = String(normal_val);

    var byteLen = 0;
    for (var i = 0; i < normal_val.length; i++) {
        var c = normal_val.charCodeAt(i);
        byteLen += c < (1 <<  7) ? 1 :
                   c < (1 << 11) ? 2 :
                   c < (1 << 16) ? 3 :
                   c < (1 << 21) ? 4 :
                   c < (1 << 26) ? 5 :
                   c < (1 << 31) ? 6 : Number.NaN;
    }
    return byteLen;
}
ответил 200_success 17 TueEurope/Moscow2013-12-17T03:05:20+04:00Europe/Moscow12bEurope/MoscowTue, 17 Dec 2013 03:05:20 +0400 2013, 03:05:20
6

Мои 2 цента

  • Пожалуйста, не сокращайте слова, не выбирайте короткие слова или аббревиатуры (Len -> Length)
  • Снимите корпус верблюда (normal_val -> normalValue)
  • Рассмотрим использование спартанских условных обозначений (s -> общая строка)
  • new Array() считается старым skool, рассмотрим var byte_pieces = []
  • Вы используете byte_pieces для отслеживания байтов только для получения длины, вы могли бы просто отслеживать длину, это быть более эффективным
  • Я не уверен, что abnormal pieces будет здесь:

if(normal_pieces[i] && normal_pieces[i] != '')

  • Вы снова проверяете их здесь, возможно, не нужно:

if(encoded_pieces[i] && encoded_pieces[i] != '')

  • Вы можете просто сделать return byte_pieces.length вместо
// Array length is the number of bytes in string
var byte_length = byte_pieces.length;

return byte_length;

Все, что вместе, я бы постарался предложить что-то вроде этого:

function getByteCount( s )
{
  var count = 0, stringLength = s.length, i;
  s = String( s || "" );
  for( i = 0 ; i < stringLength ; i++ )
  {
    var partCount = encodeURI( s[i] ).split("%").length;
    count += partCount==1?1:partCount-1;
  }
  return count;
}
getByteCount("i ♥ js");
getByteCount("abc def");

Вы можете получить сумму, используя .reduce(), я оставляю это как упражнение для читателя.

Наконец, если вы действительно обеспокоены производительностью, есть некоторые очень фантастические исполняемые js-библиотеки там .

ответил konijn 16 MonEurope/Moscow2013-12-16T22:35:51+04:00Europe/Moscow12bEurope/MoscowMon, 16 Dec 2013 22:35:51 +0400 2013, 22:35:51
0

Вы можете попробовать следующее:

var b = str.match(/[^\x00-\xff]/g);
return (str.length + (!b ? 0: b.length));

Это сработало для меня.

ответил user3728331 11 J0000006Europe/Moscow 2014, 06:54:16

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132