keiwando / nativefileso

Unity - Native file dialogs and file type associations on Windows, macOS, iOS and Android
Mozilla Public License 2.0
85 stars 8 forks source link

Feature Request: Open File as a Stream, but Not Byte Array. #3

Open tinysnake opened 3 years ago

tinysnake commented 3 years ago

Great job of making this plugin! But I think there's a problem: opening a very big file may cause app to crash, because it loads the entire file into memory. Opening a very big file as a stream will solve this problem but don't know if it's practical or not.

keiwando commented 3 years ago

That might be difficult to provide on mobile. The mobile platforms don't give you a persistent URL to a file that you could read from at a later point in time. You generally have to read the file from the temporary URL for security reasons as the user grants you permission to open the file.

I'm not sure how feasible (or even possible) it would be to try to pipe that through to the C# code in order to then stream the file contents. It might be possible to open a stream in the platform-specific code and provide a callback to the C# code to read a few bytes at a time. Even if this is possible when opening a file from within the app, this might not work when launching the app with a file to open.

The desktop platforms already provide APIs that can be used to let the user choose a file path which can the be used to stream the contents of the file.

tinysnake commented 3 years ago

My request is mainly focused on mobile platform, by the way.

My thought is by copying the file to the app's local storage and then open the copied file as stream.

keiwando commented 3 years ago

Yes, that might be one of the few ways to make it work. The Android version already does that for files that were opened from outside of the app.

It's not a 100% reliable solution since Unity we would have to make some assumptions about how Unity itself does or does not use the app's local storage, but then again, a lot of the features provided by this plugin have to already make certain assumptions in order to work and could break with future versions of Unity and/or the individual operating systems.

I will definitely leave this open, since it is a valid issue, but I can already say that I won't have time to implement this myself any time soon. If you or anyone else wants to give it a go, please feel free to do so.

bhupiister commented 3 years ago

@keiwando @tinysnake : We can create the file and then open it if I am not wrong. Is my approach right? I check for the file if its compatible and open it, if not then delete it. ` public class MyFileHandler : MonoBehaviour { public Text Status; void Start() { NativeFileSOMobile.shared.FilesWereOpened += delegate (OpenedFile[] files) { if (files[0].Extension.Equals(".csv")) { // Process the opened files Debug.Log(files[0].Name); //Status.text += " FileName: " + files[0].Name; //Status.text += " Extension: " + files[0].Extension; string path = Application.persistentDataPath + "/" + files[0].Name; File.WriteAllBytes(path, files[0].Data); CheckIfFileValid(path, files[0].Name); } else { Status.text = "file is not compatible!"; } }; } private void CheckIfFileValid(string path, string fileName) { string line1 = File.ReadLines(path).First(); if (line1.Contains("Time") && line1.Contains("Xaxis") && line1.Contains("Yaxis") && line1.Contains("Zaxis")) { Status.text = "Opening file " + fileName; PlayerPrefs.SetString("fileName", fileName); SceneManager.LoadScene("Result"); } else { Status.text = "file is not compatible!"; File.Delete(path); } } }

`

keiwando commented 3 years ago

@bhupiister The problem is that each OpenedFile instance that gets passed into the FilesWereOpened delegate has already loaded the entire file contents into memory. Preventing that would have to happen inside of the plugin code, probably somewhere at the native platform level.