unicode标准中有足够的代码点,你需要4个字节来存储它们.这就是UTF-32编码所做的.然而,UTF-8编码通过使用称为"可变宽度编码"的东西以某种方式将这些压缩到更小的空间.
实际上,它设法在一个字节中代表US-ASCII的前127个字符,它看起来与真正的ASCII完全相同,因此您可以将许多ascii文本解释为UTF-8而不对其执行任何操作.干净的把戏.那么它是怎样工作的?
我将在这里提出并回答我自己的问题,因为我只是做了一些阅读以弄清楚它并且我认为它可能会节省其他人一些时间.如果我有一些错误,也许有人可以纠正我.
因此,matz决定保留upcase
并downcase
限制/[A-Z]/i
在ruby 1.9.1中.
ActiveSupport::Multibyte
长期以来在ruby 1.8.x中经历了很棒的i18n案例String#mb_chars
.
但是,当在ruby 1.9.1下尝试时,它似乎不起作用.这是我写的一个简单的测试脚本,以及我得到的输出:
$ cat test.rb
# encoding: UTF-8
puts("@ #{RUBY_VERSION} " + (__ENCODING__ rescue $KCODE).to_s)
sd, su = "Iñtërnâtiônàlizætiøn", "IÑTËRNÂTIÔNÀLIZÆTIØN"
def ps(u, d, k); puts "%-30s: %24s / %-24s" % [k, u, d] end
ps sd.upcase, su.downcase, "Plain ruby"
require 'rubygems'; require 'active_support'
ps sd.upcase, su.downcase, "With active_support"
ps sd.mb_chars.upcase.to_s, su.mb_chars.downcase.to_s, "With active_support mb_chars"
$ ruby -KU test.rb
@ 1.8.7 UTF8
Plain ruby : IñTëRNâTIôNàLIZæTIøN / iÑtËrnÂtiÔnÀlizÆtiØn …
Run Code Online (Sandbox Code Playgroud) 显然没有mb_trim
在mb_*
家庭,所以我想实现一个我自己.
我最近在php.net的评论中发现了这个正则表达式:
/(^\s+)|(\s+$)/u
Run Code Online (Sandbox Code Playgroud)
所以,我将通过以下方式实现它:
function multibyte_trim($str)
{
if (!function_exists("mb_trim") || !extension_loaded("mbstring")) {
return preg_replace("/(^\s+)|(\s+$)/u", "", $str);
} else {
return mb_trim($str);
}
}
Run Code Online (Sandbox Code Playgroud)
正则表达式似乎对我来说是正确的,但我是正则表达式的极力菜鸟.这会有效地删除字符串开头/结尾的任何 Unicode空间吗?
我设法忽略了所有这些多字节字符的东西,但现在我需要做一些UI工作,我知道我在这方面的无知将赶上我!任何人都可以在几段或更少的段落中解释我需要知道什么,以便我可以本地化我的应用程序?我应该使用什么类型(我同时使用.Net和C/C++,我需要Unix和Windows的答案).
多字节这个术语是指一个字符集,它的字符可以 - 但不一定是 - 宽于1个字节(例如UTF-8),或者它是指在任何情况下宽于1个字节的字符集(例如UTF) -16)?换句话说:如果有人谈论多字节字符集是什么意思?
我正在编写一个文件管理器,需要扫描目录并处理重命名可能有多字节字符的文件.我正在Windows/Apache PHP 5.3.8上本地工作,目录中包含以下文件名:
在实时UNIX服务器上进行的测试很好.在Windows上本地测试使用glob('./path/*')
仅返回第一个,filename.jpg
.
使用scandir()
,至少返回正确数量的文件,但我得到的名称?????????.jpg
(注意:那些是常规问号,而不是 字符.
我最终需要编写一个"搜索"功能,以递归方式搜索整个树,查找与模式或某个文件扩展名匹配的文件名,我认为glob()
这将是正确的工具,而不是扫描所有文件和在应用程序代码中进行模式匹配和数组构建.如果需要,我愿意接受其他建议.
假设这是一个常见的问题,我立即搜索了Google和Stack Overflow,发现没有任何相关内容.这是一个Windows问题吗?PHP的缺点?解决方案是什么:我能做些什么吗?
附录:不知道如何与这个,但file_exists()
也恢复FALSE
这些文件,通过在全绝对路径(使用记事本++,PHP文件本身是UTF-8编码没有BOM).我确定路径是正确的,因为没有多字节字符的相邻文件会返回TRUE
.
编辑:glob()
可以找到一个名为的文件filename-äöü.jpg
.以前在我的.htaccess
文件中,我有AddDefaultCharset utf-8
,我之前没有考虑过.filename-äöü.jpg
打印为filename-???.jpg
.删除htaccess行的唯一效果似乎是文件名正常打印.
我已.htaccess
完全删除了该文件,这是我的实际测试脚本(我从原始帖子中更改了几个文件名):
print_r(scandir('./uploads/'));
print_r(glob('./uploads/*'));
Run Code Online (Sandbox Code Playgroud)
在Windows上本地输出:
Array
(
[0] => .
[1] => ..
[2] => ??? ?????.jpg
[3] => ???.jpg
[4] => ?????????.jpg
[5] => filename-äöü.jpg
[6] => filename.jpg
[7] …
Run Code Online (Sandbox Code Playgroud) PHP中没有多字节'preg'函数,这是否意味着默认的preg_functions都是mb安全的?在php文档中找不到任何提及.
鉴于某些多字节字符集,我是否正确假设以下内容不符合预期目的?
$string = str_replace('"', '\\"', $string);
Run Code Online (Sandbox Code Playgroud)
特别是,如果输入的字符集可能具有像0xbf5c这样的有效字符,那么攻击者可以注入0xbf22来获取0xbf5c22,留下一个有效字符后跟一个不带引号的双引号(").
有没有一种简单的方法来缓解这个问题,或者我是否首先误解了这个问题?
(在我的例子中,字符串进入HTML输入标签的value属性:echo'input type ="text"value ="'.$ string.'">';)
编辑:就此而言,像preg_quote()这样的函数呢?它没有charset论据,因此在这种情况下似乎完全没用.如果你没有选择将字符集限制为UTF-8(是的,这很好),你好像很残疾.在这种情况下可以使用哪些替换和引用功能?
是否有可能在Javascript中检测字符串是否包含多字节字符?如果是这样,是否可以分辨哪些?
我遇到的问题是这个(如果Unicode char不适合你,我会道歉)
s = "";
alert(s.length); // '2'
alert(s.charAt(0)); // '??'
alert(s.charAt(1)); // '??'
Run Code Online (Sandbox Code Playgroud)
在这里编辑一点清晰(我希望). 据我所知,Javascript中的所有字符串都表示为一系列UTF-16代码点,这意味着常规字符实际占用2个字节(16位),因此我在标题中使用"多字节"有点关闭.某些字符不属于基本多语言平面(BMP),例如上例中的字符串,因此它们占用两个代码点(32位).这是我问的问题.我也没有编辑原始标题,因为对于那些对这些东西不太了解的人(因此会搜索SO的信息),"multibyte"会有意义.
在这些语句中,两者都使用相同的编码(UTF-8)输入到源代码中并且语言环境设置正确,它们之间是否存在实际差异?
printf("? ??????????? ?? ???? ?????\n");
printf("%ls", L"? ??????????? ?? ???? ?????\n");
Run Code Online (Sandbox Code Playgroud)
因此有什么理由在做输出时更喜欢一个而不是另一个?我想第二个表现得差一点,但是它对多字节文字有任何优势(或劣势)吗?
编辑:这些字符串打印没有问题.但是我没有使用宽字符串函数,因为我也希望能够使用printf
等等.所以问题是打印任何不同的方式(鉴于上面列出的情况),如果是这样,第二个方法有任何优势吗?
编辑2:按照下面的评论,我现在知道这个程序有效 - 我认为这是不可能的:
int main()
{
setlocale(LC_ALL, "");
wprintf(L"? ??????????? ?? ???? ?????\n"); // wide output
freopen(NULL, "w", stdout); // lets me switch
printf("? ??????????? ?? ???? ?????\n"); // byte output
}
Run Code Online (Sandbox Code Playgroud)
EDIT3:我通过观察这两种类型的情况做了一些进一步的研究.拿一个更简单的字符串:
wchar_t *wides = L"£100 ?";
char *mbs = "£100 ?";
Run Code Online (Sandbox Code Playgroud)
编译器生成不同的代码.宽字符串是:
.string "\243"
.string ""
.string ""
.string "1"
.string ""
.string ""
.string "0"
.string ""
.string ""
.string …
Run Code Online (Sandbox Code Playgroud) multibyte ×10
utf-8 ×6
php ×4
unicode ×4
string ×2
c ×1
filesystems ×1
javascript ×1
mbstring ×1
preg-match ×1
preg-replace ×1
printf ×1
regex ×1
ruby ×1
terminology ×1
utf-16 ×1
windows ×1