Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Разделители в пути к файлу
Форум на CrossPlatform.RU > Библиотеки > Qt > Qt Ввод/Вывод, Сеть. Межпроцессное взаимодействие
Анна
Столкнулась с тем, что если составляю путь к файлу, например,

QString file_name = QCoreApplication::absoluteDirPath() + QDir::separator() + my_dir + QDir::separator() + name;

то часть резделителей виндовые, а часть линуксовые. QFile и QDir к этому относятся спокойно, но вот когда приходится сравнивать строковые значения, одно из которых создано, как показано выше, а другое приходит извне и указывает на тот же самый файл, возникает печалька...
QCoreApplication::absoluteDirPath() под виндой возвращает линуксовые разделители. Можно ли с этим что-то сделать?

...

Обнаружила, что мне приходит полный путь до файла тоже с линуксовыми разделителями. И получают его из QFile::fileName();
Выходит, особенности системы учитывает только QDir::separator().
Majestio
Непонятно только в чем вопрос :)

По мне, так я использую везде юниховый синтаксис, венда его кушает спокойно ... пока, по крайней мере.
Для рассовой чистоты конечно можно сделать замену в строке / на \ , только пока в этом смысла не вижу.
Анна
Ворос был в том, что пути к одному и тому же файлу выглядят по разному: "c:/xxx/xxx/xxxx\xxx\xxx" и "c:/xxx/xxx/xxxx/xxx/xxx".

В документации QDir прочитала, что не рекомендуется использовать QDir::separator(), лучше всегда '/'. А для вывода в виде, соответствующем системе, использовать QDir::toNativeSeparators() и для обратного действия QDir::fromNativeSeparators(). Выходит, мне все имена файлов нужно гнать через эти функции, например, перед сравнением.

Я просто никогда не сталкивалась с таким, поэтому несколько озадачилась. Тем более, что такое преобразование есть только у QDir, но не у QFile (впрочем, тут можно понять), не у QFileInfo.

....

Вылезла ещё такая неприятность: какие-то методы возвращают имя устройства в виде маленькой буквы, а какие-то в виде большой... Вобщем, сравнивать имена файлов в виде строк даже внутри одной программы дурное занятие.
И что делать?

Мне приходит имая файла и некоторая информация о нём, которую надо отображать в таблице. Я считала, что имя файла вполне подходит для поиска нужной строки, выходит - нет...
Iron Bug
тоже использую юниксовский формат везде. в кроссплатформе это особенно удобно.
венда понимает и такие пути. и не надо лишнего экранирования обратного слэша.
Анна
я сделала замену везде на линуксовый разделитель. Вылезла другая проблема. В одних путях устройство маленькой буквой обозначается, а в других с большой.
Litkevich Yuriy
А я вообще никогда не использую QDir::separator(), всегда в виде строки добавляю:
"/"
и всё, а когда нужно получить форму для текстового сравнения делаю приведение явно:
QString path = QDir::cleanPath ( fooPath )
path = QDir::toNativeSeparators (path)

А вообще предпочитаю не использовать строки для сравнения, т.к. путь может быть абсолютным ил относительным, и т.п.
Анна
И что же делать в моём случае?

Из всего, что мне приходит, для точного определения строки в таблице, я могу использовать только имя файла и полным путём (собственно на том, что полный путь до файла всегда уникален и строилась вся задумка).

Слеши теперь не проблема, а вот большая и маленькая буквы уже вынуждают извращаться.
Выходит, мне в таблице нужно или хранить QFile, что как-то нелепо, или QFileInfo, или городить кучу преобразований, чтобы привести строки с путём к единому виду?

В общем, маленький классик, выводящий информацию в табличку, начинает превращаться в какого-то монстра.
Iron Bug
обычно сравнение строк имеет параметр не учитывать регистр.
в Qt это QString::compare(a, b, Qt::CaseInsensitive) (google всё быстро находит).
Анна
Угу, но тот же гугль нам сообщает, что в Линуксе регистр в именах файлов имеет значение, так что CaseInsensitive не катит.

