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

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

ただいまの
回答率

90.02%

正しいCSVの書き出し方は?

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 3
  • VIEW 7,308

fukkun0412

score 35

前回、質問したのと似たものですが、お許しください。
私は今、CSVを更新するためにCSVに書き込むプログラムを作成しています。
ソースを転記しておきます。
//一度読み込む
pathは"CSVData/bring"としています。
public void WriteCSV(string path){
TextAsset csv = Resources.Load(path) as TextAsset;
StringReader reader = new StringReader(csv.text);
StreamWriter sw;
FileInfo fi;
fi = new FileInfo(csv.name + ".csv");
sw = new StreamWriter(csv.name + ".csv", true);
sw.WriteLine("あかさたな");
sw.Flush();
sw.Close();
}

この方法だとpathの名前のCSVは作成されるのですが、場所が元の場所(Resources/CSVData/bring.csv)ではなくAssetsフォルダの外にできてしまいます。CSVファイルの中身の更新するのが目的なので、これではいけないのです。

そこでなのですが、皆さんに質問をしたいと思います。
・ファイル場所を変えずにCSVを更新する方法はあるのか?
・Resource.Loadのパスは相対パスで、StreamRenderは絶対パスで指定しなければならないが、どちらにあわせれば良いのか?(私的にはResources.Loadを使いたい)
・プラットフォーム関係なくCSVを更新するには?(できればResources.Loadに沿ってやりたい)

主にこの二つの質問に答えていただければ幸いです。(実際にソースを転記していただくと幸いです。)もし訂正箇所がありましたら、随時訂正いたします。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

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

  • shironegi

    2016/06/01 09:11

    同じファイルに書き込みたい動機は何なんでしょう。
    セーブデータのように使いたいんでしょうか?
    それともCSVを編集するツールを作りたいんでしょうか?
    あと、前の質問とほぼ同じ質問を建てるなら、礼儀としてまず前の質問を何とかしましょうね。

    キャンセル

  • fukkun0412

    2016/06/01 15:06

    はい。shironegiさんのおっしゃる通り、前の質問を締め切る前に似た質問してしまったのは反省します。書き込みたい動機は、データの更新です。解禁情報や成長過程などのデータを管理したいと思ったからです。

    キャンセル

回答 2

checkベストアンサー

+2

追加情報ありがとうございます.

解禁情報や成長過程などのデータを管理したいと思ったからです。

つまりセーブデータということですね?

であれば,まずはゲームデータ(リソース)とセーブデータを切り分けて考えなければなりません.

ゲームデータはゲームの動作を定義するもので,予め用意されるものです.
セーブデータは,ゲームをプレイするにあたって生成され,書き換えられていくファイルなので,最初にゲームを起動した際は「空のファイル」または「ファイル自体無い」状態です.

つまり元からあるゲームデータを書き換えてセーブを実現しようというのは,ゲームというもののデータ管理の考え方と噛み合っていないのです.

したがって,セーブが目的であれば,
Resourcesフォルダ内のファイルを読みこんで上書きしていくのではなく,
ゲームデータの置き場所とは別の,セーブデータフォルダを用意して,
・セーブデータフォルダにファイルがあれば読み込んで,ファイルの内容を必要な変数に代入して保持
・進捗をセーブしたい時にセーブ関数を呼び出すと,セーブデータフォルダ内のファイルを上書きする
というようにするのが普通です.

前回の質問で,Application.dataPathで取得出来るパスは,プラットフォームによって書き込み出来ない場合があると書きましたが,書き込みが制限されている理由のひとつとして,ゲーム起動中にゲームデータが上書きされて,ゲームの動作がプレイ中に書き変わってしまわないように制限する目的があるのです.

