基于字节而不是字符计数的 Substr
Substr based on bytes rather than character count
我正在创建一个输入系统,其中字段最大值只能为 200 字节。我使用以下方法计算剩余的字节数(这种方法也可能引起争论!
var totalBytes = 200;
var $newVal = $(this).val();
var m = encodeURIComponent($newVal).match(/%[89ABab]/g);
var bytesLeft = totalBytes - ($newVal.length + (m ? m.length : 0));
这似乎效果很好,但是如果有人要粘贴大量数据,我希望能够对输入进行切片并仅显示其中的 200 个字节。我想在伪代码中看起来像:
$newText = substrBytes($string, 0, 200);
任何帮助或指导将不胜感激。
编辑:这里发生的一切都是 UTF-8 顺便说一句:)
编辑2:我知道我可以循环每个角色并进行评估,我想我希望有一些更优雅的东西来处理这个问题。
谢谢!
谷歌搜索产生了一篇博客文章,并附有一个自己尝试的输入框。我在这里复制代码是因为 SO 喜欢明确的答案而不是链接,但功劳归于 McDowell。
/**
* codePoint - an integer containing a Unicode code point
* return - the number of bytes required to store the code point in UTF-8
*/
function utf8Len(codePoint) {
if(codePoint >= 0xD800 && codePoint <= 0xDFFF)
throw new Error("Illegal argument: "+codePoint);
if(codePoint < 0) throw new Error("Illegal argument: "+codePoint);
if(codePoint <= 0x7F) return 1;
if(codePoint <= 0x7FF) return 2;
if(codePoint <= 0xFFFF) return 3;
if(codePoint <= 0x1FFFFF) return 4;
if(codePoint <= 0x3FFFFFF) return 5;
if(codePoint <= 0x7FFFFFFF) return 6;
throw new Error("Illegal argument: "+codePoint);
}
function isHighSurrogate(codeUnit) {
return codeUnit >= 0xD800 && codeUnit <= 0xDBFF;
}
function isLowSurrogate(codeUnit) {
return codeUnit >= 0xDC00 && codeUnit <= 0xDFFF;
}
/**
* Transforms UTF-16 surrogate pairs to a code point.
* See RFC2781
*/
function toCodepoint(highCodeUnit, lowCodeUnit) {
if(!isHighSurrogate(highCodeUnit)) throw new Error("Illegal argument: "+highCodeUnit);
if(!isLowSurrogate(lowCodeUnit)) throw new Error("Illegal argument: "+lowCodeUnit);
highCodeUnit = (0x3FF & highCodeUnit) << 10;
var u = highCodeUnit | (0x3FF & lowCodeUnit);
return u + 0x10000;
}
/**
* Counts the length in bytes of a string when encoded as UTF-8.
* str - a string
* return - the length as an integer
*/
function utf8ByteCount(str) {
var count = 0;
for(var i=0; i<str.length; i++) {
var ch = str.charCodeAt(i);
if(isHighSurrogate(ch)) {
var high = ch;
var low = str.charCodeAt(++i);
count += utf8Len(toCodepoint(high, low));
} else {
count += utf8Len(ch);
}
}
return count;
}
JavaScript 中的字符串在内部以 UTF-16 表示,因此每个字符实际上需要两个字节。所以你的问题更像是"以 UTF-8 格式获取 str 的字节长度"。
您几乎不需要一半的符号,因此可能会减少 198 或 199 个字节。
这里有 2 种不同的解决方案:
// direct byte size counting
function cutInUTF8(str, n) {
var len = Math.min(n, str.length);
var i, cs, c = 0, bytes = 0;
for (i = 0; i < len; i++) {
c = str.charCodeAt(i);
cs = 1;
if (c >= 128) cs++;
if (c >= 2048) cs++;
if (c >= 0xD800 && c < 0xDC00) {
c = str.charCodeAt(++i);
if (c >= 0xDC00 && c < 0xE000) {
cs++;
} else {
// you might actually want to throw an error
i--;
}
}
if (n < (bytes += cs)) break;
}
return str.substr(0, i);
}
// using internal functions, but is not very fast due to try/catch
function cutInUTF8(str, n) {
var encoded = unescape(encodeURIComponent(str)).substr(0, n);
while (true) {
try {
str = decodeURIComponent(escape(encoded));
return str;
} catch(e) {
encoded = encoded.substr(0, encoded.length-1);
}
}
}
相关文章:
- 在JavaScript中输出转义字符
- 不同浏览器中的空白字符正则表达式行为
- Regex匹配除“”之外的所有字符;.js”;
- 拆分文本以每隔n个字符添加一行新行,并注意空格
- 使用RegExp查找url中的字符
- 如何为jQuery屏蔽输入插件创建一个允许字母数字、空格和重音字符的掩码
- 使用正则表达式将输入格式设置为单字符逗号、单字符逗号等
- 允许在文本框中使用某些字符
- 根据页面的位置突出显示文本中的字符
- 元素的内容必须由格式正确的字符数据或标记组成
- 如何将字符串拆分为字符,但在javascript中保留空格
- 使用Google Maps API向标记添加多个字符
- 处理JSON字符串会导致JavaScript错误
- 单元格的工具提示或标题不显示超过2000个字符
- javascript替换换行符和特殊字符
- angularjs删除动态形式元素中的特殊字符
- 元素名称上带有短划线 (-) 字符的 Json 对象
- 无法呈现js unicode字符“u1F310”
- JavaScript substr 与从第一个字符开始时的子字符串
- 基于字节而不是字符计数的 Substr