Как указать путь к файлу в c
Перейти к содержимому

Как указать путь к файлу в c

Как указать путь к файлу в c

У меня было так

Я открывал этот файл, при необходимости он создавался — и все было бы хорошо, но

И все больше файл открываться не хочет! (и не создается) Я больше ничего не менял в программе — значит виноваты эти строки. Подскажите, плиз.

От: LuciferMoscow
Дата: 03.03.06 10:19
Оценка:
От: HiSH http://m0riarty.ya.ru
Дата: 03.03.06 10:21
Оценка: 2 (2)

Здравствуйте, AlexDav, Вы писали:

AD>
AD>Я открывал этот файл, при необходимости он создавался — и все было бы хорошо, но
AD>Я заменил на
AD>
AD>И все больше файл открываться не хочет! (и не создается) Я больше ничего не менял в программе — значит виноваты эти строки. Подскажите, плиз.

А зачем двойные слеши? Должно быть или «c:\\program files\\. «, или «c:/program files/. «

От: rg45
Дата: 03.03.06 10:24
Оценка:

Здравствуйте, AlexDav, Вы писали:

AD>У меня было так

AD>

AD>Я открывал этот файл, при необходимости он создавался — и все было бы хорошо, но

AD>Я заменил на

AD>

AD>И все больше файл открываться не хочет! (и не создается) Я больше ничего не менял в программе — значит виноваты эти строки. Подскажите, плиз.

1. Либо «C://set.ds» либо «C:/set.ds» — двойной слэш — это лишний символ в строке, хотя большинством фунций «глотается» нормально.
2. Чтобы ответить, все таки, что не так, нужно видеть, как используется эта строка.
Вполне возможно, что проблема в пробелах, которые присутствуют во втором варианте и которых нет в первом.

От: AlexDav
Дата: 03.03.06 10:27
Оценка:

Здравствуйте, HiSH, Вы писали:

HSH>А зачем двойные слеши? Должно быть или «c:\\program files\\. «, или «c:/program files/. «

Так вот зачем эти странные палочки?! И точно работает

От: rg45
Дата: 03.03.06 10:27
Оценка:

R>1. Либо «C://set.ds» либо «C:/set.ds» — двойной слэш — это лишний символ в строке, хотя большинством фунций «глотается» нормально.

Написал не то, что хотел, надо было так:

От: RevSegment
Дата: 03.03.06 10:34
Оценка:

Здравствуйте, AlexDav, Вы писали:

AD>У меня было так

AD>

AD>Я открывал этот файл, при необходимости он создавался — и все было бы хорошо, но

AD>Я заменил на

AD>

AD>И все больше файл открываться не хочет! (и не создается) Я больше ничего не менял в программе — значит виноваты эти строки. Подскажите, плиз.

А так не пробовал?
«c:\\Folder One\\Folder Two\\file.ext»

От: AlexDav
Дата: 03.03.06 10:46
Оценка:

Здравствуйте, LuciferMoscow, Вы писали:

LM>Попробуй путь взять в кавычки. У тебя есть пробел в пути к файлу
LM>

я попробовал такой путь «C:/Data/set.ds» работает — т.е. ты (можно на ты?) это пробелы, но как ты написал тоже не прокатывает?? Что Делать.

От: ekamaloff
Дата: 03.03.06 10:50
Оценка:

Здравствуйте, AlexDav, Вы писали:

AD>я попробовал такой путь «C:/Data/set.ds» работает — т.е. ты (можно на ты?) это пробелы, но как ты написал тоже не прокатывает?? Что Делать.

Покажи где ты ее используешь и на каком варианте строки ты сейчас остановился.

От: AlexDav
Дата: 03.03.06 11:07
Оценка:

Здравствуйте, ekamaloff, Вы писали:

E>Покажи где ты ее используешь и на каком варианте строки ты сейчас остановился.

Прошу прощения за MFC

От: AlexDav
Дата: 03.03.06 13:35
Оценка:

Хотите верти — хотите нет, но

просто начала работать и все! Зуб даю кроме этой строчки в программе ничего не менял!

От: rg45
Дата: 03.03.06 13:39
Оценка: 4 (1)

Здравствуйте, AlexDav, Вы писали:

AD>Хотите верти — хотите нет, но
AD>

AD>просто начала работать и все! Зуб даю кроме этой строчки в программе ничего не менял!

Впервоначальном варианте у тебя все слэши были двойные. А петерь вместо них одинарные бэк-слэши (литерал «\\» автоматически преобразуется в одинарный бэк-слэш). Значит, какая то из функций не могла вынести присутствия лишних символов в строке.

От: i-maverick
Дата: 03.03.06 13:48
Оценка:

Здравствуйте, AlexDav, Вы писали:

