質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

91.00%

  • C++

    2937questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

c++ ファイルの分割ロードについて

受付中

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 193

ssssskkkkk

score 3

ファイルの分割ロードについて

c++でファイルの分割ロードを実現したいと考えています。
具体的には、毎フレーム128キロバイトずつ、もしくはまだ読み込めていないサイズの合計が128キロバイト未満であれば、残りサイズを読み込みます。

とある本に書いてあったコードを参考に、以下のようなコードを書いてみました。

Fileクラス

実際に読み込むファイルのデータを保持しています。

#ifndef _FILE_H_
#define _FILE_H_

/*

File.h

*/

#include "Singleton.h"
#include <string>

using namespace std;

class File {

public:

    bool isReady() const;
    int size() const;
    const char* data() const;
    string fileName() const;

    File(const char* fileName);
    ~File() {};

private:

    friend class Loader;

    string mFileName;
    char* mData;
    int mSize;

};

#endif
#include "File.h"

/*

File.cpp

*/

bool File::isReady() const {

    return mData != 0;

}

int File::size() const {

    return mSize;

}

const char* File::data() const {

    return mData;

}

string File::fileName() const {

    return mFileName;

}

File::File(const char* fileName) {

    mFileName = fileName;

    mData = 0;

}

Loaderクラス

ファイルのロードを行うクラスです。
createFileで読み込みたいファイルのListであるmFilesにファイルの登録を行います。
updateを毎フレーム呼び出し、少しずつファイルを読み込みます。

#ifndef _LOADER_H_
#define _LOADER_H_

/*

Loader.h

*/

#include "Singleton.h"
#include "File.h"
#include <list>
#include <fstream>

class Loader : public Singleton<Loader> {

public:

    void createFile(File** file, const char* fileName);
    void destroyFile(const char* fileName);
    void update();

private:

    friend class Singleton<Loader>;

    Loader() {}
    Loader(const Loader& obj) {}
    void operator=(const Loader& obj) {}
    ~Loader() {}

    list<File*> mFiles;

    size_t mFileSize;
    size_t mSeekPosition;
    ifstream* mStream;
    File* mCurrentFile;
    char* mData;


};

#endif
#include "Loader.h"
#include "DEBUG.h"

/*

Loader.cpp

*/

void Loader::createFile(File** file, const char* fileName) {

    ASSERT((!(*file) && "ポインタはNULLである必要があります"));

    *file = new File(fileName);

    mFiles.push_back(*file);

}

void Loader::destroyFile(const char* fileName) {

    bool isFound = false;

    for (auto itr = mFiles.begin(); itr != mFiles.end(); ++itr) {

        File* file = *itr;

        if (file->mFileName == fileName) {

            delete file;

            file = nullptr;

            mFiles.erase(itr);

            isFound = true;

            break;

        }

    }

    ASSERT((isFound && "見つかりませんでした"));

}

void Loader::update() {

    if (mCurrentFile == nullptr && !mFiles.empty()) {

        auto itr = mFiles.begin();

        mCurrentFile = *itr;

        mStream = new ifstream(mCurrentFile->mFileName);

        mFileSize = static_cast<size_t>(mStream->seekg(0, fstream::end).tellg());

        mData = new char[mFileSize];

    }

    if (mCurrentFile != nullptr) {

        int rest = mFileSize - mSeekPosition;  // ファイルサイズ - 現在の読み込み位置で、残りのファイルサイズを取得しています。

        int maxKB = 128 * 1024;

        int size = (rest > maxKB) ? maxKB : rest;

        mStream->seekg(mSeekPosition, fstream::beg);

        mStream->read(mData + mSeekPosition, size);

        mSeekPosition += size;

        if (size == rest) {

            mCurrentFile->mData = mData;
            mCurrentFile->mSize = mFileSize;

            delete mData;
            mData = 0;

            mFileSize = mSeekPosition = 0;

            delete mStream;

            mFiles.erase(mFiles.begin());

            mCurrentFile = nullptr;

        }

    }

}

読み込むファイル

Test.txtというファイルを読み込みます。
今回は、試しにファイルサイズが小さいものを読み込んでいるので、あまり分割する意味はありませんが、実際にはもっと大きいファイルを読み込みたいと考えています。

TEST
GAMEPROGRAMING

実現したいこと

上記のTest.txtを読み込み、標準出力に表示したいと思い、mainを以下のように実装したのですが、
上手くいきませんでした。

#include "Loader.h"
#include "File.h"
#include <iostream>
#include <string>

using namespace std;

int main(void) {

    File* file = nullptr;

    if (file == nullptr) {

        Loader::shared().createFile(&file, "Test.txt");  // shared()はシングルトンクラスによって提供されている、唯一のインスタスを返すメソッドです。

    }

    while (!file->isReady()) {   //isReady()は読み込みが終わっているならばtrueを返すので、読み込みが終わっていない間、回ります。

        Loader::shared().update();

    }

    string str(file->data());

    cout << str << endl;

    return 0;

}

どのようにすれば実現できるのでしょうか。よろしくお願いいたします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • coco_bauer

    2017/09/19 12:00

    どんなファイルを読み込んでいるのかはssssskkkkkさんしか知りませんから、どんな使い方をするのかを知っているのもssssskkkkkさんしか居ません。他の人に判る訳がないと思いませんか?

    キャンセル

  • ssssskkkkk

    2017/09/19 18:16

    そうですよね、質問を修正したいと思います。

    キャンセル

  • t_obara

    2017/09/22 13:27

    うまくいかないとは、具体的にどのような動作になったのでしょうか

    キャンセル

回答 1

0

こんにちは。

このコードで最終的にFileクラスのmDataに読み込んだデータが格納されると踏んでいるのですが、そのような理解で合っているのでしょうか。

あっていると思いますが、何をやりたいのかコードから読み取れないのでssssskkkkkさんの期待通りに動作するかどうかは私には分かりません。

実際に走らせて確認するのが良いですよ。走らせるためにはmain()ルーチンが必要ですね。まずはmain()を書きましょう。その過程で様々な疑問を解決できると思います。
分からない部分を「具体的」に質問できるので回答も返ってきやすくなるという意味です。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/09/19 18:17

    ご指摘ありがとうございます。
    実際に走らせてみたのですが、やはりまだ分からない箇所があるので、具体的になるよう、質問を修正したいと思います。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 91.00%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • C++

    2937questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。