Как стать автором
Обновить

Комментарии 49

Не стоит делать так:

std::string filepath(«C:\тест»);

Потому что escape-сивмола \т не существует.

Надо делать так:

std::string filepath(«C:\\тест»);
Не канонично.

Каноничный вариант std::string filepath(«C:/тест»);
Всё остальное от лукавого.
Прошу прощения, исправил.
важно разделять те кодировки с которыми может работать конкретная платформа и те которые приезжают нам извне(из исходника из сети). вообще то для всей системы стоит держать одну внутреннюю котировку например utf-8 ( в ней же хранить исходники и в ней же передавать данные из сети ). После чего осуществит преобразование из кодировки приехавшей по сети в кодировку конктретной платформы. А иначе вы словите рано или поздно когда вам по сети данные в кодировке про которую конктретная платформа не знает и вот эта строчка std::locale cp1251(std::locale(), new codecvt_cp866) не сработает так как iconv который под этим лежит про cpp866 не слышал даже.

так что std::string filepath(«C:\\тест»); верен и ваш огород не нужен
важно разделять те кодировки с которыми может работать конкретная платформа и те которые приезжают нам извне. вообще то для всей системы стоит держать одну внутреннюю котировку например utf-8

Вообще-то я о том же. Конкретная платформа работает в std::locale(""), а все что извне — преобразуется ручками. Если вы заранее не знаете в каком коде к вам данные извне попадаютт, то встает задача распознавания кодировки, но это уже совсем другая история…
int ds = open( "file.dat", O_CREAT|O_APPEND, S_IREAD|S_IWRITE); 
int wr = 0;
while( size >0 && (wr = write( ds, pdata, size )) >= 0 )
   size -= wr;
close(ds);


Ужас какой-то. От начала до конца.
Многих именно такие вещи отпугивают от C++ :)
Потому, что С++ многогранен и некоторые люди почему-то любят делать простые вещи сложным образом
Тут как раз нет ничего ужасного. Ужас это когда в проекте запрещено использовать буст и все шаблоны приходится писать самому. Что впрочем для С++ программиста только в удовольствие :)
Напомните пожалуйста, по каким причинам можно так не любить буст?
А бог его знает — какая-то идиосинкразия у начальства. Я так этого и не понял.
Скажите спасибо, что автор ещё не стал писать переносимый код, который будет одинаково работать на *nix, mac и «NetBSD на тостере» ©.
Переносимый код обычно как раз лучше выглядит, ибо платформозависимые части четко зашиты в отдельных файлах куда не каждый день лазаешь
Я и имел в виду, что в эти отдельные файлы лучше не лазить. Абстрагироваться от них поскорее и забыть, как страшный сон. Туда же и кульбиты с именами файлов надо выносить.
Ну суть одна и та же. Вообще приложение должно оперировать ресурсами, а не конкретным их представлением.
Не стоит делать так:

> std::string filepath(«C:\\тест»);
> std::ofstream file(filepath.c_str());

Хотя бы потому что не стоит использовать платформо-специфичные пути. А в большинстве случаев пути можно и вообще не хардкодить.

Для чего ещё используются захардкоженные пути если не для указания места складывания конфигов по-умолчанию? А это лучше всего получать библиотекой libxdg-basedir.
Слэши обратные — скорее исключение из правила. Причем, винда, хитрая жопа, понимает как прямые слэши, так и обратные, а вот большинство других систем — только прямые. Так что проще везде использовать прямые.
А вообще файловые операции лучше пускать через обертки (либо свои, либо уже готовые — но не буду советовать буст). На этом уровне можно решить несколько проблем, и вопрос кодировки — только одна из них.
Плюс, при обращении к файлам через однобайтову строку — в Китай/Японии/Корее/etc этот код просто не заработает.
Далеко не все винды — хитрые жопы. И даже более-менее свежие стали такими совсем не сразу.
Хм, а кстати, стало интересно. NT изначально умела, или потом уже прикрутили?
В маках пути двоеточиями разделяются.
Бред… там Unix'овые пути
На маках никогда не работал. Может новые и понимают UNIX-пути. Купился вот на что:

Убить бы хоткеи на хабре.
search.cpan.org/~smueller/PathTools-3.33/lib/File/Spec/Mac.pm
Mac OS (Classic)
ключевое слово — Classic
Маки это и есть Unix'ы, причем сертифицированные
НЛО прилетело и опубликовало эту надпись здесь
То есть, читаем путь в std::wstring, используя соответствующим образом локализованный поток, а при использовании, сужаем по пользовательской локализации. Эта идея основана на том, что раз пользователь правильно видит символы своего языка в консоли, то его пользовательская локализация знает в какую кодировку надо сузить широкую строку, чтобы правильно интерпретировать путь.