AD>Хотите верти — хотите нет, но
AD>

AD>просто начала работать и все! Зуб даю кроме этой строчки в программе ничего не менял!

Тебе ведь так и сказали — нужно либо одинарный прямой слэш, либо двойной обратный.
Ты бы хоть разобрался, зачем тут двойной слэш, чтоб больше не путаться.

От: AlexDav
Дата: 03.03.06 13:54
Оценка:

Здравствуйте, i-maverick, Вы писали:

IM>Тебе ведь так и сказали — нужно либо одинарный прямой слэш, либо двойной обратный.
IM>Ты бы хоть разобрался, зачем тут двойной слэш, чтоб больше не путаться.

Ну ладно ругать то сразу — никто же не сказал что надо весь проект перекомпилить что бы подхватил эту дефайну

Пути к файлам

Казалось бы — что может быть проще, чем работа с файлами в C++. Но отдельные личности поражают своей находчивостью в поиске наихудшего подхода.
Не стоит делать так:

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

Если кратко, то использование не ASCII символов в строковых константах char может привести к печальным последствиям. Я уже обсуждал этот вопрос в посте о кодировках. В данном случае название файла напрямую зависит от кодировки исходника и если кто-то напишет подобное в utf-8, в windows-xp можно получить файл с запрещенными символами, с которым невозможно будет ничего сделать. Можно не использовать не ASCII. Но вы же не можете запретить это пользователю (потоку или БД из которого получен путь). Это же дискриминация по национальному признаку! Срочно исправляемся:

std::wstring filepath= L»C:\тест»
std::ofstream file(filepath.c_str());

Несведущие в стандарте пользователи Visual Studio могут успокоиться, пока нужда не заставит сменить компилятор (точнее STL). И тут начинается…

Дело в том, что текущий стандарт и не предполагает его наличия (не трогаем пока C++0x). Это в чистом виде энтузиазм мелкомягких.

Что же делать?

  • Использовать стороннюю библиотеку для работы с путями (к примеру boost::filesystem)
  • Использовать std::locale
  • Придумывать свой

С третьим вариантом все ясно, с первым тоже ничего сложного:

  1. #include <boost/filesystem/fstream.hpp>
  2. #include <string>
  3. namespace fs = boost :: filesystem ;
  4. int main ( int argc, char * argv )
  5. <
  6. std :: wstring filepath ( L «C:\тест» ) ;
  7. fs :: ofstream ( filepath ) ;
  8. return 0 ;
  9. >

А вот по поводу второго у тех, кто не учил матчасть, могут возникнуть проблемы.

Пользуемся std::locale

Отступление.
Огорчу пользователей mingw: вам придется использовать стороннюю реализацию STL (к примеру stlport) из-за отсутствия в родной правильной поддержки локализации. А точнее, функция std::locale(«») всегда возвращает std::locale(«C»), что бы там у вас не стояло. Тот же stlport лишен подобного недостатка. О том как слепить связку mingw+stlport+boost я отписал тут.

