4

我得到文件名中包含捷克字符的图像文件(例如,ěščřžýáíé),我想重命名它们而不带重音,以便它们与网络更兼容。我以为我可以使用一个简单的 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 上运行,但跨平台工作的答案更好:)

4

10 回答 10

5

根据 0xFFFD 标记(在 Firefox 中显示为带有问号的菱形),您已经没有使用正确的编码(即 Unicode / UTF-8)读取它们。据我发现这个错误,它似乎是相关的。

这是另一个关于此的主题:php readdir question with Japanese language file name

直截了当,等到他们获得稳定的 PHP6 后再使用它。

与问题无关:Normalizer是摆脱变音符号的更好工具。

于 2009-11-19T22:33:29.510 回答
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。

于 2009-11-19T22:23:50.120 回答
1

也许不能直接回答您的问题,但您可能想看看iconv()PHP 中的函数,尤其是//TRANSLIT可以附加到第二个参数的选项。我已经使用它多次将法语和东欧字符串转换为对 az 和 url 友好的对应对象。

来自 PHP.net ( http://www.php.net/manual/en/function.iconv.php )

如果您将字符串 //TRANSLIT 附加到 out_charset 音译被激活。这意味着当一个字符不能在目标字符集中表示时,它可以通过一个或几个看起来相似的字符来近似。

于 2009-11-19T22:58:28.523 回答
0

这对我有用 100%:

setlocale(LC_ALL,"cs_CZ");
$new_str = iconv("UTF-8","ASCII//TRANSLIT",$orig_str);
于 2015-03-24T08:35:47.967 回答
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

于 2009-11-20T01:41:17.260 回答
0

这是我在 PHP strtr 页面上发现的另一个有用的函数

<?
// 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 等效字符不是问题,但我找不到重命名文件的可靠方法(即,具有非 ascii 字符的参考文件)。

于 2009-12-15T10:10:52.443 回答
0

您的源代码(和测试字符串)似乎是 utf8,而文件名似乎使用单字节编码。我建议您对替换字符串使用相同的编码。为避免源编码问题,最好在代码中以十六进制形式编写重音字符(如 \xE8 表示“č”等)。

于 2009-11-19T22:16:58.507 回答
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>";
}
?>
于 2009-12-25T12:57:23.420 回答
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); ... }

于 2013-05-28T19:38:38.340 回答
0

$file = mb_convert_encoding($file, 'UTF-8', "iso-8859-1"); 为我工作(Windows,丹麦语字符)。

于 2016-12-16T02:30:34.650 回答