Я подозреваю, что один из Java или Mac использует CESU-8 вместо надлежащего UTF-8. Java использует «модифицированный UTF-8» (что является небольшим изменением CESU-8) для различных внутренних целей, но я не знал, что он мог бы использовать его как файловую систему / defaultCharset. К сожалению, у меня нет ни Mac, ни Java для тестирования.
«Модифицированный» - это модифицированный способ сказать «сильно прослушивается». Вместо вывода четырехбайтовой последовательности UTF-8 для дополнительных (не BMP) символов, таких как & # x26FF6;:
\xF0\xA6\xBF\xB6
выводит последовательность в кодировке UTF-8 для каждого из суррогатов:
\xED\xA1\x9B\xED\xBF\xB6
Это недопустимая последовательность UTF-8, но многие декодеры в любом случае разрешат это. Проблема в том, что, если вы в обратном порядке, то через настоящий кодер UTF-8 вы получили другую строку, четырехбайтовую, приведенную выше. Попробуйте получить доступ к файлу с этим именем и бум! потерпеть неудачу.
Итак, сначала давайте просто проверим, как имена файлов на самом деле хранятся в вашей текущей файловой системе, используя платформу, которая использует байты для имен файлов, например Python 2.x:
$ python
Python 2.x.something (blah blah)
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.listdir('.')
В моей файловой системе (Linux, ext4, UTF-8) имя файла «草 & # x26FF6; 鷗 外 .gif» выглядит так:
['\xe8\x8d\x89\xf0\xa6\xbf\xb6\xe9\xb7\x97\xe5\xa4\x96.gif']
что ты и хочешь. Если это то, что вы получаете, вероятно, Java делает это неправильно. Если вы получили более длинную шестибайтовую версию:
['\xe8\x8d\x89\xed\xa1\x9b\xed\xbf\xb6\xe9\xb7\x97\xe5\xa4\x96.gif']
это, вероятно, OS X делает неправильно ... всегда ли хранятся такие имена файлов? (Или файлы пришли откуда-то еще изначально?) Что если вы переименуете файл в «правильную» версию?:
os.rename('\xe8\x8d\x89\xed\xa1\x9b\xed\xbf\xb6\xe9\xb7\x97\xe5\xa4\x96.gif', '\xe8\x8d\x89\xf0\xa6\xbf\xb6\xe9\xb7\x97\xe5\xa4\x96.gif')