Все что нам нужно сделать это следовать простым правилам — с не ASCII работаем в «расширенном» виде. То есть, читаем путь в std::wstring, используя соответствующим образом локализованный поток, а при использовании, сужаем по пользовательской локализации. Эта идея основана на том, что раз пользователь правильно видит символы своего языка в консоли, то его пользовательская локализация знает в какую кодировку надо сузить широкую строку, чтобы правильно интерпретировать путь. Итак, пример. Допустим у нас есть файл в кодировке cp866, содержащий путь. Нам необходимо создать файл по этому пути. Что мы делаем:

  1. #include <iostream>
  2. #include <string>
  3. #include <fstream>
  4. #include <locale>
  5. #include <memory>
  6. #include «facet/codecvt/codecvt_cp866.hpp»
  7. /**@brief Сужает широкую строку, используя локализацию loc
  8. @return Возвращает суженную строку или пустую суженную строку, в
  9. случае. если возникла ошибка*/
  10. std :: string narrow ( const std :: wstring & wstr, const std :: locale & loc )
  11. <
  12. const size_t sz = wstr. length ( ) ;
  13. if ( sz == 0 )
  14. return std :: string ( ) ;
  15. mbstate_t state = 0 ;
  16. char * cnext ;
  17. const wchar_t * wnext ;
  18. const wchar_t * wcstr = wstr. c_str ( ) ;
  19. char * buffer = new char [ sz + 1 ] ;
  20. std :: uninitialized_fill ( buffer, buffer + sz + 1 , 0 ) ;
  21. typedef std :: codecvt < wchar_t , char , mbstate_t > cvt ;
  22. cvt :: result res ;
  23. res = std :: use_facet < cvt > ( loc ) . out ( state, wcstr, wcstr + sz, wnext,
  24. buffer, buffer + sz, cnext ) ;
  25. std :: string result ( buffer ) ;
  26. if ( res == cvt :: error )
  27. return std :: string ( ) ;
  28. return result ;
  29. >
  30. /**@brief Расширяет строку, используя локализацию loc
  31. @return Возвращает расширенную строку или пустую расширенную строку, в
  32. случае, если возникла ошибка.*/
  33. std :: wstring widen ( const std :: string & str, const std :: locale & loc )
  34. <
  35. const size_t sz = str. length ( ) ;
  36. if ( sz == 0 )
  37. return std :: wstring ( ) ;
  38. mbstate_t state = 0 ;
  39. const char * cnext ;
  40. wchar_t * wnext ;
  41. const char * cstr = str. c_str ( ) ;
  42. wchar_t * buffer = new wchar_t [ sz + 1 ] ;
  43. std :: uninitialized_fill ( buffer, buffer + sz + 1 , 0 ) ;
  44. typedef std :: codecvt < wchar_t , char , mbstate_t > cvt ;
  45. cvt :: result res ;
  46. res = std :: use_facet < cvt > ( loc ) . in ( state, cstr, cstr + sz, cnext,
  47. buffer, buffer + sz, wnext ) ;
  48. std :: wstring result ( buffer ) ;
  49. delete [ ] buffer ;
  50. if ( res == cvt :: error )
  51. return std :: wstring ( ) ;
  52. return result ;
  53. >
  54. int main ( int argc, char * argv [ ] )
  55. <
  56. //Пусть имеется cp866 файл с путем
  57. std :: ofstream ofile ( «input.txt» , std :: ios :: binary ) ;
  58. if ( ! ofile )
  59. <
  60. std :: cerr << «Error open file» << std :: endl ;
  61. return 0 ;
  62. >
  63. std :: ostreambuf_iterator < char > writer ( ofile ) ;
  64. * ( writer ) = 0xe2 ; // т
  65. * ( ++ writer ) = 0xa5 ; // е
  66. * ( ++ writer ) = 0xe1 ; // с
  67. * ( ++ writer ) = 0xe2 ; // т
  68. ofile. close ( ) ;
  69. //Читаем путь
  70. std :: locale cp866 ( std :: locale ( ) , new codecvt_cp866 ) ;
  71. std :: wifstream ifile ( «input.txt» , std :: ios :: binary ) ;
  72. ifile. imbue ( cp866 ) ;
  73. std :: wstring wpath ;
  74. ifile >> wpath ;
  75. ifile >> wpath ;
  76. ifile. close ( ) ;
  77. //Создаем по этому пути файл
  78. std :: ofstream file ( narrow ( wpath, std :: locale ( «» ) ) . c_str ( ) ) ;
  79. file << «testing» ;
  80. file . close ( ) ;
  81. >

Фасеты можно взять на git-hub.

SUMMARY

Если вы используете путь из argv — можете смело с ним работать (пользователь знает что делает). Из «внешней среды» путь получайте с помощью правильно локализованного потока как широкую строку и сужайте ее с помощью пользовательской локализации.

С вопросами можно обращаться:
0. К стандарту
1. К книге Страуструпа (3-е специальное издание, приложение)
2. К документации по mingw.
3. К документации по boost.
4. К посту о фасетах и кодировках.

Всем прямых путей!

UPD: Ну и как правильно заметили Gorthauer87,Migun и naryl в комментариях, обратные слеши и платформо-специфичные пути тоже плохая идея.

Как прописать путь к txt-файлу?

Как указать путь к файлу который находится в той же директории что и сам проект, то есть чтобы можно было этот файл и проект перекинуть в другое место и он все таки находил этот файл не меняя пути к нему? FileStream f = new FileStream(@»C:\Users\User\Desktop\TaskOne\input.txt», FileMode.Open, FileAccess.Read);

Для это вам нужно оперировать двумя параметрами проекта Visual Studio:

  • Working directory
  • Output path

Возьмём для примера проект консольного приложения.

введите сюда описание изображения

Параметр Working directory определяет, какая рабочая директория будет задана по умолчанию текущему процессу консольного приложения.
Если этот параметр пустой, то рабочей директория будет директория из которой запущен exe файл. А его место создание определяется параметром проекта Output path :

введите сюда описание изображения

По умолчанию это поддиректорий текущего проекта bin\Debug.

Таким образом, в данном случае, чтобы обратиться к файлу input.txt находящемуся в директории проекта нужно обратиться на два директория выше, т.е. использовать «..» в пути файла:

Так как пути все указываются относительно директории проекта, то при переносе папки проекта изменять пути не надо будет.

Директорией проекта является директория, в которой лежит файл проекта .csproj .

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *