C++を勉強中なのですが、欲しかった機能をC++で書けなかったのでC#にちょっと手を出してしまっています。
VC++ではテキストファイルなどのリソースはプロジェクトの見かけ上のフォルダ(実際は.cppと同一のフォルダ)にあるとファイル名だけで参照してくれますが、VC#は.csと同一フォルダに置いておいてもファイル名だけではダメでフルパスなどを要求されます。
初心者にとってはなんか面倒だなと思いますが、後発のVC#がこのような仕様になっているということは何かデメリットがあるからだと思うのですが、これはどのようなことを考えてこのような仕様になっているのでしょうか?
よろしくお願い致します。
C#に手を出してしまった理由は、IDManagerというパスワード管理ソフトを使っているのですがIEに上手く張り付かないので(firefoxはOK)あるサイトにIEでログインするアプリをC++(WinHTTPなど)で作ろうと思ったのですが全体的な知識が不足している為に上手く作れませんでした。
検索の途中でC#でグーグルの検索窓に値を入れるコードを見つけたのでそれを利用して作ったのですが、あまりに簡単に短いコードで出来てしまったので二股かけている状態です。
VC++とVC#のテキストファイルなどの参照の違いについて
Re: VC++とVC#のテキストファイルなどの参照の違いについて
どのクラスを使ってファイルを読み込もうとしているのか書いてないけど、
絶対パスでも相対パスでも動作するように作られてることが多いと思う。
豆電球さんが試したときはファイルの置き場所が間違ってたんじゃないかな
絶対パスでも相対パスでも動作するように作られてることが多いと思う。
豆電球さんが試したときはファイルの置き場所が間違ってたんじゃないかな
Re: VC++とVC#のテキストファイルなどの参照の違いについて
実行プロセスには「作業ディレクトリ(カレントディレクトリ)」というものが存在します。相対パスをプログラム中に書いていた場合、その作業ディレクトリからの相対パスと認識されます。
実行ファイルを直接起動した場合等は、基本的にその実行ファイルが置いてある位置が作業ディレクトリとして実行されます。
VC++上から実行した場合には、基本的に「プロジェクトファイルが置いてあるディレクトリ」が作業ディレクトリとして設定されます。もちろんこれはプロジェクトの設定から変更することが可能です(プロジェクトのプロパティ -> 構成プロパティ -> デバッグ内に設定項目が存在します)。
VC#の場合は分かりませんが、私が試しに作成した空のプロジェクトでは、この作業ディレクトリの設定は空でした。その際は、VC++でもそうだったと思いますが、ビルドして出力される実行ファイルの場所が作業ディレクトリとして開始されます(プロジェクトファイルの場所/bin/Debug(Release)/ですね)。
なのでVC#でもVC++と同様に作業ディレクトリを設定するか、出力された実行ファイルが置かれる場所を基準に外部リソースを配置することで、望んだ結果が得られるのではないかと思われます。
なお「プロジェクトの見かけ上のフォルダ(実際は.cppと同一のフォルダ)」というのはよく分かっておりません。
実行ファイルを直接起動した場合等は、基本的にその実行ファイルが置いてある位置が作業ディレクトリとして実行されます。
VC++上から実行した場合には、基本的に「プロジェクトファイルが置いてあるディレクトリ」が作業ディレクトリとして設定されます。もちろんこれはプロジェクトの設定から変更することが可能です(プロジェクトのプロパティ -> 構成プロパティ -> デバッグ内に設定項目が存在します)。
VC#の場合は分かりませんが、私が試しに作成した空のプロジェクトでは、この作業ディレクトリの設定は空でした。その際は、VC++でもそうだったと思いますが、ビルドして出力される実行ファイルの場所が作業ディレクトリとして開始されます(プロジェクトファイルの場所/bin/Debug(Release)/ですね)。
なのでVC#でもVC++と同様に作業ディレクトリを設定するか、出力された実行ファイルが置かれる場所を基準に外部リソースを配置することで、望んだ結果が得られるのではないかと思われます。
なお「プロジェクトの見かけ上のフォルダ(実際は.cppと同一のフォルダ)」というのはよく分かっておりません。
Re: VC++とVC#のテキストファイルなどの参照の違いについて
Idraさん、djannさん、ありがとうございます。
そして、情報不足で申し訳ありません。
「プロジェクトの見かけ上のフォルダ(実際は.cppと同一のフォルダ)」(説明不足で申し訳ありません)
VC++の場合、ソリューションエクスプローラに「Source Files」「Resource Files」というフォルダがあり、cppファイルは「Source Files」に入れて、テキストファイルなどは「Resource Files」に入れているのですが、ウィンドウズのエクスプローラで表示されるフォルダではなく、ソリューションエクスプローラだけのフォルダのようで実際には(ウィンドウズのエクスプローラ上では)同じフォルダにファイルが置かれています。
この.cppと同じフォルダにテキストファイル
.csと同じフォルダにテキストファイル
という状態でVC++とVC#の設定を変えたのは、後発のVC#の方がこれが良い設定なのだという事で変更したのかなと思ってしまいました。
しかし、お二人の回答をみて特にデメリットがあってという事ではないようですので、ファイル指定が多い場合はプロジェクトにパスを設定しようと思います。
ありがとうございました。
コードは下記のようなものです。
C#
C++
そして、情報不足で申し訳ありません。
「プロジェクトの見かけ上のフォルダ(実際は.cppと同一のフォルダ)」(説明不足で申し訳ありません)
VC++の場合、ソリューションエクスプローラに「Source Files」「Resource Files」というフォルダがあり、cppファイルは「Source Files」に入れて、テキストファイルなどは「Resource Files」に入れているのですが、ウィンドウズのエクスプローラで表示されるフォルダではなく、ソリューションエクスプローラだけのフォルダのようで実際には(ウィンドウズのエクスプローラ上では)同じフォルダにファイルが置かれています。
この.cppと同じフォルダにテキストファイル
.csと同じフォルダにテキストファイル
という状態でVC++とVC#の設定を変えたのは、後発のVC#の方がこれが良い設定なのだという事で変更したのかなと思ってしまいました。
しかし、お二人の回答をみて特にデメリットがあってという事ではないようですので、ファイル指定が多い場合はプロジェクトにパスを設定しようと思います。
ありがとうございました。
コードは下記のようなものです。
C#
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CS_FileOperation
{
class c1
{
static void Main(string[] args)
{
FileStream reader = null;
try
{
reader = new FileStream(@"c:\XXXXXXXXXXXXXXXXXXXXXXX\CS_FileOperation\data1.txt", FileMode.Open);
}
catch (Exception)
{
}
finally
{
if (reader != null)
reader.Close();
}
Console.ReadKey(true);
}
}
}
#pragma warning(disable:4996)
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <sstream>
int main()
{
std::string filename("data1.txt");
std::ifstream ifs(filename, std::ios::in);
if (ifs.fail()){ printf("fail\n"); return -1; }
ifs.close();
std::system("pause");
return 0;
}
Re: VC++とVC#のテキストファイルなどの参照の違いについて
解決済みとされていますが,この場合だと,C#に関しては別解があります。
まず,data1.txtのプロパティで「出力ディレクトリにコピー」を「常にコピーする」若しくは「新しい場合はコピーする」に設定しておきます。
すると,ビルドプロセス中で自動的にファイルがコピーされます。
そして,ファイルを開くときは実行ファイルのパスを元に指定します。
この方法であれば,ディレクトリ構成が変わっても問題なく実行できます。
まず,data1.txtのプロパティで「出力ディレクトリにコピー」を「常にコピーする」若しくは「新しい場合はコピーする」に設定しておきます。
すると,ビルドプロセス中で自動的にファイルがコピーされます。
オフトピック
プロジェクトのフォルダ中に入れてこの設定にすると,フォルダ構成ごとコピーされます
この方法であれば,ディレクトリ構成が変わっても問題なく実行できます。
オフトピック
絶対パスを記述する方法は特定の環境だけでしか実行できなくなってしまうので,勉強段階であってもできるだけ避けた方がよいです。
下記の様に,システムから情報を得て,得られたディレクトリからの相対パスを絶対パスに変換し,それを使う必要があります。
下記の様に,システムから情報を得て,得られたディレクトリからの相対パスを絶対パスに変換し,それを使う必要があります。
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CS_FileOperation
{
class c1
{
static void Main(string[] args)
{
// CS_FileOperation.c1クラスを含むアセンブリのディレクトリにあるdata1.txtを読み込む場合
// 実行開始ファイルのパスであるなら,typeof(c1).Assemblyの代わりにSystem.Reflection.Assembly.GetEntryAssembly()を利用。
using (var stream = File.Open(Path.Combine(Path.GetDirectoryName(typeof(c1).Assembly.Location), "data1.txt"))
{
// 処理本体。
// catchする必要がなければtry-catch-finallyよりもusingを推奨。
}
Console.ReadKey(true);
}
}
}
Re: VC++とVC#のテキストファイルなどの参照の違いについて
YuOさん、ありがとうございます。
使ったことの無いものがいくつかあったのでググって弄っていました。
単純にworking directoryを設定せずに、この様な変化に強いコードを推奨しているのかもしれませんね。
ググっている中で、System.IO.Path系のものも色々あって面白かったです。
ありがとうございました。
使ったことの無いものがいくつかあったのでググって弄っていました。
単純にworking directoryを設定せずに、この様な変化に強いコードを推奨しているのかもしれませんね。
ググっている中で、System.IO.Path系のものも色々あって面白かったです。
ありがとうございました。