実装について少し触れますが,
Resources.Loadはファイルの読み込みは出来ますが,保存はできません.
さらにマニュアルによるとResourcesフォルダ内のアセットしか読み込めないようです.
(http://docs.unity3d.com/ja/current/Manual/LoadingResourcesatRuntime.html)
したがってResourcesフォルダ外のセーブデータフォルダのファイルを読み込むにはStreamReaderを使用する必要があると思います.
保存にはStreamWriterを使用しなければなりません.
流れとしては,
・StreamReaderで既存のセーブデータファイルがあれば開く
・内容を読み込み内容を一旦変数に書きうつして閉じる
・(書き写した変数の中身を編集する)
・StreamWriterでセーブデータファイルを開いて内容を書き込んで閉じる.
となります.

上記を踏まえて質問の回答ですが,

・ファイル場所を変えずにCSVを更新する方法はあるのか? 

読み込んだファイルと同じファイルパスで保存すれば,場所を変えずに保存できます.
(読み込み時にファイルを開いたままCloseしない状態だと書き込めないという実装上の注意点はありますが.)
今回の肝は3つ目だと思うので,そちらの回答を見て下さい.

・Resource.Loadのパスは相対パスで、StreamRenderは絶対パスで指定しなければならないが、どちらにあわせれば良いのか?(私的にはResources.Loadを使いたい) 

読み込むことだけを考えれば,StreamReaderとResource.Loadは,どちらも読み込み機能しかありませんので,どちらでも構いません.
ただし書き込みにはStreamWriterを使わなければなりませんし,前述のようにResourcesフォルダ外であればStreamReaderでなければなりません.

・プラットフォーム関係なくCSVを更新するには?(できればResources.Loadに沿ってやりたい)

これを考えるならば,前提としてファイルの場所が「どのプラットフォームでも書き換え可能な場所」でなければなりません.
その為に,プラットフォームにあわせてパスが勝手に変わってくれるApplication.persistentDataPathが用意されているので,それを使用する他ありません.
プラットフォームが変わればApplication.persistentDataPathが変わるので,StreamReaderを使うしかないと思います.

具体的な方法やコード等が分からなければ聞いてもらえれば後ほど追加でお答えするとして,
その前にまずはセーブデータの扱い方について,ゲームデータと切り分けて考えてみてもらうことは可能でしょうか?

※ 質問内容から少しそれますが,
StreamReaderの代わりにFile.ReadAllText,StreamWriterの代わりにFile.WriteAllTextというものもあります.これらはファイルをCloseする必要がありませんし(ストリーミングしないため),使用方法もより単純です.
CSVファイルにこだわる理由は分かりませんが,セーブが目的なのであれば,UnityにはPlayerPrefsという仕組みが用意されており,これを使用すればファイル読み書きを気にすることなくセーブが実装出来ます.

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/06/02 00:33

    回答していただきありがとうございます。CSVファイルにこだわる理由は、クイズゲームを作成しておりまして、問題の管理をCSVファイルで行うと決め、他のファイルが別のものだと管理がしずらいのではないかと考えた末に全てのファイルをCSVファイルで管理しようと思ったのです。
    質問なのですが、PlayerPrefsを使用すれば、質問の方で申し上げた、成長情報や解禁情報の管理も可能なのでしょうか?この情報は中身が変更するので、一体どうなるのか分からないので質問させていただきます。

    キャンセル

  • 2016/06/02 19:18

    なるほど.
    問題文管理でCSVファイル入出力処理を作ってセーブにも使いまわそうという考えだったのですね.
    経緯を知って納得しました.

    PlayerPrefsについて,詳しくは1から調べてみてもらえればと思いますが,
    簡単にどんなものかと言うと,int, float, string の値を,自分で好きな名前を付けて保存・読み込みができ,ファイルへの書き出しもSave関数を呼び出せば自動で行ってくれて,アプリ起動時のファイル読み込みも自動で行ってくれるというものです.

    自分で名前付けと保存する値のルールを決めればいいので,どんなデータにも対応できます.

    例えばクイズの問題が1~10まであったとして,
    1が正解済みであれば
    名前を自分で決めて(たとえば"Question_1_is_Cleared"など),その名前で 1 を保存する,クリアできずにパスしていた場合は 0 を保存しておく事に決めておきます.
    クリアしたかどうか調べる場合には,名前を指定して値を読み込む関数があるので,「1が得られたらクリア済み」「0だったらクリアできなかった」「値が無かったら問題を見てすらいない」と進捗が判別できます.

    私はゲーム開発に関しては,あるものは進んで利用するべきだという考えです.
    もちろん既存の方法では効率が悪くて(例えばデータの設定が面倒すぎて時間がかかったりして)とか,処理速度が遅くてとか,二進も三進もいかず仕組みを自作した方が良いと判断した場合は自作します.

    それ以外はせっかくUnityを使っているわけですし,よほどのこだわりが無ければ,出来る限りUnityの仕組みを利用するのが良いと思いますよ.

    最近のゲーム開発はプロの現場でもそんな感じです.

    キャンセル

0

GetAssetPathで取ったパスは使えませんか?

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/06/01 15:31

    GetAssetPathを使う際に引数がint instanceIDのパターンとObject assetObjectのパターンがあるのですが、私の質問のプログラムの場合だとどういった使い方なら、よろしいのでしょうか?

    キャンセル

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

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