Search Unity

Read from TextAsset line by line

Discussion in 'Scripting' started by Malleck666, May 21, 2015.

  1. Malleck666

    Malleck666

    Joined:
    Jan 9, 2015
    Posts:
    235
    I've done a lot of searching for an answer before posting here but I don't seem to be getting anywhere.

    Essentially I have a streamreader that reads a text file line by line to populate a list. The issue is that after it has been compiled, it will no longer read from this list unless I store the text file as a textasset. I have declared the textasset but I'm unsure of how to access it line by line for the streamreader as using .text reads the whole lot in one go.

    Here is what I have so far

    Code (CSharp):
    1.   TextAsset spellData = Resources.Load("spelldata.txt") as TextAsset;
    2.  
    3.         Debug.Log("Compiling spell database...");
    4.  
    5.         string line;
    6.         System.IO.StreamReader file = new System.IO.StreamReader(Application.dataPath + "/Resources/spelldata.txt"); //load text file with data
    7.         while ((line = file.ReadLine()) != null)
    8.         { //while text exists.. repeat
    9.  
    10.             char[] delimiterChar = { '#' };//variable separation
    11.             string[] split = line.Split(delimiterChar, StringSplitOptions.None); //each line splits parts with # character
    12.             Spell spellIn = new Spell(split[0], Convert.ToInt32(split[1]), Convert.ToInt32(split[2]), Convert.ToBoolean(split[3]), split[4], Convert.ToInt32(split[5]), split[6],
    13.                                       split[7], split[8], split[9]); //create new spell and populate
    14.             Debug.Log(spellIn.spell_name + " found...");
    15.             spellDB.Add(spellIn); //add to database
    16.         }
    17.         file.Close();
    Currently it reads from "Application.dataPath + "/Resources/spelldata.txt" but I'd like it from the declared textasset. Thanks in advance!
     
  2. Bradamante

    Bradamante

    Joined:
    Sep 27, 2012
    Posts:
    293
    Well you are declaring spellData at the top, but you are using while on the file variable. Or how do you mean?
     
  3. Malleck666

    Malleck666

    Joined:
    Jan 9, 2015
    Posts:
    235
    Instead of reading from the current file path, how would I read from the textAsset instead. I know i'd have to restructure the streamreader but I'm not sure how.
     
    raulius likes this.
  4. Bradamante

    Bradamante

    Joined:
    Sep 27, 2012
    Posts:
    293
    Don't have to use the StreamReader:

    Code (csharp):
    1.  
    2. public static Spell parseTextAsset ( TextAsset ft ) {
    3.  
    4.   string fs = ft.text;
    5.   string[] fLines = Regex.Split ( fs, "\n|\r|\r\n" );
    6.  
    7.   for ( int i=0; i < fLines.Length; i++ ) {
    8.  
    9.   string valueLine = fLines[i];
    10.   string[] values = Regex.Split ( valueLine, ";" ); // your splitter here
    11.  
    12.   Spell newSpell = new Spell ( values[0], ... ) // etc
    13.   return newSpell;
    14.   // spellDB.Add ( newSpell );
    15.   }
    16. }
     
  5. Malleck666

    Malleck666

    Joined:
    Jan 9, 2015
    Posts:
    235
    Thank you for you help, but now I'm unsure how to populate my spellDB list with each of these? Apologies if I'm overlooking something simple!
     
  6. Bradamante

    Bradamante

    Joined:
    Sep 27, 2012
    Posts:
    293
    Well, not like this?

    Code (csharp):
    1.  
    2. TextAsset spellData = Resources.Load("spelldata.txt") as TextAsset;
    3. List<Spell> spellDB = new List<Spell>();
    4.  
    5. // put the parseTextAsset function in a static public class
    6. // that doesn't derive from MonoBehavior
    7. Spell newSpell = TextAssetParser.parseTextAsset ( spellData);
    8. spellDB.Add ( newSpell );
     
  7. Malleck666

    Malleck666

    Joined:
    Jan 9, 2015
    Posts:
    235
    Thank you again, but there is still one more issue. The function is erroring saying that it doesn't return a value on all paths. What should I be returning for null if I'm understanding this correctly?
     
  8. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    8,137
    Don't use @Bradamante's code directly; I think he was in a hurry, because he's got a "for" loop that exits (returns) on the very first iteration through the loop. I'm pretty sure that's not what you want!

    But take the big idea — just split the TextAsset.text into lines (for example, with Regex.Split as @Bradamante showed), and then do whatever you want with each line.
     
  9. rakkarage

    rakkarage

    Joined:
    Feb 3, 2014
    Posts:
    682
    make a public TextAsset property and drag the text into it in editor
    the TextAsset has a text property and that text property has a Split method

    Code (CSharp):
    1.         public void Import()
    2.         {
    3.             Clear();
    4.             var splitFile = new string[] { "\r\n", "\r", "\n" };
    5.             var splitLine = new char[] { ',' };
    6.             // name
    7.             var NameLines = NameFile.text.Split(splitFile, StringSplitOptions.None);
    8.             for (uint i = 0; i < NameLines.Length; i++)
    9.             {
    10.                 var line = NameLines[i].Split(splitLine, StringSplitOptions.None);
    11.                 Utility.Assert(line.Length == _nameFieldCount);
    12.                 // male
    13.                 Add(line[0], Male);
    14.                 // female
    15.                 Add(line[1], Female);
    16.                 // both
    17.                 Add(line[2], Male);
    18.                 Add(line[2], Female);
    19.             }
    20.             // syllable
    21.             var SyllableLines = SyllableFile.text.Split(splitFile, StringSplitOptions.None);
    22.             for (uint i = 0; i < SyllableLines.Length; i++)
    23.             {
    24.                 var line = SyllableLines[i].Split(splitLine, StringSplitOptions.None);
    25.                 Utility.Assert(line.Length == _syllableFieldCount);
    26.                 // male
    27.                 Add(line[0], MaleStart);
    28.                 Add(line[1], MaleMiddle);
    29.                 Add(line[2], MaleEnd);
    30.                 // female
    31.                 Add(line[3], FemaleStart);
    32.                 Add(line[4], FemaleMiddle);
    33.                 Add(line[5], FemaleEnd);
    34.                 // both
    35.                 Add(line[6], MaleStart);
    36.                 Add(line[7], MaleMiddle);
    37.                 Add(line[7], MaleEnd);
    38.                 Add(line[6], FemaleStart);
    39.                 Add(line[7], FemaleMiddle);
    40.                 Add(line[8], FemaleEnd);
    41.             }
    42.             // title
    43.             var TitleLines = TitleFile.text.Split(splitFile, StringSplitOptions.None);
    44.             for (uint i = 0; i < TitleLines.Length; i++)
    45.             {
    46.                 var line = TitleLines[i].Split(splitLine, StringSplitOptions.None);
    47.                 Utility.Assert(line.Length == _titleFieldCount);
    48.                 // male
    49.                 Add(line[0], MalePre);
    50.                 Add(line[1], MalePost);
    51.                 // female
    52.                 Add(line[2], FemalePre);
    53.                 Add(line[3], FemalePost);
    54.                 // both
    55.                 Add(line[4], MalePre);
    56.                 Add(line[5], MalePost);
    57.                 Add(line[4], FemalePre);
    58.                 Add(line[5], FemalePost);
    59.             }
    60.             Sort();
    61.         }
    62.  
     
  10. Warped

    Warped

    Joined:
    Mar 19, 2015
    Posts:
    12
    Try this
    Code (CSharp):
    1. string[] linesFromfile = sourceTexts.text.Split("\n"[0]);
     
  11. Xitech_

    Xitech_

    Joined:
    Feb 19, 2013
    Posts:
    117
    Might be an old-ish post but I created a little function that has a TextAsset as input parameter, and returns a list of each line (split by \n(enters)).


    Code (CSharp):
    1.  private List<string> TextAssetToList(TextAsset ta)
    2.     {
    3.         var listToReturn = new List<string>();
    4.         var arrayString = ta.text.Split('\n');
    5.         foreach (var line in arrayString)
    6.         {
    7.             listToReturn.Add(line);
    8.         }
    9.         return listToReturn;
    10.     }
     
  12. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    8,137
    I think this would be more efficient...

    Code (CSharp):
    1. private List<string> TextAssetToList(TextAsset ta) {
    2.         return new List<string>(ta.text.Split('\n'));
    3. }
     
    vestigial likes this.
  13. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    4,665
  14. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    8,137
    How would you use that on a TextAsset, exactly? I didn't think there was (in a compiled game) an actual file to read from in this case.
     
  15. vestigial

    vestigial

    Joined:
    May 9, 2015
    Posts:
    37
    Extension method version of JoeStrouts solution, call with myTextAsset.TextAssetToList()

    Code (CSharp):
    1.  
    2.     public static class TextAssetExtensionMethods {
    3.         public static List<string> TextAssetToList(this TextAsset ta) {
    4.             return new List<string>(ta.text.Split('\n'));
    5.         }
    6.     }
    7.  
     
    Griffo and Kurt-Dekker like this.
  16. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    4,084
    Should this perhaps use

    Code (csharp):
    1. System.Environment.NewLine
    instead of just \n ?

    I've always used \n but I'm wondering if we can rely on that with all of Unity's target platforms.
     
    JoeStrout likes this.
  17. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    8,137
    Yeah, I can't say for sure, but in other cross-platform work I've been bitten by making assumptions about line endings. So using System.Environment.NewLine is probably a good idea — it can't hurt, and it just might help.
     
    Kurt-Dekker likes this.
  18. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    4,084
    There is also the System.IO.StringReader way... I haven't tried that yet. Might be safe to assume that takes into account System.Environment.NewLine internally.

    Also, don't forget it is an IDisposable, as so many example codelets seem to forget.
     
    JoeStrout likes this.
  19. stef4nio

    stef4nio

    Joined:
    May 31, 2017
    Posts:
    1
    you are the best!!!! thank you wery much
     
  20. unity_oeMZSDS9APQlWQ

    unity_oeMZSDS9APQlWQ

    Joined:
    Dec 17, 2018
    Posts:
    2
    comparision not working always returns false, can you help me out for searching.
    Debug.Log( words.Contains(inputField.text));

    if (words.Contains(inputField.text, StringComparer.CurrentCultureIgnoreCase)) {
    Debug.Log("Contains");
    } else{
    Debug.Log("not");
    }