У меня на рабочей машине стоит американская локаль, а вот файлы иногда могут иметь в именах кирилические символы — живу то я в Украине. И да, консоль их показывать не умеет, но мне это не критично — я с такими файлами через нее не работаю. ИМХО из всех предложенных способов этот — самый ненадежный и его скорее надо вписывать в «как делать не надо».
И да, консоль их показывать не умеет

И писать на этом языке вы тоже, я так понимаю, не можете. С этим подходом и программа тоже не должна.
Честно говоря, задумался… а логично ли это… и как поступать, если не логично…
Что мешает установить одну системную консоль, а раскладку клавиатуры из другой? Большая часть системы и весь UTF софт будет работать.
Консоль в винде юникодная и умеет показывать любые символы. Проблема в том, что далеко не все символы присутствуют в тех моноширинных шрифтах, которыми пользуется консоль.
И да, консоль их показывать не умеет

И писать на этом языке вы тоже, я так понимаю, не можете. С этим подходом и программа тоже не должна.
Честно говоря, задумался… а логично ли это… и как поступать, если не логично…
Ужас — когда в проекте файлы или папки кто-то создает не с названиями только из английских букв.
Речь-то не только о проекте. Если, к примеру, пользователь какой-нибудь загадочной страны дает на вход программе файл в UTF-8 с путем к файлу, который программа должна изменить/создать/прочитать что делать в общем случае, чтобы решение было переносимым?
Боже, храни .net
Слава богу, в Qt этой проблемы нет.
Проблема высосана из пальца — определяем макрос _T(x), который при включенном юникоде равен L«x», при отключенном — просто «x». (Такой макрос по-моему даже уже определен в студии. А может и нет).
При компиляции на другой платформе\другим компилятором макрос переопределяется под тот префиск (или что-нибудь еще), который нужен для данной платформы.

1 строка кода. Всё.
Вы пост читали? Потоков, работающих с wchar_t в качестве имени файла в стандарте нет.
А Вы комментарий мой читали? Под студией макрос заменится на L«x» — и успешно сработает сделанный «на энтузиазме Microsoft» поток с wchar_t. Под gcc макрос заменится на просто строку и сработает gcc-шный конструктор ofstream. У меня уже 2 проекта так работают — и прекрасно компилируются под Win и Linux.
Пусть надо прочитать путь из файла в UTF-8 и создать по нему файл. Как в этом вам поможет макрос?! Откуда вы знаете в какую кодировку преобразовать путь? Это знает только пользовательская локаль.
Ок, возможно, я погорячился, приводя макрос в качестве решения Вашей задачи — он действительно немного для других целей. Не серчайте.
вообще если уж упомянули boost.filesystem то можно добавить что в нем работа с путями превращатся в сказку

fs::path p("/somepath");

p/=«another_dir»;
и так далее

затем допутсим нужно пройти по всем объектам в папке:
for(fs::directory_iterator it = p.begin();it!=p.end();++it)


или хотите пройти по всем объектам рекурсивно, тогда вместо directory_iterator можно использовать recursive_directory_iterator
:) Ваш QR-код, в иллюстрации, не работает. :)
Спасибо всем за минусы.

Вот так понятнее? —
< :) >     </ :) >
А как быть если путь к файлу надо передать как параметер main — вот тут то и спотыкаешся об 8битную кодировку.
Если путь пришел к вам через аргументы командной строки, можете оперировать им напрямую. Как правило (есть исключения), кодировка аргументов командной строки соответствует кодировке ФС.
Вопрос не в кодировке файловой системы — а втом что фргументы для маин только char**, тоесть 8 бит на символ, если аргумент содержит киррилицу (16бит), ничего кроме крякозябров на вход не прийдет.
Я не понимаю вашего вопроса…

В приложении вы получаете путь как аргумент командной строки. Значение аргумента представлено какой-то кодировкой в windows это скорее всего cp866, в *nix — UTF-8 и в неизменном виде передаете на открытие файла (в ifstream или fopen), чаще всего это будет работать нормально.
Вот как раз так у меня и не получалось, ни разу, если в пути есть русские буквы, то болт, файл не открывался, правда если использовать 16 битную кодировку то все взлетало, но int main(int argv, wchar_t args**) не напишеш, поэтому все рашалось поиском из под уже запущенной программы.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Изменить настройки темы

Истории