2017年2月11日土曜日

Unityでファイルの読み書きについて3

Androidのファイルの読み書きについてちょっとめんどくさかったので書きます。
Androidの場合ファイルの読み書きは初回起動時はStreamingAssetsフォルダから読み込み、
2回目以降はApplication.persistentDataPathで読み書きするようにします。

しかもAndroid のみ StreamingAssetsフォルダから読み込む場合 WWW クラスを使わないと読み込めないのが面倒くさいところです。

なぜこういう作りにするのか
StreamingAssetsフォルダを作っておけばビルド先のプラットフォームの、特定のフォルダーに何も変換されない状態で保持されます。しかし読み込みしかできず書き込みができないので
Application.persistentDataPathを使います。読み書きができるデータパスなので
初回はStreamingAssetsから読み込みそれ以降は、Application.persistentDataPathでデータのやり取りをします。


プロジェクトをGitHubに上げておきました。
Unityバージョン  5.5.0f3
https://github.com/templa00/FIleTest

一応ソースコードも貼っておきます。

以下ソースコード

// データを初期化するか?
//#define DATA_INIT

using UnityEngine;
using System.IO;
using System.Text;
using System.Collections;
using System;


/// ファイル管理
public class FIleManager
{
    // StreamingAssetsパス
#if UNITY_EDITOR
    // StreamingAssetsのパス
    public static string StreamingAssetsPath = Application.dataPath + "/StreamingAssets";

    // Android
#elif UNITY_ANDROID
    // パス(Android)
    public static string StreamingAssetsPath = "jar:file://" + Application.dataPath + "!/assets";


    // iOS
#elif UNITY_IPHONE
    public static string StreamingAssetsPath = path = Application.dataPath + "/Raw";


#else
    public static string StreamingAssetsPath = Application.dataPath + "/StreamingAssets";
#endif


    /// ファイル読み込み
    public static IEnumerator ReadFileText (Action callback, string _file_path)
    {
        // 結果
        string result = string.Empty;

        // ファイル
        FileInfo file;

        // 初回読み込みか?
        bool is_init_load = false;

        // 保存データパス
        var save_file_path = Application.persistentDataPath + _file_path;

        // 初回起動時ロードパス
        var init_file_path = StreamingAssetsPath + _file_path;

        // 読み込み先パス
        string load_path = string.Empty;

        

        // 保存先にデータがある場合
        if (File.Exists(save_file_path))
        {

            // データを初期化する場合
#if DATA_INIT

            Debug.Log("強制的に初回読み込み");

            // 初回起動時と同じ処理をするようにする
            is_init_load = true;

            // セーブデータ読み込み
            file = new FileInfo(save_file_path);
            
            // ファイル削除
            file.Delete();
            
            // 初回パスデータを取得する
            load_path = init_file_path;
#else
            Debug.Log("2回目以降の読み込み");

            // セーブデータのパスを設定する
            load_path = save_file_path;
#endif
        }
        // 初回起動時
        else
        {
            Debug.Log("初回読み込み");

            is_init_load = true;

            // 初回パスデータを取得する
            load_path = init_file_path;
        }

        Debug.Log("データ読込パス : " + load_path);

        // win or ios
#if UNITY_EDITOR || UNITY_IPHONE

        // JSONファイルを読み込む
        file = new FileInfo(load_path);
        using (StreamReader sr = new StreamReader(file.OpenRead(), Encoding.UTF8))
        {
            result = sr.ReadToEnd();
        }
        yield return new WaitForSeconds(0f);
        // Android
#elif UNITY_ANDROID
        // 初回ロードの場合
        if (init_load_data)
        {
            WWW www = new WWW(path);
            /// wwwの通信が終わるまで待機
            yield return www;

            string txtBuffer = string.Empty;
            TextReader txtReader = new StringReader(www.text);
            string description = string.Empty;
            while ((txtBuffer = txtReader.ReadLine()) != null)
            {
                description = description + txtBuffer + "\r\n";
                Debug.Log("description : " + description);
            }
            result = description;
        }
        // 初回ロードではない場合
        else
        {
            // ファイルを読み込む
            file = new FileInfo(path);
            using (StreamReader sr = new StreamReader(file.OpenRead(), Encoding.UTF8))
            {
                result = sr.ReadToEnd();
            }
            yield return new WaitForSeconds(0f);
        }
#endif
        callback(result);
    }

    /// ファイルを上書きする
    public static void WriteText (string _folda_path, string _file_name, string _contents)
    {
        // 保存フォルダパス
        var save_folda_path = Application.persistentDataPath + _folda_path;

        // 保存データパス
        var save_path = Application.persistentDataPath + _folda_path + _file_name;

        // フォルダがある場合
        if (Directory.Exists(save_folda_path))
        {
            Debug.Log("フォルダがあります");
        }
        else
        {
            Debug.Log("フォルダが無いので作成します");

            // ディレクトリ作成
            Directory.CreateDirectory(save_folda_path);
        }

        // 保存先 persistentDataPath
        // [win] : C:/Users/HomePC/AppData/LocalLow/DefaultCompany/プロジェクト名/save_data.json
        // [Android] : /data/app/xxxx.apk
        // [ios] : /var/mobile/Applications/xxxxxx/myappname.app/Data
        FileInfo file = new FileInfo(save_path);

        Debug.Log("保存先パス : " + save_path);

        // ファイルがある場合
        if (File.Exists(save_path))
        {
            // 削除
            file.Delete();
        }

        // 書き込み用ストリーム
        StreamWriter stream;

        stream = file.AppendText();      // StreamWriter を作成
        stream.WriteLine(_contents);     // 書き込み
        stream.Flush();                  // バッファ書き込み
        stream.Close();                  // 閉じる
    }
}

以下、使用方法

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class FileTest : MonoBehaviour {

 // Use this for initialization
 IEnumerator Start ()
    {
        // テストデータの文字列
        string test_data_str = string.Empty;

        // TestData読み込み(ロード)
        yield return FIleManager.ReadFileText(r => test_data_str = r, "/Data/TestData.txt");

        // 読み込んだテストデータの文字列を表示
        Debug.Log(test_data_str);

        // TestData書き込み(セーブ)
        FIleManager.WriteText("/Data", "/TestData.txt", "テストデータに書き込みました!");

        // 書き込んだTestDataを読み込み(ロード)
        yield return FIleManager.ReadFileText(r => test_data_str = r, "/Data/TestData.txt");

        // 読み込んだテストデータの文字列を表示
        Debug.Log(test_data_str);
    }
}

実行したら以下のようなログが出力されればOKです。
windowsでデバッグしました。
Androidでデバッグする場合はMonitorなどを使用するとログが表示されます。

初回起動時








2回目以降の起動時












0 件のコメント :

コメントを投稿

【早い者勝ち!】 あなたのお名前、残ってる?

シャドウバースにPC版が誕生