ファイルの中身をすべてメモリに保存する方法

[戻る]
もも 2005/05/25(水) 17:41:36
こんにちわ。

CFileのOpenでファイルを開いて、
そのファイルの中身をすべて文字列として保存しようと思っています。
Openはうまくいくのですが、
なぜかReadでファイルの中身が取得できません。

CFile cfIni;
char buff[512];
if(cfIni.Open(m_strInifilePath,
    CFile::modeReadWrite | CFile::typeBinary | 
     CFile::shareExclusive) == TRUE)
{
 cfIni.SeekToBegin();
 cfIni.Read(buff,512);
}

ファイルの中身を文字列としてうまく取得する方法はないでしょうか?

よろしくお願いします。

Blue 2005/05/25(水) 18:00:44
どのように取得できた出来ないをはんだんしていますか?
バイナリモードで読み込んでいますので当然途中に’\0’が入ることもあります。

それと気になった点

>if(cfIni.Open(m_strInifilePath,
>    CFile::modeReadWrite | CFile::typeBinary | 
>     CFile::shareExclusive) == TRUE)

CFile::typeBinaryはMSDNに派生クラスで使いますとあります。
CFileで開けば必ずバイナリで開いていますので指定する必要はありません。

BOOL型の戻り値に対して == TRUE とするのはよくありません。
詳しくは
(int型変数の評価)
http://rararahp.cool.ne.jp/cgi-bin/lng/vc/vclng.cgi?print+200505/05050084.txt
で議論になっているので参考に。

それと、一応try〜catchで囲んでCFileExceptionを捕まえるような処理を入れたほうが
無難だと思います。

>ファイルの中身を文字列として
ということならば CFileの派生クラスのCStdioFileを使われてはどうでしょうか?

reshia 2005/05/25(水) 20:16:03
if( cfIni.Open(....) == TRUE )
これがダメです。
CFile::Openの仕様では、ファイルのオープンに失敗すると「0」を返し
成功した場合、「0以外」を返します。TRUEを返すわけではありませんので、
「 cfIni.Open(....) == TRUE 」は成り立たないので
「cfIni.Read(buff,512);」は呼ばれていない可能性があります。

本当に、このReadが呼ばれているのかを確かめてください。

##テストした方法を示します。VC2003です。
プロジェクト:「Win32コンソールプロジェクト」
設定:サポートの追加の項で「MFC」にチェック
以下のコードを追加
//----------------------------------------
// TODO: アプリケーションの動作を記述するコードをここに挿入してください。
CFile cfIni;
char buff[512];
int readsize;
if(cfIni.Open(m_strInifilePath, CFile::modeReadWrite | CFile::typeBinary |
CFile::shareExclusive) == TRUE)
{
    cfIni.SeekToBegin();
    cfIni.Read(buff,512);
    _tprintf("%s\n", buff);
}
//----------------------------------------
として確かめました。

ファイルサイズが512バイト以下では、上手く動作しませんのであしからず。
あと、この場合「cfIni.SeekToBegin();」はなくても動きます。

Blue 2005/05/25(水) 23:25:33
>ファイルサイズが512バイト以下では、上手く動作しませんのであしからず。
はどんな時、何がうまくいきませんでした?
(そんなことないと思うのですが・・・VC7からは動かないのかなぁ。。。)

一応全てのExceptionをcatchできるようにコンストラクタでオープンしてみたのを
載せておきます。
# ファイル名はテキトーですが。

try
{
    CFile fileInput( "test.txt", CFile::modeReadWrite | 
CFile::shareExclusive );
    TCHAR szBuff[ 512 ] = { 0 };
    fileInput.Read( szBuff, sizeof( szBuff ) );
    cout << szBuff << endl;
    fileInput.Close();
}
catch ( CFileException* ex )
{
    TCHAR szCause[ 255 ];
    ex->GetErrorMessage( szCause, sizeof( szCause ) );
    ex->Delete();
    cerr << szCause << endl;
}

ちなみに、私の環境はWinXp SP2のVC6 SP6 です。

reshia 2005/05/26(木) 00:45:18
>どんな時、何がうまくいきませんでした?
どうやら、CFile::Readは、指定されたサイズ分きっちり読み込んでくれますが、
その後にナル文字は入れてくれません。
なので、printfでの出力には、いつもの「フフフフフ」が出てきてしまいます。
std::coutでも同じ状態です。

上手くやろうと思うと、
CFile::Readの返り値が「バッファに転送されたバイト数」ですから、
(ちょっと上のプログラムに残骸が残ってしまっていたのですが)
char buff[513];
int readsize = cfIni.Read(buff,512);
などとして、
buff[readsize] = '\0';
とする必要があるみたいです。

reshia 2005/05/26(木) 00:48:50
あ、すみません。
だから、512バイト以下だろうが以上だろうが、
最初に私が提示したプログラムはうまくいきません。

επιστημη 2005/05/26(木) 13:02:13
stream系を使った方が楽じゃないすか?

/*
 * readmyself.cpp
 */
#include <fstream>
#include <sstream>
#include <iostream>

int main() {
  std::ifstream in("readmyself.cpp");
  std::ostringstream out;
  out << in.rdbuf(); // 一気に全部読む
  std::cout << '[' << out.str() << ']';
  return 0;
}

古いスレッドには追加発言できません。