使用JavaScript将文本截断为特定大小(8 KB)

时间:2009-10-04 08:06:55

标签: javascript text byte truncate zemanta

我正在使用Zemanta API,每次调用最多可接受8 KB的文本。我正在使用JavaScript从网页中提取要发送给Zemanta的文本,所以我正在寻找一个能够以8 KB的速度截断我的文本的函数。

Zemanta应该自己进行截断(例如,如果你发送一个更大的字符串),但是我需要在进行API调用之前将这个文本稍微移动一下,所以我想保持有效负载尽可能小

假设8 KB的文本是8,192个字符并且相应地截断是否安全? (每个字符1个字节;每KB 1,024个字符; 8 KB = 8,192个字节/字符)或者,在某些情况下是不准确还是仅为真?

是否有更优雅的方法根据文件的实际文件大小截断字符串?

4 个答案:

答案 0 :(得分:10)

如果您使用单字节编码,是,8192个字符= 8192个字节。如果您使用的是UTF-16,8192个字符(*)= 4096个字节。

(实际上是8192个代码点,面对​​代理人的情况略有不同,但我们不要担心,因为JavaScript没有。)

如果您使用的是UTF-8,可以使用快速技巧在JS中使用最少的代码实现UTF-8编码器/解码器:

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);
    }
}

(try-catch的原因是,如果你截断多字节字符序列中间的字节,你将得到一个无效的UTF-8流,而decodeURIComponent会抱怨。)

如果它是另一种多字节编码,例如Shift-JIS或Big5,那么你就是自己的。

答案 1 :(得分:2)

不,假设8KB的文本是8192个字符是不安全的,因为在某些字符编码中,每个字符占用multiple bytes

如果您正在从文件中读取数据,那么您是否只能抓取文件大小?或者以8KB的块读取它?

答案 2 :(得分:1)

正如多米尼克所说,字符编码是问题所在 - 但是如果你能真的确保你只处理8位字符(不太可能但可能)或假设16位字符和将自己限制在可用空间的一半,即4096个字符,然后你可以尝试这个。

依靠JS来做这个是一个坏主意,因为它可以被简单地修改或忽略,并且你有例如转义字符和编码的复杂性。最好使用JS作为第一次机会过滤器并使用您可用的任何服务器端语言(这也将打开压缩)。

答案 3 :(得分:1)

由于不建议使用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;
}