Я нашла "виновника торжества"! QFileInfo::absoluteFilePath() возвращает строку, где устройство указано с большой буквы, подобные же функции у других классов возвращают маленькую букву. Буду поступать, как нормальные герои.
Majestio
Анна, не забывай, что нормальные герои еще учитывают возможное наличие хард-линков.
А при сравнении можешь получить совсем не геройский результат ... (даже в венде есть точки соединения)!
Анна
Это не мой случай.
Мне строка с путём к файлу приходит извне, с компа,который может быть под виндой, а может быть и под линуксом . В принципе, моей программе абсолютно наплевать, что ей приходит в строке, лишь бы она могла работать уникальным ключом. Просто так совпало, что приходят пути к файлу (чем не уникальный ключ!), и обнаружилось, что пути к одному и тому же файлу выглядят по-разному.

Цитата
(даже в венде есть точки соединения)!

Ну, если мой партнёр умудрится за один и тот же сеанс прислать мне строки с разными путями до одного и того же файла, я с этим в любом случае ничего поделать не смогу - будет в таблице несколько строк об одном и томже.

Просто, полезно знать, что если в QFileInfo передали полный путь к файлу (безо всяких изысков), то QFileInfo::absoluteFilePach(), вернёт строку , в общем случае, не равную переданной.

QString addPath = QApplication::applicationDirPath();   // addPath будет "e:/My/Path"
QFileInfo info(appPath);
info.absoluteFilePath();   // эта функция вернёт "E:/My/Path"
Majestio
Цитата(Анна @ 22.11.2013, 12:04) *
Мне строка с путём к файлу приходит извне, с компа,который может быть под виндой, а может быть и под линуксом

Ну тогда и алгоритм обработки простейший:
1) Строку собираем, если надо, используя '/'
2) Если первый символ строки '/' - это юних и ничего не делаем
3) Иначе все символы - в прписные, и замену всех '/' на '\'
4) Потом сравнения
Iron Bug
Цитата(Анна @ 22.11.2013, 11:41) *
Угу, но тот же гугль нам сообщает, что в Линуксе регистр в именах файлов имеет значение, так что CaseInsensitive не катит.

ну, как вопрос был задан - так я на него и ответила.
естественно, что в никсах "размер имеет значение". но и юзер не просто так набивает данные, а с учётом регистра. если промахнулся - не будет совпадения. а если юзер явно хочет сравнение без регистров, то он должен понимать, что делает.
и да, таки в никсах есть хард и софт линки. в венде такого вообще нет. точнее, есть в NTFS, но в венде это реализовано только на уровне системы и используется в серверах, а юзер этим не пользуется и часто даже не подозревает.


Цитата(Majestio @ 22.11.2013, 17:15) *
Если первый символ строки '/' - это юних и ничего не делаем

да и венда спокойно такие пути кушает, как относительные. а вот относительно чего - это уже смотря как софт это интерпретирует.
Majestio
Iron Bug,

Цитата(Iron Bug @ 22.11.2013, 16:19) *
да и венда спокойно такие пути кушает, как относительные. а вот относительно чего - это уже смотря как софт это интерпретирует.


Я написал первым пунктом "1. Строку собираем, если надо, используя '/'" - а это значит, что путь к п.2 становится абсолютным.


Цитата(Iron Bug @ 22.11.2013, 16:19) *
в венде такого вообще нет. точнее, есть в NTFS, но в венде это реализовано только на уровне системы и используется в серверах, а юзер этим не пользуется и часто даже не подозревает.

Зависит от юзера. Имеея NTFS и утилиты Марка Руссиновича (junction), юзер может творить чудеса. Вот я творю :lol:
Litkevich Yuriy
Лучше сразу определится, имеем ли мы дело с именем файла или какой-то произвольной строкой.
Если с именем файла, то все манипуляции выполняем с помощью соответствующих классов (QDir, QFile, QFileInfo) они сам разрулят все регистры слэши и т.п.).
Если произвольная строка, то тогда и обработка другая.
Анна
Цитата(Iron Bug @ 22.11.2013, 16:19) *
ну, как вопрос был задан - так я на него и ответила.
естественно, что в никсах "размер имеет значение". но и юзер не просто так набивает данные, а с учётом регистра. если промахнулся - не будет совпадения. а если юзер явно хочет сравнение без регистров, то он должен понимать, что делает.

