Краткая история одного бага

Как-то раз самый главный пользователь ЯРИЛа и фактически его соавтор наткнулся на один баг, который никому до этого не попадался — у него после добавления библиотеки в историю и последующей загрузки игры вываливалась простыня с ошибкой. (Вот этот баг.)
У меня он сходу не воспроизвёлся, да и потом тоже. Стали разбираться сообща. Все условия практически идентичны, разве что я запускаю с меню «Пуск», а он — с Total Commander. Но какая разница? Стали сравнивать логи. Единственное, чем они отличались — это регистр диска C: (у меня большая буква, у него — маленькая). И это под Windows. Под Windows же регистр не имеет значения? Да, для путей не имеет.
А дело вот в чём. В Java 6, на которой изначально писался ЯРИЛ, нет встроенного функционала для получения относительного пути к файлу из двух абсолютных (надо было получить путь к библиотеке относительно игры).
Но есть обходной путь — у класса File (отвечающего за файл) есть метод toURI(), преобразуйщий путь к URI (если что, тут есть непонятное описание URI). А у него в свою очередь есть метод relativize(), который и возвращает относительный путь. Да, это работает в большинстве случаев. :)
Помните, что наши логи отличались только регистром диска C:? Нюанс в том, что Total Commander сохраняет путь к папке запуска почему-то с маленькой буквы. Так вот, URI не прощает разный регистр, в итоге это оказались совершенно разные пути, и вместо относительного relativize() вернул абсолютный, да ещё со слэшем ("/") вначале. В итоге путь к библиотеке сохранился в виде "/C:/..." — и далее полный путь к файлу. А по такому пути File уже не может загрузить файл. да и путь этот для ссылки на библиотеку не верный.
Вот такая вот история.
P.S. Для Java 6 нет идеального исправления, пришлось пока перед получением относительного пути приводить всё к одному (нижнему) регистру, но, боюсь, это тоже может выстрелить. В Java 8 уже есть класс Path для работы с путями, надеюсь, он учитывает эти особенности разных платформ. :)

3 комментария

epoxa
Вот она — хваленая «идеальная переносимость» Java, которая работает только на сферической операционной системе в вакууме :) А вообще, да, интересные бывают баги. У тебя получилось, что ошибка проявилась даже не от замены одной буквы, а всего лишь от способа ее написания — в строчном регистре или заглавном.
ASBer
О как! =)
А я наоборот предпочитаю относительные пути преобразовывать к абсолютным и далее работать только с абсолютными…
realsonic
Это если работать. А тут сохраняется путь в файл истории, чтобы история потом в другом месте могла рядом с собой найти библиотеку.