Search code examples
c#unity-game-engineexecutablestreamreader

Troubles with reading text file after Build


I'm having trouble reading a text file in Unity3D. I've created a method which returns a type float[][] and takes a streamreader as argument:

public float[][] CreateWeights(StreamReader reader){
    int n = 0;
    float[][] Weights = new float[50][];

    while((!reader.EndOfStream)){
        string text = reader.ReadLine();
            if (text == null)
            break;

        string[] strFloats = text.Split (new char[0]);
        float[] floats = new float[strFloats.Length];
        for(int i = 0; i<strFloats.Length; i++){
            floats[i] = float.Parse(strFloats[i]);

        }
        Weights[n] = floats;
        n++;
    }
    return Weights;
}

I make use of this method in void Start() to create "weights":

float[][] WeightsIH; 
float[][] WeightsHO;

void Start(){

    FileInfo theSourceFile = new FileInfo(Application.dataPath + "/Resources/WeightsIH.txt");
    StreamReader reader = theSourceFile.OpenText();

    FileInfo theSourceFile2 = new FileInfo(Application.dataPath + "/Resources/WeightsHO.txt");
    StreamReader reader2 = theSourceFile2.OpenText();

    WeightsIH = CreateWeights(reader);
    WeightsHO = CreateWeights(reader2);

    Yhidden = new float[50][];
    HiddenOutput = new float[50][];
    Xoutput = new float[1];

}

And this will work fine in Unity's play mode. However, after creating an executable, the files won't be found, which I do understand. So to make it work, I understood that I need to use Resources.Load and I have:

void Start(){

    TextAsset text1 = Resources.Load("WeightsIH") as TextAsset;
    TextAsset text2 = Resources.Load("WeightsHO") as TextAsset;

    WeightsIH = CreateWeights(text1);
    WeightsHO = CreateWeights(text2);

    Yhidden = new float[50][];
    HiddenOutput = new float[50][];
    Xoutput = new float[1];

}

Of course the argument type can't be a streamReader anymore, and I changed it to take TextAsset as argument. Here's how it changed:

public float[][] CreateWeights(TextAsset textAsset){

    float[][] Weights = new float[50][];

    string[] linesFromFile = textAsset.text.Split("\n"[0]);

    for(int i = 0; i<linesFromFile.Length; i++){

        string[] strFloats = linesFromFile[i].Split (new char[0]);
        float[] floats = new float[strFloats.Length];
        for(int j = 0; j<strFloats.Length; j++){
            floats[j] = float.Parse(strFloats[j]);

        }
        Weights[i] = floats;

    }
    return Weights;
}

Now this won't work at all, not even in play mode. The run-time error I would get is as follows:

FormatException: Invalid format.

System.Double.Parse (System.String s, NumberStyles style, IFormatProvider provider) (
at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System/Double.cs:209) System.Single.Parse (System.String s) (
at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System/Single.cs:183) FollowShortestPath.CreateWeights (UnityEngine.TextAsset textAsset) (
at Assets/Scripts/Pathfinding/FollowShortestPath.cs:203) FollowShortestPath.Start () (
at Assets/Scripts/Pathfinding/FollowShortestPath.cs:54)

line 54 refers to:

WeightsIH = CreateWeights(text1);

and line 203 refers to:

floats[j] = float.Parse(strFloats[j]);

What am I doing wrong? How can I get the text files to be read successfully in in the executable?


Solution

  • The problem you have is with text file format you are loading.

    Couse you have many white spaces

    string[] strFloats = text.Split (new char[0]);
    

    will result in that some strings are empty.

    To fix this, remove extra withe spaces from text files or use:

    for(int j = 0; j<strFloats.Length; j++){
                if (string.IsNullOrEmpty (strFloats [j]))
                    continue;
    
                floats[j] = float.Parse(strFloats[j]);
    
            }