1

Trying to List a number files according to extension *.json. Instantiating the prefab under a parent but it wont come in an order.Is there a way to refresh the list or arrange them according in an ascending order way.Aim is to Load and delete the files.How to arrange the files 1,2,3,4,5...and if there are 10 files the last saved file should come down there in the 10 th place under a parent?

Dictionary<int, Button> BtnList = new Dictionary<int, Button>();
public static FileInfo[] info;
GameObject lisobj;

public void ListMap()
{

    panellist.SetActive(true);
    string mainpath = Application.persistentDataPath;
    DirectoryInfo dir = new DirectoryInfo(mainpath);



    info = dir.GetFiles("*.json");


    for(int i = 1;i<=info.Length;i++)
    {
           lisobj = Instantiate(prefabpanellist);
        lisobj.transform.SetParent(Parentcontent);

            number.text = i.ToString();
            mapnamedb.text =info[i-1].Name;

        var button = lisobj.GetComponentInChildren<Button>();
        BtnList.Add(i,button);



    }
    lisobj.transform.SetParent(Parentcontent);

    Dictionary<int, Button>.ValueCollection values = BtnList.Values;

    foreach (Button btn in values)
    {

        btn.onClick.AddListener(() => Deleteinformation());


    }

}

public void Deleteinformation()
{
    var b= UnityEngine.EventSystems.EventSystem.current.currentSelectedGameObject.GetComponent<Button>();


    var mykey=BtnList.FirstOrDefault(x=>x.Value==b).Key;
    Debug.Log("Items are" + mykey);

    string mainpath = Application.persistentDataPath;
    Debug.Log("Name is " + info[mykey - 1].Name);

    //File.Delete(mainpath + info[mykey-1].);
}

Initially when I save the file to .json and click the button for Listmap(To show the filelist - shown in Screenshot).It is showing the index number 5 two times.Also the last file I saved was named "00000.json",but it became the first file.That is after I save it(the file list) is not getting updated,When I click Listmap the files are showing same index number mulitiple times.Seems like it is not refreshing not sure.Another problem is the last saved file is coming on the top.

1 2

