Load and save data in files on HoloLens device (txt, xml)

In this tutorial I describe how to save and load data from text and XML files. The data I store is three-dimensional points into the mixed reality environment in which you can insert to list with gesture event air tap.

Add the GameObject “Camera”, Gaze and from the gestures air tap event which described in the guide “Gaze and Gestures on HoloLens“.

crud.png

Create three GameObjects with Box Collider to use as buttons. With “Start Recording” tile you can start recording new three-dimensional points in the space with the use of air tap, with “Save Points” tile you can save the points in the text and XML file, with “Load Points” you can load the points from text and XML files. These GameObjects have a script for the OnSelect event.

OnSelectSave.cs file

    void OnSelect()
    {
        #if WINDOWS_UWP
        CRUDManager.Instance.SavePins();
        #endif
    }

OnSelectRecord.cs file

    void OnSelect()
    {
        CRUDManager.Instance.RecordCursorPins();
    }

OnSelect.cs file

    void OnSelect()
    {
        CRUDManager.Instance.LoadPins();
    }
public class Pin {
    
    public float posX { get; set; }
    public float posY { get; set; }
    public float posZ { get; set; }
}

Add a GameObject named “Manager” and add into to GameObject the scripts, GazeGestureManager.cs, CRUDManager.cs in which there is a code that records and loads the data from the text and XML file, TextMessage.cs in which display the list of three-dimensional points in GameObject “Border”. Also add the spatial mapping to select every surface from the real world.

CRUDManager.cs file

public class CRUDManager : MonoBehaviour
{

    public static CRUDManager Instance { get; private set; }

    public GameObject cursor;
    public GameObject recordMessage;

    private bool isrecording = false;
    private List<Pin> pins = new List<Pin>();
    private static string fileNameXML = "pins.xml";
    private static string fileNameTXT = "pins.txt";
#if WINDOWS_UWP
    private StorageFolder storageFolder = ApplicationData.Current.LocalFolder;
    private static string filePathXML = Path.Combine(ApplicationData.Current.LocalFolder.Path, fileNameXML);
    private static string filePathTXT = Path.Combine(ApplicationData.Current.LocalFolder.Path, fileNameTXT);
#endif

    void Awake()
    {
        Instance = this;
    }

    #region Record
    public void RecordCursorPins()
    {
        isrecording = !isrecording;

        if (isrecording)
        {
            pins.Clear();
            InvokeRepeating("AddPins", 2f, 2f);
            recordMessage.GetComponent<TextMesh>().text = "Stop Recording";
        }
        else
        {
            CancelInvoke("AddPins");
            recordMessage.GetComponent<TextMesh>().text = "Start Recording";
        }
    }

    private void AddPins()
    {
        pins.Add(new Pin { posX = cursor.transform.position.x, posY = cursor.transform.position.y, posZ = cursor.transform.position.z });
    }
    #endregion
    
    #region Save
#if WINDOWS_UWP
    public async void SavePins()
    {
        if (isrecording || pins.Count == 0)
        {
            TextMessage.Instance.ChangeTextMessage_Border("Try to record pins.");
            return;
        }
        
        //await WriteTXTToLocalStorage(); //Save to TXT file
    }

    public async Task WriteXMLToLocalStorage()
    {
        XmlSerializer serializer = new XmlSerializer(typeof(List));
        StorageFolder storageFolder = ApplicationData.Current.LocalFolder;

        if (File.Exists(filePathXML))
            File.Delete(filePathXML);

        StorageFile storageFile = await storageFolder.CreateFileAsync(fileNameXML);
        using (FileStream fs = new FileStream(storageFile.Path, FileMode.Create))
        {
            serializer.Serialize(fs, pins);
        }
     }

    public async Task WriteTXTToLocalStorage()
    {
        XmlSerializer serializer = new XmlSerializer(typeof(List));
        
        if (File.Exists(filePathTXT))
            File.Delete(filePathTXT);

        StorageFile storageFile = await storageFolder.CreateFileAsync(fileNameTXT);
        
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < pins.Count; i++)
        {
            builder.Append(string.Format("{0} {1} {2}", pins[i].posX.ToString("n5"), pins[i].posY.ToString("n5"), pins[i].posZ.ToString("n5"))).AppendLine();
        }

        //await FileIO.WriteTextAsync(storageFile, builder.ToString());
    }
#endif
    #endregion

    #region Load
    public void LoadPins()
    {
#if WINDOWS_UWP
        if (isrecording || pins.Count == 0)
        {
            TextMessage.Instance.ChangeTextMessage_Border("Try to record pins.");
            return;
        }
        
        if (!File.Exists(filePathXML))
        {
            TextMessage.Instance.ChangeTextMessage_Border("XML file does not exist.");
            return;
        }

        List savedPins = ReadXMLFromLocalStorage();
        string pinMessage = string.Empty;
        for(int i = 0; i < savedPins.Count; i++)
        {
            pinMessage = string.Format("{0} {1} {2}{3}", savedPins[i].posX.ToString("n5"), savedPins[i].posY.ToString("n5"), savedPins[i].posZ.ToString("n5"), Environment.NewLine);
        }

        //pinMessage = LoadTXTFromLocalStorage().Result; //Load TXT file

        TextMessage.Instance.ChangeTextMessage_Border(pinMessage);
#endif
    }
#if WINDOWS_UWP
    public List ReadXMLFromLocalStorage()
    {

        List savedPins;
        XmlSerializer serializer = new XmlSerializer(typeof(List));
        
        using (FileStream fs = new FileStream(filePathXML, FileMode.Open, FileAccess.Read))
        {
            savedPins = (List)serializer.Deserialize(fs);
        }

        return (savedPins != null)? savedPins : new List();
}

    public async Task LoadTXTFromLocalStorage()
    {
        StorageFile storageFile = await storageFolder.GetFileAsync(fileNameTXT);
        
        return await FileIO.ReadTextAsync(storageFile);
    }
#endif
    #endregion
}

TextMessage.cs file

public class TextMessage : MonoBehaviour {

    public static TextMessage Instance { get; private set; }
    
    public GameObject textMessageBorderGmObj;

    void Awake()
    {
        Instance = this;
    }

    public void ChangeTextMessage_Border(string textMessage)
    {
        textMessageBorderGmObj.GetComponent<TextMesh>().text = textMessage;
    }
}

You can find this sample and download it from github to this link https://github.com/gntakakis/Hololens-CRUD-TXT-XML-Storage-Unity

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s