Не спорю, но согласитесь, что если возникает необходимость сравнить абсолютные пути к файлам, то единообразие кода для никсов и винды пропадает. Это особенно обидно, что на отправляющей стороне пользователь ничего руками не трогает, просто абсолютный путь самой программой, вернее несколькими программами, берётся от разных источников: из QFile, из диалога выбора файлов, из QFileInfo...


Цитата(Litkevich Yuriy @ 23.11.2013, 15:26) *
Лучше сразу определится, имеем ли мы дело с именем файла или какой-то произвольной строкой.
Если с именем файла, то все манипуляции выполняем с помощью соответствующих классов (QDir, QFile, QFileInfo) они сам разрулят все регистры слэши и т.п.).
Если произвольная строка, то тогда и обработка другая.

Вот об этом-то и шла речь. Для моей стороны приходит строка, которая имеет формат полного пути к файлу на каком-то другом компе. QFileInfo организует маленькую подствау в виде обозначения устройства с большой буквы в абсолютном пути, в то время, как QDir и QFile возвращают маленькую букву при аналогичном запросе.

Думала, что можно обойти проблему, прогоняя все строки через QFileInfo, тоже получилось не совсем корректно - к линуксовым путям добавляется текущее устройство, если моя программа работает под виндой; для сравнения строк, конечно, такой вариант подходит
, но при выводе на экран, возникает недоумение.
Iron Bug
единого формата путей для венды и никсов нет. тут ничего не поделать.
как вариант, можно использовать boost::filesystem. там множество функций, специально заточенных про замену слэшей и прочее такое, чтобы повысить переносимость кода.
Анна
Я сделала компромисное решение. Для вывода на экран (DisplayRole) кладу то, что присылают, а для поиска в UserRole кладу эту же строку, пропущенную для едионобразия через QFileInfo.

Цитата(Iron Bug @ 25.11.2013, 17:51) *
можно использовать boost::filesystem

Давно интересуюсь этими библиотеками (в Хакере постоянно проскакивают ), но количество информации, которую надо переварить, да ещё и на английском, меня повергает в уныние. Времени не хватает.
Iron Bug
при программировании на С++ имеет смысл обратить внимание на boost.
boost - не просто кроссплатформенная библиотека. это полигон стандартизации С++. то есть, там отрабатываются будущие стандатные библиотеки С++. после обкатки в boost'е, библиотеки переходят в стандарт.
документация там хорошая(хотя и на английском). плюс множество примеров.
на русскую документацию надеяться не стоит. программист должен свободно читать техническую литературу на английском. это просто факт. иначе - оставание от технологий. потому что переводы отстают на много лет.
Litkevich Yuriy
Цитата(Анна @ 26.11.2013, 11:11) *
но количество информации, которую надо переварить, да ещё и на английском, меня повергает в уныние. Времени не хватает.
у нас на форуме есть раздел посвещённый Boost-у.
Да и Iron Bug в нём ориентируется, как у себя дома, можно поспрашивать если что-то не понятно.
Анна
Цитата(Litkevich Yuriy @ 26.11.2013, 13:46) *
Да и Iron Bug в нём ориентируется, как у себя дома, можно поспрашивать если что-то не понятно.

Ну, уж что что, а спрашивать я умею, вам ли это не знать! ;)
Хотя, если честно, очень часто не хватает базовой информации. Придумаешь что-нибудь классное, а потом оказывается, что это велосипед, к тому же из 19 века. Обидно, вроде бы и институт закончила по этой специальности, но на деле самоучка, так как ООП у нас только-только начали преподавать.

... Совсем оффтоп начался.
Алексей1153
Цитата(Iron Bug @ 21.11.2013, 18:49) *
тоже использую юниксовский формат везде. в кроссплатформе это особенно удобно.
венда понимает и такие пути. и не надо лишнего экранирования обратного слэша.

тоже везде прямой слеш использую. Но есть момент, где он не прокатывает: стандартное виндовое окно диалога "сохранить файл"- если там вписать путь со слешами, то не понимает. Обратные - понимает
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Форум IP.Board © 2001-2024 IPS, Inc.