Store and read csv file from android and ios in Unity - c#

I have a Unity project which I want to work for both android and ios. I also have a csv file which I want to read during runtime. I tried the following code:
string basePath = Path.Combine(Application.persistentDataPath, $"{fileName}.csv");
if (File.Exists(basePath))
{
string[] rows = File.ReadAllLines(basePath);
foreach (string item in rows)
{
Debug.Log(item);
}
}
However, I don't know where to put the csv file for it to find it on persistentDataPath. And if I find the correct place, will it be the same on android and ios or do I need to save the file on more locations or folders?
Or do you have any other suggestions on how to store and then load a cvs for different platforms?

If you just want to read a .csv file that you deploy with your game, you could just place it into the Resources folders inside your Assets.
You could read it like this:
TextAsset file = Resources.Load(fileName) as TextAsset;
string content = file.ToString();
Note: fileName must be specified here without file extension.
If you want to modify the .csv file or perhaps make it available in Application.persistentDataPath, you can simply copy it to that location first. For later changes you can then access the file in persistentDataPath.
Self-Contained Example
A self-contained example could look something like this:
using System.IO;
using UnityEngine;
public class CSVFileManager : MonoBehaviour
{
void Start()
{
var fileName = "example";
var csvFileName = $"{fileName}.csv";
string basePath = Path.Combine(Application.persistentDataPath, csvFileName);
Debug.Log($"basePath = >>{basePath}<<");
if (!File.Exists(basePath))
{
TextAsset file = Resources.Load(fileName) as TextAsset;
string content = file.ToString();
File.WriteAllText(basePath, content);
}
else
{
//... work with the current file in persistentDataPath
}
}
}
Test
I tested it briefly on Mac, but it should work equally well on Android and iOS:

Related

Problem in overwriting Application.persistentDataPath

I have a JSON file which contains data for my Localization in my game. The file is stored in Application.persistentDataPath . I read in the documentation that the file is not deleted or overwritten when updating the game. Currently I launch the app and the file is there but when I add more content and send an update to save again, it only has the original content.
But is there a way to update this file when I update the game?
What if in the future I want to add more content to this JSON file, I would have to delete it and upload it again?
Any way to update and overwrite it?
private static void Request(string file)
{
var loadingRequest = UnityWebRequest.Get(Path.Combine(Application.streamingAssetsPath, file));
loadingRequest.SendWebRequest();
while (!loadingRequest.isDone)
{
if (loadingRequest.isNetworkError || loadingRequest.isHttpError)
{
break;
}
}
if (loadingRequest.isNetworkError || loadingRequest.isHttpError)
{
// Some error happened.
}
else
{
File.WriteAllBytes(Path.Combine(Application.persistentDataPath, file), loadingRequest.downloadHandler.data);
}
}
// Loads key from "StreamingAssets/language_data.json" file.
public static string LoadJson(string key)
{
Request("data.json");
var jsonPath = Path.Combine(Application.persistentDataPath, jsonFileName);
using (StreamReader r = new StreamReader(jsonPath))
{
var N = JSON.Parse(r.ReadToEnd());
string result = N[GetLanguage()][key];
return result;
}
}
I think the issue is the following:
You are only creating a file named data.json NOT languages_data.json!
In Request (you pass in "data.json") you copy
Application.streamingAssetsPath, file
to
Application.persistentDataPath, file
where file = "data.json"
Then in LoadJson you are trying to load values from
Application.persistentDataPath, jsonFileName
where - as to your comments - jsonFileName = "languages_data.json"
=> It is a different path!
In the Editor/on your PC you probably still have an old languages_data.json in the persistent data from some time ago. Therefore there is no error but it is also never updated. Delete the persistent/languages_data.json on your PC and it will throw a FileNotFoundException.
To solve this make 100% sure the file names are the same everywhere. The simplest fix code wise would be to simply rather use
Request(jsonFileName);
and make sure that jsonFileName matches the name of your existing file in StreamingAssets.

Retrieving recorded media (videos/photos)

I'm having trouble retrieving videos that I have recorded from my app on my iPhone.
The purpose of this is to upload this recorded video to Amazon Web Service's cloud (store it in a bucket).
However I seem to only be have directory access capabilities instead of the actual files. I don't know if this is a permissions issue or if there's a specific class that allows me to retrieve recorded videos.
This snippet of code saves the video:
var options = new PHAssetResourceCreationOptions {};
var changeRequest = PHAssetCreationRequest.CreationRequestForAsset ();
changeRequest.AddResource (PHAssetResourceType.Video, outputFileUrl, options);
The path from the outputFileUrl, which saves to the iPhone's temp folder, is how I was going about trying to retrieve the file to upload but to no success.
Can someone help me with this?
I have an toggle Record Event that gets the file like this:
// Start recording to a temporary file.
MovieFileOutput.StartRecordingToOutputFile (new NSUrl(GetTmpFilePath ("mov"), false), this);
This is the definition for GetTmpFilePath():
static string GetTmpFilePath (string extension)
{
// Start recording to a temporary file.
string outputFileName = NSProcessInfo.ProcessInfo.GloballyUniqueString;
string tmpDir = Path.GetTempPath();
string outputFilePath = Path.Combine (tmpDir, outputFileName);
return Path.ChangeExtension (outputFilePath, extension);
}
outputFileUrl is a NSUrl and is the result of this, it is a parameter to the method that uses this in the "AddResource" above.

