我获得了文件名中包含捷克字符的图像文件(例如,ěščřžýáíé),我想在没有重音的情况下重命名它们,以便它们更适合网络。 我以为我可以使用一个简单的str_replace函数,但它对文件数组的效果似乎与字符串文字不一样。
在检查扩展名后,我用readdir读取文件。
function readFiles($dir, $ext = false) {
if (is_dir($dir)) {
if ($dh = opendir($dir)) {
while (($file = readdir($dh)) !== false) {
if($ext){
if(end(explode('.', $file)) == $ext) {
$f[] = $file;
}
} else {
$f[] = $file;
}
}
closedir($dh);
return $f;
} else {
return false;
}
} else {
return false;
}
}
$files = readFiles(".", "jpg");
$search = array('š','á','ž','í','ě','é','ř','ň','ý','č',' ');
$replace = array('s','a','z','i','e','e','r','n','y','c','-');
$string = "čšěáýísdjksnalci sášěééalskcnkkjy+ěéší";
$safe_string = str_replace($search, $replace, $string);
echo '<pre>';
foreach($files as $fl) {
$safe_files[] = str_replace($search, $replace, $fl);
}
var_dump($files);
var_dump($safe_files);
var_dump($string);
var_dump($safe_string);
echo '</pre>';
输出
array(6) {
[0]=>
string(21) "Hl�vka s listem01.jpg"
[1]=>
string(23) "Hl�vky v atelieru02.jpg"
[2]=>
string(17) "Jarn� v�hon03.jpg"
[3]=>
string(17) "Mlad� chmel04.jpg"
[4]=>
string(23) "Stavba chmelnice 05.jpg"
[5]=>
string(21) "Zimni chmelnice06.jpg"
}
array(6) {
[0]=>
string(21) "Hl�vka-s-listem01.jpg"
[1]=>
string(23) "Hl�vky-v-atelieru02.jpg"
[2]=>
string(17) "Jarn�-v�hon03.jpg"
[3]=>
string(17) "Mlad�-chmel04.jpg"
[4]=>
string(23) "Stavba-chmelnice-05.jpg"
[5]=>
string(21) "Zimni-chmelnice06.jpg"
}
string(53) "čšěáýísdjksnalci sášěééalskcnkkjy+ěéší"
string(38) "cseayisdjksnalci-saseeealskcnkkjy+eesi"
现在我正在运行WAMP,但跨平台工作的答案甚至更好:)
答案 0 :(得分:5)
根据0xFFFD标记(在Firefox中显示为带有问号的钻石),您已经没有使用正确的编码(Unicode / UTF-8)读取它们。到目前为止,我发现这个bug,似乎是相关的。
以下是关于此问题的另一个主题:php readdir problem with japanese language file name
到目前为止,等到PHP6稳定后再使用它。
与问题无关:Normalizer是摆脱diacritical marks的更好工具。
答案 1 :(得分:1)
如果它适用于字符串但不适用于数组,只需将其应用于字符串: - )
$search = array('š','á','ž','í','ě','é','ř','ň','ý','č',' ');
$replace = array('s','a','z','i','e','e','r','n','y','c','-');
len = count($safe_files)
for ($i=0; $i<len; $i++)
$safe_files[$i] = str_replace($search, $replace, $safe_files[$i]);
我认为str_replace只接受2个第一个参数的数组,而不是最后一个。我可能错了,但无论如何这应该有效。
如果你有任何意思,你有一个真正的编码问题,它可能只是你的操作系统使用单字节编码,而你的源文件使用另一个,可能是UTF-8。
在这种情况下,请执行以下操作:
$search = array('š','á','ž','í','ě','é','ř','ň','ý','č',' ');
$replace = array('s','a','z','i','e','e','r','n','y','c','-');
$code_encoding = "UTF-8"; // this is my guess, but put whatever is yours
$os_encoding = "CP-1250"; // this is my guess, but put whatever is yours
len = count($safe_files)
for ($i=0; $i<len; $i++)
{
$safe_files[$i] = iconv($os_encoding , $code_encoding, $safe_files[$i]); // convert before replace
/*
ALternatively :
$safe_files[$i] = mb_convert_encoding($safe_files[$i], $code_encoding , $os_encoding );
*/
$safe_files[$i] = str_replace($search, $replace, $safe_files[$i]);
}
mb_convert_encoding()需要ext / mbstring扩展名,iconv()需要ext / iconv。
答案 2 :(得分:1)
不是直接回答你的问题,但你可能想看一下PHP中的iconv()
函数,尤其是你可以附加到第二个参数的//TRANSLIT
选项。
我已经多次使用它将法国和东欧的字符串转换为他们的a-z和url友好的同行。
来自PHP.net(http://www.php.net/manual/en/function.iconv.php)
如果将字符串// TRANSLIT附加到out_charset,则会激活音译。这意味着当一个角色无法在目标字符集中表示时,它可以通过一个或几个相似的字符来近似。
答案 3 :(得分:0)
您的源代码(和测试字符串)似乎是在utf8中,而文件名似乎使用单字节编码。我建议您使用相同的编码替换字符串。为避免源代码编码问题,最好在代码中以十六进制格式编写带重音的字符(例如\ xE8代表“č”等)。
答案 4 :(得分:0)
所以我通过这个
在我的Windows XP系统上工作了$search = array('š','á','ž','í','e','é','r','n','ý','c',' ');
$replace = array('s','a','z','i','e','e','r','n','y','c','-');
$files = readFiles(".", "jpg");
$len = count($files);
for($i = 0; $i < $len; $i++){
if(mb_check_encoding($files[$i], 'ASCII')){
$safe_files[$i] = $files[$i];
}else{
$safe_files[$i] = str_replace(
$search, $replace, iconv("iso-8859-1", "utf-8//TRANSLIT", $files[$i]));
}
if($files[$i] != $safe_files[$i]){
rename($files[$i], $safe_files[$i]);
}
}
我不知道这是不是巧合,但是调用mb_get_info()
显示
[internal_encoding] => ISO-8859-1
答案 5 :(得分:0)
这是我发现有用的另一个功能on the PHP strtr page
<?
// Windows-1250 to ASCII
// This function replace all Windows-1250 accent characters with
// thier non-accent ekvivalents. Useful for Czech and Slovak languages.
function win2ascii($str) {
$str = StrTr($str,
"\xE1\xE8\xEF\xEC\xE9\xED\xF2",
"\x61\x63\x64\x65\x65\x69\x6E");
$str = StrTr($str,
"\xF3\xF8\x9A\x9D\xF9\xFA\xFD\x9E\xF4\xBC\xBE",
"\x6F\x72\x73\x74\x75\x75\x79\x7A\x6F\x4C\x6C");
$str = StrTr($str,
"\xC1\xC8\xCF\xCC\xC9\xCD\xC2\xD3\xD8",
"\x41\x43\x44\x45\x45\x49\x4E\x4F\x52");
$str = StrTr($str,
"\x8A\x8D\xDA\xDD\x8E\xD2\xD9\xEF\xCF",
"\x53\x54\x55\x59\x5A\x4E\x55\x64\x44");
return $str;
}
?>
基本上,将欧洲字符转换为ascii equivilent并不是一个问题,但我找不到重命名文件的可靠方法(即使用非ascii字符的引用文件)。
答案 6 :(得分:0)
对于UTF-8,使用PHP函数utf8_encode。 Microsoft Windows使用ISO-8859-1,因此在这种情况下需要进行转换。
示例 - 列出目录中的文件:
<?php
$dir_handle = opendir(".");
while (false !== ($file = readdir($dir_handle)))
{
echo utf8_encode($file)."<br>";
}
?>
答案 7 :(得分:0)
Area5one是正确的 - 这是一个不同编码的问题。
当我将我的机器从XP升级到Win7时,我还升级了我的MySQL和PHP版本。在此过程中,过去工作的PHP程序停止工作。特别是,scandir,readdir和utf-8幸福地生活在一起,但不再幸福。
所以,我修改了我的代码。与从“_iso”中的硬盘端获取的数据相关的变量用于反映Windows的ISO-8859-1编码,来自MySQL数据库的数据进入以“_utf”结尾的变量。因此,area5one的代码是这样的: $ dir_handle_iso = opendir(“。”); while(false!==($ file_iso = readdir($ dir_handle_iso))) { $ file_utf = utf8_encode($ file); ... }
答案 8 :(得分:0)
这对我100%有用:
setlocale(LC_ALL,"cs_CZ");
$new_str = iconv("UTF-8","ASCII//TRANSLIT",$orig_str);
答案 9 :(得分:0)
$ file = mb_convert_encoding($ file,&#39; UTF-8&#39;,&#34; iso-8859-1&#34;); 为我工作(Windows,丹麦人物)。