Search Unity

Read first line of every text file in array

Discussion in 'Scripting' started by LazyGoblinCody, Nov 18, 2017.

  1. LazyGoblinCody

    LazyGoblinCody

    Joined:
    Mar 18, 2015
    Posts:
    66
    Hey everyone quick question. If I have an array of text files say Level01.txt, Level02.txt and so on how can I go through each array index and get the first line of the .txt files. I found ways of reading the first line in a specific .txt file but I want to loop through an array of .txt files and get the first line.

    I hope this is making sense.
     
  2. BlackPete

    BlackPete

    Joined:
    Nov 16, 2016
    Posts:
    970
    StreamReader.ReadLine?

    You'll need to loop through your array and open each file to read in a single line, much like you did for a specific file.
     
  3. Fido789

    Fido789

    Joined:
    Feb 26, 2013
    Posts:
    343
    Code (CSharp):
    1.  foreach (var file in files)
    2.  {
    3.     using (var sr = new StreamReader(file))
    4.     {
    5.         // if there is a line
    6.         if (sr.Peek() >= 0)
    7.         {
    8.             Debug.Log(sr.ReadLine());
    9.         }
    10.     }
    11. }
     
  4. LazyGoblinCody

    LazyGoblinCody

    Joined:
    Mar 18, 2015
    Posts:
    66
    I keep getting these errors
    The best overloaded method match for `System.IO.StreamReader.StreamReader(System.IO.Stream)' has some invalid arguments

    Argument `#1' cannot convert `FallingItems.LevelInfo' expression to type `System.IO.Stream'

    Here is the code
    Code (CSharp):
    1. using System.IO;
    2. using System;
    3. using System.Collections;
    4. using System.Collections.Generic;
    5. using System.Collections.ObjectModel;
    6. using BrainGlue;
    7. using HeavyDutyInspector;
    8. using UnityEngine;
    9.  
    10.  
    11. namespace FallingItems.UI {
    12.  
    13.     public class Config : MonoBehaviour {
    14.  
    15.         [SerializeField] private float netLoadTimeout = -1;
    16.         [ReorderableList][SerializeField] public List<LevelInfo> levels;
    17.         [ReorderableList][SerializeField] private List<float> dropSpeedMultipliers;
    18.         [SerializeField] private int defaultDropSpeedIndex;
    19.         [SerializeField] private Localization localization;
    20.         public int scoreToPass;
    21.         public float duration;
    22.         public int fileCount;
    23.         public Object[] lvls;
    24.  
    25.         void Awake()
    26.         {
    27.             lvls = Resources.LoadAll("WordFiles");
    28.             fileCount = lvls.Length;
    29.  
    30.             levels = new List<LevelInfo>(new LevelInfo[fileCount]);
    31.          
    32.         }
    33.  
    34.         void Update()
    35.         {
    36.             for (int i = 0; i < fileCount; i++)
    37.             {
    38.                 levels[i].wordFile = lvls[i] as TextAsset;
    39.                 foreach (var lvl in levels)
    40.                 {
    41.                     using (var sr = new StreamReader(lvl))
    42.                     {
    43.                         if (sr.Peek() >= 0)
    44.                         {
    45.                             Debug.Log(sr.ReadLine());
    46.                         }
    47.                     }
    48.                 }
    49.             }
    50.         }
     
  5. BlackPete

    BlackPete

    Joined:
    Nov 16, 2016
    Posts:
    970
    You're trying to pass a LevelInfo object to the stream reader. You need to pass a string containing the file name.
     
  6. LazyGoblinCody

    LazyGoblinCody

    Joined:
    Mar 18, 2015
    Posts:
    66
    I am not trying to access one single file name though I am trying to access multiple while looping through an array.

    So at array index 0 I have Level01.txt and at index 1 I have Level02.txt I want to loop through the array holding the .txt and get the first line. Not hard code a single .txt file.
     
  7. LazyGoblinCody

    LazyGoblinCody

    Joined:
    Mar 18, 2015
    Posts:
    66
    So I kind of got it working with this bit of code but it doesn't really help much because the naming format of the .txt files are Level01 Level02 and so on.

    Code (CSharp):
    1. for (int i = 0; i < fileCount; i++)
    2.             {
    3.                 levels[i].wordFile = lvls[i] as TextAsset;
    4.                 foreach (var lvl in levels)
    5.                 {
    6.                     using (var sr = new StreamReader("Assets/Resources/WordFiles/Level" + i.ToString() + ".txt"))
    7.                     {
    8.                         if (sr.Peek() >= 0)
    9.                         {
    10.                             Debug.Log(sr.ReadLine());
    11.                         }
    12.                     }
    13.                 }
    14.             }
     
  8. whileBreak

    whileBreak

    Joined:
    Aug 28, 2014
    Posts:
    289
    What is the true type of levels? If you have the path to the file inside LevelInfo then just do this
    Code (CSharp):
    1. for (int i = 0; i < fileCount; i++)
    2.             {
    3.                 levels[i].wordFile = lvls[i] as TextAsset;
    4.                     StreamReader sr = new StreamReader(level[i].wordFile));
    5.                         if (sr.Peek() >= 0)
    6.                         {
    7.                             Debug.Log(sr.ReadLine());
    8.                         }
    9.             }
     
  9. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    Where are you going to use this?

    You'd be better off using one of Unity's path properties (e.g. Application.persistentDataPath) if you want to build that for a runtime version. If you want to load it directly from the Resources folder, there're Resources.Load methods for that.

    The reason I'm saying this is that
    1) hard-coded paths can be a pain
    2) some paths do not exist after builds at all
    3) you may run into trouble reading from relative paths (or even absolute ones - depending on the platform) if the API that you're using is not meant to figure that out automatically

    All these issues are most-likely gone if you take Unity's path properties or use the Resources class, because they are supposed to make this very convenient.

    In regards to the issue about the naming, you probably need to use padding for the number with zeros if the naming pattern is like you mentioned.

    Here are a few options to get the numbering correct:

    Code (CSharp):
    1. string numAsString;
    2. if (i < 10)
    3. {
    4.     numAsString = "0" + i;
    5. }
    6. else
    7. {
    8.     numAsString = i.ToString();
    9. }
    10.  
    11. // or one line, using the ternary operator (this can also be used within an expression)
    12. var numAsString = i < 10 ? "0" + i : i.ToString();
    13.  
    14. // or using string methods
    15. // first parameter determines the total width,
    16. // 2 => 01, 02, 03
    17. // 3 => 001, 002, 003
    18. var numAsString = i.ToString().PadLeft(2, '0');
    19.            
    20. // build your string, you could also use a System.Text.StringBuilder or even better, System.IO.Path.Combine(...)
    21. var path = "yourPathHere/" + numAsString + ".txt";
     
  10. LazyGoblinCody

    LazyGoblinCody

    Joined:
    Mar 18, 2015
    Posts:
    66
    Thanks everyone I got it to work :D