Использование JavaScript для усечения текста до определенного размера (8 КБ) - PullRequest
8 голосов
/ 04 октября 2009

Я использую Zemanta API, который принимает до 8 КБ текста на вызов. Я извлекаю текст для отправки в Zemanta с веб-страниц с помощью JavaScript, поэтому я ищу функцию, которая усекает мой текст ровно на 8 КБ.

Zemanta должна выполнить это усечение самостоятельно (то есть, если вы отправите ей строку большего размера), но мне нужно немного переместить этот текст перед вызовом API, поэтому я хочу сохранить как можно меньшую полезную нагрузку .

Можно ли предположить, что 8 КБ текста составляет 8 192 символа, и соответственно усечь? (1 байт на символ; 1024 символа на КБ; 8 КБ = 8 192 байта / символ) Или это неточно или верно только при определенных обстоятельствах?

Есть ли более элегантный способ обрезать строку в зависимости от ее фактического размера?

Ответы [ 4 ]

10 голосов
/ 04 октября 2009

Если вы используете однобайтовую кодировку, да, 8192 символа = 8192 байта. Если вы используете UTF-16, 8192 символа (*) = 4096 байт.

(На самом деле 8192 кодовых точек, что немного отличается от суррогатов, но давайте не будем об этом беспокоиться, потому что JavaScript этого не делает.)

Если вы используете UTF-8, есть быстрый прием, который можно использовать для реализации кодера / декодера UTF-8 в JS с минимальным кодом:

function toBytesUTF8(chars) {
    return unescape(encodeURIComponent(chars));
}
function fromBytesUTF8(bytes) {
    return decodeURIComponent(escape(bytes));
}

Теперь вы можете обрезать с помощью:

function truncateByBytesUTF8(chars, n) {
    var bytes= toBytesUTF8(chars).substring(0, n);
    while (true) {
        try {
            return fromBytesUTF8(bytes);
        } catch(e) {};
        bytes= bytes.substring(0, bytes.length-1);
    }
}

(Причина попытки перехвата заключается в том, что если вы урежете байты в середине многобайтовой последовательности символов, вы получите недопустимый поток UTF-8, и decodeURIComponent будет жаловаться.)

Если это другая многобайтовая кодировка, такая как Shift-JIS или Big5, вы сами по себе.

2 голосов
/ 04 октября 2009

Нет, небезопасно предполагать, что 8 КБ текста - это 8192 символа, поскольку в некоторых кодировках символов каждый символ занимает несколько байтов .

Если вы читаете данные из файлов, вы не можете просто взять размер файла? Или прочитать его кусками по 8 КБ?

1 голос
/ 24 августа 2018

Вы можете сделать что-то подобное, так как unescape частично устарела

function byteCount( string ) {
    // UTF8
    return encodeURI(string).split(/%..|./).length - 1;
}

function truncateByBytes(string, byteSize) {
    // UTF8
    if (byteCount(string) > byteSize) {
        const charsArray = string.split('');
        let truncatedStringArray = [];
        let bytesCounter = 0;
        for (let i = 0; i < charsArray.length; i++) {
            bytesCounter += byteCount(charsArray[i]);
            if (bytesCounter <= byteSize) {
                truncatedStringArray.push(charsArray[i]);
            } else {
                break;
            }
        }
        return truncatedStringArray.join('');
    }
    return string;
}
1 голос
/ 04 октября 2009

Как говорит Доминик, проблема заключается в кодировке символов - однако, если вы можете либо действительно , убедитесь, что вы будете иметь дело только с 8-битными символами (маловероятно, но возможно), либо допустите 16-битные символы и ограничение до половины доступного пространства, то есть 4096 символов, тогда вы можете попробовать это.

Это плохая идея полагаться на JS для этого, потому что он может быть тривиально изменен или проигнорирован, и у вас есть сложности, связанные с escape-символами и кодированием, например. Лучше использовать JS в качестве фильтра первого шанса и использовать любой доступный вам язык на стороне сервера (который также откроет сжатие).

...