c# zip file - Extract file last

Quick question: I need to extract zip file and have a certain file extract last.
More info: I know how to extract a zip file with c# (fw 4.5).
The problem I'm having now is that I have a zip file and inside it there is always a file name (for example) "myFlag.xml" and a few more files.
Since I need to support some old applications that listen to the folder I'm extracting to, I want to make sure that the XML file will always be extract the last.
Is there some thing like "exclude" for the zip function that can extract all but a certain file so I can do that and then extract only the file alone?
Thanks.
You could probably try a foreach loop on the ZipArchive, and exclude everything that doesn't match your parameters, then, after the loop is done, extract the last file.
Something like this:
private void TestUnzip_Foreach()
{
using (ZipArchive z = ZipFile.Open("zipfile.zip", ZipArchiveMode.Read))
{
string LastFile = "lastFileName.ext";
int curPos = 0;
int lastFilePosition = 0;
foreach (ZipArchiveEntry entry in z.Entries)
{
if (entry.Name != LastFile)
{
entry.ExtractToFile(#"C:\somewhere\" + entry.FullName);
}
else
{
lastFilePosition = curPos;
}
curPos++;
}
z.Entries[lastFilePosition].ExtractToFile(#"C:\somewhere_else\" + LastFile);
}
}

Restrict users to upload zip file with folder inside

I have a file upload control.
I restrict users to upload only zip files.
the namespace i use is Ionic.Zip;
I also want check if that zip file has a folder inside.
I have to restrict the users not upload a zipfile with a folder inside.
I could check how many files inside zip file like
using (ZipFile zip = ZipFile.Read(file_path))
{
if (zip.Count < 5)
{
}
I do not know how to check for a folder inside
Anyone can help me please.
thanks in advance
void Main()
{
var isGood=false;
using (ZipFile zip = new ZipFile(#"c:\\1.zip"))
{
for (var i=0;i<zip.Count;i++)
if (zip[i].Attributes==FileAttributes.Directory)
{
isGood=false;
break;
}
}
if (isGood) Console.WriteLine ("ok");
else
Console.WriteLine ("error");
}
// Define other methods and classes here
edit :
there's seems to be a problem with the way you created this zip file.
I extracted the files from the file you sent me and created new zip : (named 3.zip):
and as you can see - the code works :
so I guess the dll is not powerful enough to recognize edge format
You can iterate on your zip object's ZipEntries - ZipEntry object contains IsDirectory property.
foreach(var entry in zip)
{
if(entry.IsDirectory)
{
//your stuff
}
}

Use content of FileUpload

I am attempting to add a file import function to an admin webpage where a CSV file will be imported from a local C: drive
I've just realized that string filePath = Path.GetFileName(FileUpload1.FileName); doesn't actually allow the client path to be read and only gives the filename.
protected void btnImportData_Click(object sender, EventArgs e)
{
List<CSVFile> entries = new List<CSVFile>();
string filePath = Path.GetFileName(FileUpload1.FileName);
using (TextFieldParser parser = new TextFieldParser(filePath))
{
//Other code
}
}
Currently the line TextFieldParser parser = new TextFieldParser(filePath) gives an error as I can't get the full path to the CSV.
Is it possible to load the contents of FileUpload1 into variable parser instead? I can see the control has content but not sure how or if it's possible?
The FileName property is simply the filename the browser sent, and is not yet physically stored on the server. To do so, you'll need to save it first:
string filePath = String.Format({0}{1}", System.IO.Path.GetTempPath(), FileUpload1.FileName); // Save to temp directory
FileUpload1.SaveAs(filePath);
using (TextFieldParser parser = new TextFieldParser(filePath))
{
//...
}
File.Delete(filePath); // Delete the file if you're done with it
Also, if TextFieldParser can take in a System.IO.Stream, you won't even need to save the file to disk first:
using (TextFieldParser parser = new TextFieldParser(FileUpload1.FileContent)) // Read stream
{
//...
}
Take into account that the file is not stored yet on the server so there is no path. FileName is just that: a file name and not a full path.
If you require the file to exist on the file system in order to parse it, you'll need to first save it.

Categories