【问题标题】:Can't manage to remove diacritics from a filename无法从文件名中删除变音符号
【发布时间】:2018-02-02 11:18:13
【问题描述】:

我在尝试替换文件名的变音符号和特殊字符时偶然发现了一个奇怪的行为。

该函数可以正确处理字符串,但是当我尝试使用文件名完全相同的序列时,它不会

.

$(document).on('change', 'input[type=file]', function() {
  var files = this.files;
  for (var i = 0; i < files.length; i++) {
    (function(file) {
      // Assuming the file name is áñǽŦõş
      var _string = 'áñǽŦõş.jpg',
        _filename = file.name;
      $('.string .result').html(convertAscii(_string));
      $('.filename .result').html(convertAscii(_filename));
    })(files[i]);
  }
});

function convertAscii(str) {
  str = str.replace(/Ä/g, 'Ae');
  str = str.replace(/æ|ǽ|ä/g, 'ae');
  str = str.replace(/À|Á|Â|Ã|Å|Ǻ|Ā|Ă|Ą|Ǎ|А/g, 'A');
  str = str.replace(/à|á|â|ã|å|ǻ|ā|ă|ą|ǎ|ª|а/g, 'a');
  str = str.replace(/Б/g, 'B');
  str = str.replace(/б/g, 'b');
  str = str.replace(/Ç|Ć|Ĉ|Ċ|Č|Ц/g, 'C');
  str = str.replace(/ç|ć|ĉ|ċ|č|ц/g, 'c');
  str = str.replace(/Ð|Ď|Đ/g, 'Dj');
  str = str.replace(/ð|ď|đ/g, 'dj');
  str = str.replace(/Д/g, 'D');
  str = str.replace(/д/g, 'd');
  str = str.replace(/È|É|Ê|Ë|Ē|Ĕ|Ė|Ę|Ě|Е|Ё|Э/g, 'E');
  str = str.replace(/è|é|ê|ë|ē|ĕ|ė|ę|ě|е|ё|э/g, 'e');
  str = str.replace(/Ф/g, 'F');
  str = str.replace(/ƒ|ф/g, 'f');
  str = str.replace(/Ĝ|Ğ|Ġ|Ģ|Г/g, 'G');
  str = str.replace(/ĝ|ğ|ġ|ģ|г/g, 'g');
  str = str.replace(/Ĥ|Ħ|Х/g, 'H');
  str = str.replace(/ĥ|ħ|х/g, 'h');
  str = str.replace(/Ì|Í|Î|Ï|Ĩ|Ī|Ĭ|Ǐ|Į|İ|И/g, 'I');
  str = str.replace(/ì|í|î|ï|ĩ|ī|ĭ|ǐ|į|ı|и/g, 'i');
  str = str.replace(/Ĵ|Й/g, 'J');
  str = str.replace(/ĵ|й/g, 'j');
  str = str.replace(/Ķ|К/g, 'K');
  str = str.replace(/ķ|к/g, 'k');
  str = str.replace(/Ĺ|Ļ|Ľ|Ŀ|Ł|Л/g, 'L');
  str = str.replace(/ĺ|ļ|ľ|ŀ|ł|л/g, 'l');
  str = str.replace(/М/g, 'M');
  str = str.replace(/м/g, 'm');
  str = str.replace(/Ñ|Ń|Ņ|Ň|Н/g, 'N');
  str = str.replace(/ñ|ń|ņ|ň|ʼn|н/g, 'n');
  str = str.replace(/Ö/g, 'Oe');
  str = str.replace(/œ|ö/g, 'oe');
  str = str.replace(/Ò|Ó|Ô|Õ|Ō|Ŏ|Ǒ|Ő|Ơ|Ø|Ǿ|О/g, 'O');
  str = str.replace(/ò|ó|ô|õ|ō|ŏ|ǒ|ő|ơ|ø|ǿ|º|о/g, 'o');
  str = str.replace(/П/g, 'P');
  str = str.replace(/п/g, 'p');
  str = str.replace(/Ŕ|Ŗ|Ř|Р/g, 'R');
  str = str.replace(/ŕ|ŗ|ř|р/g, 'r');
  str = str.replace(/Ś|Ŝ|Ş|Ș|Š|С/g, 'S');
  str = str.replace(/ś|ŝ|ş|ș|š|ſ|с/g, 's');
  str = str.replace(/Ţ|Ț|Ť|Ŧ|Т/g, 'T');
  str = str.replace(/ţ|ț|ť|ŧ|т/g, 't');
  str = str.replace(/Ü/g, 'Ue');
  str = str.replace(/ü/g, 'ue');
  str = str.replace(/Ù|Ú|Û|Ũ|Ū|Ŭ|Ů|Ű|Ų|Ư|Ǔ|Ǖ|Ǘ|Ǚ|Ǜ|У/g, 'U');
  str = str.replace(/ù|ú|û|ũ|ū|ŭ|ů|ű|ų|ư|ǔ|ǖ|ǘ|ǚ|ǜ|у/g, 'u');
  str = str.replace(/В/g, 'V');
  str = str.replace(/в/g, 'v');
  str = str.replace(/Ý|Ÿ|Ŷ|Ы/g, 'Y');
  str = str.replace(/ý|ÿ|ŷ|ы/g, 'y');
  str = str.replace(/Ŵ/g, 'W');
  str = str.replace(/ŵ/g, 'w');
  str = str.replace(/Ź|Ż|Ž|З/g, 'Z');
  str = str.replace(/ź|ż|ž|з/g, 'z');
  str = str.replace(/Æ|Ǽ/g, 'AE');
  str = str.replace(/ß/g, 'ss');
  str = str.replace(/IJ/g, 'IJ');
  str = str.replace(/ij/g, 'ij');
  str = str.replace(/Œ/g, 'OE');
  str = str.replace(/Ч/g, 'Ch');
  str = str.replace(/ч/g, 'ch');
  str = str.replace(/Ю/g, 'Ju');
  str = str.replace(/ю/g, 'ju');
  str = str.replace(/Я/g, 'Ja');
  str = str.replace(/я/g, 'ja');
  str = str.replace(/Ш/g, 'Sh');
  str = str.replace(/ш/g, 'sh');
  str = str.replace(/Щ/g, 'Shch');
  str = str.replace(/щ/g, 'shch');
  str = str.replace(/Ж/g, 'Zh');
  str = str.replace(/ж/g, 'zh');
  return str;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="file" name="pic" accept="image/*">

<div>
  <div class="string">Converted string : <span class="result"></span></div>
  <div class="filename">Converted filename : <span class="result"></span></div>
</div>

我还让a fiddle 显示了这个问题,当你上传一个名为áñaéTõş 的jpg 时,你会明白我的意思。

我从输入中获取文件名。奇怪的行为是这样的:

console.log(convertAscii(_string)); // Correct => anaeTos
console.log(convertAscii(_filename)); // Wrong => áñaéTõş

我相信这是因为变音符号被解释为独立字符,但是有人知道如何解决它吗?

【问题讨论】:

  • 我无法重现:文件名已正确翻译。您在哪个浏览器中运行,以及哪个操作系统? (我在FF,Windows上运行)
  • 我可以重现它。行为发生在 Chrome 中。这很奇怪 - 几乎就像字符串是只读的
  • 我在 macOS Sierra 10.12.4 上,它发生在 FF / Chrome / Safari / Opera 上。
  • 这与不同的编码有关(我相信)。检查your modified fiddle,它只是打印 URI 编码的字符串。您可能会得到 Unicode 格式的文件名,而字符串是 UTF-8,反之亦然。
  • 编码,代码点...我不知道这里的来龙去脉,但也许这个人指出你需要什么:stackoverflow.com/a/10805884/2064981

标签: javascript jquery regex


【解决方案1】:

我确信您的代码由于 codeppoint 问题而无法正常工作。有问题的字符可能看起来像您期望的特殊字符,但最终并不相等。因此,字符串替换不起作用

要解决这个问题,正如@ClasG 所建议的那样,您可以使用外部库执行 Unicode 规范化,因为 JavaScript 没有内置此功能。

  • unorm 是可以为您进行规范化的低级库。
  • 还有更多高级库,如iconv lite,它们有更多的依赖关系。

还需要在您的代码中使用 Unicode 字符来进行与规范化文本的比较。

这是我修改后的fiddle。我希望这可以为您解决问题。

$(document).on('change', 'input[type=file]', function() {

  var files = this.files;

  for (var i = 0; i < files.length; i++) {
    (function(file) {
      // Assuming the file name is áñǽŦõş
      var _string = 'äöüß', // 'áñǽŦõş.jpg',
        _filename = file.name;

      $('.string .result').html(convertAscii(_string.normalize('NFC')));
      $('.filename .result').html(convertAscii(_filename.normalize('NFC')));

    })(files[i]);
  }

});

function convertAscii(str) {
  //convert German umlauts (normalized using nfc: Canonical Decomposition, followed by Canonical Composition) to Ascii
  tr = {
    "\u00e4": "ae",
    "\u00fc": "ue",
    "\u00f6": "oe",
    "\u00df": "ss"
  }
  str = str.replace(/[\u00e4|\u00fc|\u00f6|\u00df]/g, function($0) {
    return tr[$0]
  })
  //... add more..

  return str;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src='https://raw.githubusercontent.com/walling/unorm/master/lib/unorm.js'></script>
<input type="file" name="pic" accept="image/*">

</script>
<div>
  <div class="string">Converted string : <span class="result"></span></div>
  <div class="filename">Converted filename : <span class="result"></span></div>
</div>

【讨论】:

    猜你喜欢
    • 2012-04-29
    • 2019-03-09
    • 2011-04-07
    • 2016-09-01
    • 2011-01-07
    • 1970-01-01
    • 2015-08-30
    • 1970-01-01
    • 2010-09-19
    相关资源
    最近更新 更多