zyonneo
  • 1,319
  • 5
  • 25
  • 63
  • 1
    Possible duplicate of [Sorting Directory.GetFiles()](https://stackoverflow.com/questions/52842/sorting-directory-getfiles) – BugFinder Apr 09 '19 at 08:58
  • @BugFinder info = dir.GetFileSystemInfos(); How to get .JSON files using this? – zyonneo Apr 09 '19 at 09:03
  • thats not the question you were asking. You asked how to list them in ascending order.. which is a dup of the one I listed – BugFinder Apr 09 '19 at 09:05
  • the same way .. it also has an overload [`GetFileSystemInfos(string)`](https://learn.microsoft.com/de-de/dotnet/api/system.io.directoryinfo.getfilesysteminfos?view=netframework-4.7.2#System_IO_DirectoryInfo_GetFileSystemInfos_System_String_) where you can pass `*.json` in – derHugo Apr 09 '19 at 09:05
  • @BugFinder Does Naming affect that..I used 0000 in filename and it came first. – zyonneo Apr 09 '19 at 09:07
  • It will sort it as string by default but you could of course change that ... (because filenames are string) – BugFinder Apr 09 '19 at 09:10
  • @zyonneo by default `GetFiles` sorts by filename => starting with `0` comes before starting with `1` though it also says [msdn](https://learn.microsoft.com/dotnet/api/system.io.directory.getfiles#System_IO_Directory_GetFiles_System_String_System_String_):`The order of the returned file names is not guaranteed; use the Sort() method if a specific sort order is required.` etc. In the given link you can see they instead sort (like you want) by `files.OrderBy(f => f.CreationTime);` – derHugo Apr 09 '19 at 09:10
  • I am saving them in a folder.I am Instantiating a prefab actually.So it should be the prefab I should sort not the files Right? – zyonneo Apr 09 '19 at 09:15
  • 1
    but you iterate the files and add a prefab for each file ... so you should sort the `info` in order to instaniate the prefabs in the correct order. Afaik `SetParent` always adds the child as the last one ... just to be sure you could also look into [Transform.SetAsLastSibling](https://docs.unity3d.com/ScriptReference/Transform.SetAsLastSibling.html) – derHugo Apr 09 '19 at 09:16
  • I would btw instead of iterating the buttons again already set it directly when you instantiate the prefab... – derHugo Apr 09 '19 at 09:18
  • @derHugo Yes thats what I guess I was trying to solve.. – zyonneo Apr 09 '19 at 09:22
  • var orderedFiles = info.OrderBy(f => f.CreationTime); Now orderedFiles contains info contents in order right? But I cannot get anything out of orderedFiles. mapnamedb.text =infos[i-1].Name; instead I used mapnamedb.text =orderedFiles[i-1].Name; showing error. – zyonneo Apr 09 '19 at 09:35
  • @zyonneo "orderfiles" from above contains ALL the fileinfo you started with - so you should be able to get all the info you wanted.. This question seems to have derailed a heck of a lot – BugFinder Apr 09 '19 at 09:48
  • @BugFinder Not getting it though getting the error..Error CS0021: Cannot apply indexing with [] to an expression of type 'IOrderedEnumerable' .. – zyonneo Apr 09 '19 at 09:51
  • 2
    use `var orderedFiles = info.OrderBy(f => f.CreationTime).ToList();` – derHugo Apr 09 '19 at 09:53
  • Tried a simple fix... if(i==infos.Length) { int aa = Parentcontent.childCount; Parentcontent.GetChild(0).SetSiblingIndex(aa - 1); } . While loading the list multiple index number with same filenames previous created file – zyonneo Apr 09 '19 at 11:59

1 Answers1

2

I've set it all together and this works perfectly for me now:

Note: I commented out everything not relevant for the example (or what you didn't add to your code in the question)

public class FilesExample : MonoBehaviour
{
    // Start is called before the first frame update
    private void Start()
    {
        ListMap();
    }

    public static FileSystemInfo[] info;

    public void ListMap()
    {
        /*
         * If you already called this before you already have child objects
         * So I would destroy the old ones before instantiating new ones
         */
        //foreach(Transform child in Parentcontent)
        foreach(Transform child in transform)
        {
            Destroy(child.gameObject);
        }

        //panellist.SetActive(true);

        /*
         * preferred to use streamingAssetsPath for testing
         */

        //var mainpath = Application.persistentDataPath;
        var mainpath = Application.streamingAssetsPath;
        var dir = new DirectoryInfo(mainpath);

        info = dir.GetFileSystemInfos("*.json").OrderBy(i => i.CreationTime).ToArray();

        for (var i = 1; i <= info.Length; i++)
        {
            /* 
             * Instead of instantiating I simply created new empty objects
             * just as example 
             */

            //var lisobj = Instantiate(prefabpanellist);
            var lisobj = new GameObject(i + " " + info[i - 1].Name);
            //lisobj.transform.SetParent(Parentcontent);
            lisobj.transform.SetParent(transform);

            // Though I'm sure this should already have the correct order
            // you could still do SetLastSibling to move the 
            // created/instantiated object to the bottom
            lisobj.transform.SetAsLastSibling();

            //number.text = i.ToString();
            //mapnamedb.text = info[i - 1].Name;

            /*
             * NOTE: I would simply do the buttons thing in the same
             *       loop. That saves you a lot of storing and accessing lists
             */

            //var index = i;
            //var button = lisobj.GetComponentInChildren<Button>(true);
            //button.onClick.AddListener(() => Deleteinformation(index));
        }
    }

    public void Deleteinformation(int index)
    {
        Debug.Log("Index is " + index);

        Debug.Log("Path is " + info[index].FullName);

        File.Delete( info[index].FullName);

        // update the scene list
        ListMap();
    }
}

Result

Files on drive ordered by name

enter image description here

Files on drive ordered by creation date

enter image description here

result in Unity ordered by creation date

enter image description here

derHugo
  • 83,094
  • 9
  • 75
  • 115
  • I can Instantiate and do the same right..I can instantiate so that I can show them as a list with text and delete button – zyonneo Apr 09 '19 at 12:55
  • Instatiate creates problem It will be added at the top only..So i used this code to bring it down the last created list value with delete button........ if (i == infos.Length) { int aa = Parentcontent.childCount; Parentcontent.GetChild(0).SetSiblingIndex(aa - 1); } ...........but when I delete the last one, the first element in the list gets deleted – zyonneo Apr 09 '19 at 13:21
  • @derHugo..How to update the filelist when the file is deleted. – zyonneo Apr 10 '19 at 08:43
  • you could before instantiating stuff destroy all current children (`foreach(Transform child in transform){ Destroy(child.gameObject); }`) – derHugo Apr 10 '19 at 08:45
  • @DerHugo..FileSystemInfo infos [] save them into a cache?.I have hit Play two times to update my List with contents from the folder.Doesnt get updated When I add ListMap() function call inside Deletemap....................if(Parentcontent.childCount>0) { GameObject gg = Parentcontent.GetChild(i-1).gameObject; Destroy(gg); Debug.Log("Name is = " + gg.name); } – zyonneo Apr 10 '19 at 09:40
  • is it possible that `File.Delete` takes some time and therefore ListMap is simply called to early? – derHugo Apr 10 '19 at 10:11
  • Not Time I believe....Will wait for a while n check...Also I have added a . back button and let me click Listmap again..Should I use Coroutine? – zyonneo Apr 10 '19 at 10:20