I am extracting some information from several text files in different folders. For that purpose I created an application with several Input Fields to write the folders' name that I want to go. Everything went well in Editor Mode.
However when I build the project and run the ".exe" file created, it can't find the text files I want. I show below the code I am using to extract the files. The first data.path is the one I used on my Editor and worked well while the second (commented) data.path is one trial that I tried by placing my folder on the ".exe" Data folder. But it didn't work...
data.motion = input_text;
data.subjectName = input_text2;
data.path = "C:/Users/Matias/Desktop/Acquisition_Data/Kinect1/" + data.subjectName + "/" + data.motion + ".txt";
/*data.path = Application.dataPath + "/Acquisition_Data/Kinect1/" + data.subjectName + "/" + data.motion + ".txt";*/
data.lines = System.IO.File.ReadAllLines(data.path);
I can't get any explanation why any of these methods work when I build the application.
I am using C# and running on Windows10.
You really can't do that because Unity encodes the files into binary form and renames them too. You have to move the txt file after building then you can access it directly. I answered similar question like this yesterday so I will post the link to the answer. Do do things I mentioned in this answer below.
Unity3D loading resources after build
Then remove the Texture2D stuff and replace File.ReadAllBytes(imagePath); with System.IO.File.ReadAllLines(data.path); and that should work.
This is the problem of using Relative path or using absolute path.
If absolute path doesn't work try relative path.
eg.
../name.txt
put your name.txt in asset or somewhere you can point with.
If your texts are static (never more, never less) then you could simply use TextAsset : http://docs.unity3d.com/ScriptReference/TextAsset.html
Make prefabs from text assets;
Put the prefabs into your scene;
Let the user what prefab(s) to load text(s) from.
Related
I'm trying to "ping" a Textfile in a custom editor in Unity3D like e.g. using EditorGUIUtility.PingObject (Shows the file in the Hierachy and flashes a yellow selection field over it).
The file is under Assets/StreamingAssets/Example.csv
The simplest solution (I thought) would be to simply show it in an ObjectField -> if clicking on the field the asset also gets "pinged".
so I'm trying:
// For debug, later the filename will be dynamic
var path = "Assets/StreamingAssets/" + "Example" + ".csv";
TextAsset file = (TextAsset)AssetDatabase.LoadAssetAtPath(path, typeof(TextAsset));
EditorGUILayout.PrefixLabel("CSV File", EditorStyles.boldLabel);
EditorGUILayout.ObjectField(file, typeof(TextAsset), false);
But though the file is there and the path correct, file is allways null
Unfortunately, your code is fine and this is a bug.
The bug occurs when the asset is placed in the StreamingAssets folder that is in the Assets folder. This causes the AssetDatabase.LoadAssetAtPath function to fail. I did search about this and only one post came up without any workaround. I mean you can use one of the API from the System.IO namespace to read the file but then you won't have access to the Object that references the file.
Possible Fix:
1.Restart Unity.
2.Create a folder named "Test" in the Assets folder.
3.Drag the StreamingAssets folder to this "Test" folder.
4.Change the path in the code to var path = "Assets/Test/StreamingAssets/" + "Example" + ".csv"; then click "Play". It should not be null. If it's no longer null, move the StreamingAssets folder back to the Assets folder and also change the path in code to the old path.
The steps above is how I fixed it on my side and it works now. If that doesn't work, I suggest you move the "Example.csv" file to the Assets folder then use var path = "Assets/" + "Example" + ".csv"; to read it. If it works, move it back to the StreamingAssets folder and change the path to the old path.
Another thing I suggest you do is call AssetDatabase.Refresh() to refresh the project.
I also suggest you file for bug report for this issue.
My mistake was the typecasting to TextAsset and using LoadAssetAtPath which requires a Type parameter.
Leaving it "uncasted" as object (asset) and using LoadMainAssetAtPath instead which doesn't require the Type parameter works now:
// For debug, later the filename will be dynamic
var path = "Assets/StreamingAssets/" + "Example" + ".csv";
var file = AssetDatabase.LoadMainAssetAtPath(path);
EditorGUILayout.PrefixLabel("CSV File", EditorStyles.boldLabel);
EditorGUILayout.ObjectField(file, typeof(object), false);
I am wondering how to remove the version number from a file path in a Windows Form Application.
Currently I wish to save some users application data to a .xml file located in the roaming user profile settings.
To do this I use:
get
{
return Application.UserAppDataPath + "\\FileName.xml";
}
However this returns the following string:
C:\Users\user\AppData\Roaming\folder\subfolder\1.0.0.0\FileName.xml
and I was wondering if there is a non-hack way to remove the version number from the file path so the file path looks like this:
C:\Users\user\AppData\Roaming\folder\subfolder\FileName.xml
Besides parsing the string looking for the last "\", I do not know what to do.
Thanks
Use Directory.GetParent method for this purpose.
get
{
var dir = Directory.GetParent(Application.UserAppDataPath);
return Path.Combine(dir.FullName, "FileName.xml");
}
Also note that I've used Path.Combine instead of concatenating paths, this method helps you to avoid so many problems. Never concatenate strings to create path.
I am making a program where I need 24 pictures and a text file. I have all the files on my computer, and I easily fetch them with this code:
pictureBox1.Image = Image.FromFile("C:/Users/myUser/Documents/myFolder/myPicture.jpg");
The problem is that this path is unique for my PC, not many have my username, if you have windows in a different languague if won't work either, and you would have to save the folder containing the program in documents.
What I need is in some way make the program search after the image files in the same folder where the program is, regardless where it is stored on the PC like this:
pictureBox1.Image = Image.FromFile("/myFolder/myPicture.jpg");
I think this is pretty basic, adding a picture to your program, in order to transfer it to other PCs, but I have not found the solution anywhere.
Seems like the problem is solved, is there any way to set it to solved?
Just omit the first /
pictureBox1.Image = Image.FromFile("myFolder/myPicture.jpg");
you can also do
pictureBox1.Image = Image.FromFile(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "/myFolder/myPicture.jpg");
You can use this :
string picPath = (AppDomain.CurrentDomain.BaseDirectory + "mypicture.jpg");
picPath is the same path as "your app directory" + "mypicure.jpg"
Use Environment.GetFolderPath.
It is documented here.
http://msdn.microsoft.com/en-us/library/system.environment.getfolderpath(v=vs.110).aspx
I have a log object that writes daily log files with a relative path. It's fairly simple (.NET 4.0, VS 2010).
public void LogLine(string txt)
{
DateTime dt = DateTime.Now;
if (CurrentDay != dt.Day)
{
string newFileName = "..\\Log\\" + programName + dt.Day + ".log";
fs = new FileStream(newFileName, FileMode.Create, FileAccess.Write);
sw = new StreamWriter(fs);
CurrentDay = dt.Day;
}
sw.WriteLine(txt);
}
This works well almost all the time. However, sometimes I get what seems to be a random DirectoryNotFoundException with a totally different path. For example, when I first run the program, it creates a file:
C:\MyFiles\Log\MyApp19.log
After using the program some and letting it run overnight so a new file and stream are created (at the first log after midnight), I come back to the DirectoryNotFoundException stating something like:
C:\MyFiles\MyOtherFiles\Resources\Log\MyApp20.log
The only thing that I can think of is: I use an OpenFileDialog and SaveFileDialog a couple times throughout the life of the software, and one of those open/save dialogs access a file within
C:\MyFiles\MyOtherFiles\Resources\SavedFiles\
So it seems to me that when I use the dialogs, I open/save something into the SavedFiles directory and when it creates the new log, the relative file path ..\ goes up to Resources (from SavedFiles), then can't find the directory Log within Resources and throws an exception. However, I can't reproduce the problem using dialogs, and I thought the relative path is relative to the executable? Can the Open/Save File Dialogs alter how the software calculates the relative file path? Anyone have any thoughts? Thanks for your time!
Alng i think that the following link can help you:
http://msdn.microsoft.com/en-us/library/system.windows.forms.filedialog.aspx
Pay attention to the following part:
Important:
If the user of your application changes the folder in the FileDialog, then the current working directory for your application is set to the location specified in the FileDialog. To prevent this, set the RestoreDirectory property to true.
Try to use the Microsoft proposed methodologies for paths as described in the above link.
This can help you also
http://msdn.microsoft.com/en-us/library/system.windows.forms.application.executablepath.aspx
regards
A relative path always works on the current directory of the application. That can easily change, for example when you show a save dialog.
It is always better to create a path relative to your executable.
var assembly = Assembly.GetEntryAssembly() ?? Assembly.GetCallingAssembly();
var path = Path.GetDirectoryName(assembly.Location);
newFileName = Path.Combine(path, "..\\Log\\" + programName + dt.Day + ".log");
I'm making a guess that the application changes the current working directory at some point. As a result, on that basis, I'd use a fully-qualified path for the log file. You could use the assembly's startup path, eg Application.StartupPath, which should not change even if the app changes folders for some reason.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Getting path relative to the current working directory?
I have code in C# that includes some images from an absolute path to a relative so the image can be found no matter where the application fold is located.
For example the path in my code (and in my laptop for the image) is
C:/something/res/images/image1.jpeg
and I want the path in my code to be
..../images/image1.jpeg
So it can run wherever the folder is put, whatever the name of the C: partition is etc.
I want to have a path in my code which is independant of the application folder location or if it is in another partition, as long as it is in the same folder as the the rest of the solution.
I have this code:
try
{
File.Delete("C:/JPD/SCRAT/Desktop/Project/Resources/images/image1.jpeg");
}
catch (Exception)
{
MessageBox.Show("File not found:C:/Users/JPD/Desktop/Project/images/image1.jpeg");
}
This code only runs if the file and folder are in that certain path, (which is also the location of the code) I wish for that path to be relative so wherever I put the whole folder (code, files etc) the program will still work as long as the code (which is under project folder) is at the same location with the folder images... what should I do?
Relative paths are based from the binary file from which your application is running. By default, your binary files will be outputted in the [directory of your .csproj]/bin/debug. So let's say you wanted to create your images folder at the same level as your .csproj. Then you could access your images using the relative path "../../images/someImage.jpg".
To get a better feel for this, try out the following as a test:
1) create a new visual studio sample project,
2) create an images folder at the same level as the .csproj
3) put some files in the images folder
4) put this sample code in your main method -
static void Main(string[] args)
{
Console.WriteLine(Directory.GetCurrentDirectory());
foreach (string s in Directory.EnumerateFiles("../../images/"))
{
Console.WriteLine(s);
}
Console.ReadLine(); // Just to keep the console from disappearing.
}
You should see the relative paths of all the files you placed in step (3).
see: Getting path relative to the current working directory?
Uri uri1 = new Uri(#"c:\foo\bar\blop\blap");
Uri uri2 = new Uri(#"c:\foo\bar\");
string relativePath = uri2.MakeRelativeUri(uri1).ToString();
Depending on the set up of your program, you might be able to simply use a relative path by skipping a part of the full path string. It's not braggable, so J. Skit might be up my shiny for it but I'm getting the impression that you simply want to make it work. Beauty being a later concern.
String absolutePath = #"c:\beep\boop\HereWeStart\hopp.gif";
String relativePath = absolutePath.Substring(13);
You could then, if you need/wish, exchange the number 13 (which is an ugly and undesirable approach, still working, though) for a dynamically computed one. For instance (assuming that the directory "HereWeStart", where your relative path is starting, is the first occurrence of that string in absolutePath) you could go as follows.
String absolutePath = #"c:\beep\boop\HereWeStart\hopp.gif";
int relativePathStartIndex = absolutePath.IndexOf("HereWeStart");
String relativePath = absolutePath.Substring(relativePathStartIndex);
Also, your question begs an other question. I'd like to know how you're obtaining the absolute path. Perhaps there's an even more clever way to avoid the hustle all together?
EDIT
You could also try the following approach. Forget the Directory class giving you an absolute path. Go for the relative path straight off. I'm assuming that all the files you're attempting to remove are in the same directory. If not, you'll need to add some more lines but we'll cross that bridge when we get there.
Don't forget to mark an answer as green-checked (or explain what's missing or improvable still).
String
deletableTarget = #"\images\image1.jpeg",
hereWeAre = Environment.CurrentDirectory;
MessageBox.Show("The taget path is:\n" + hereWeAre + deletableTarget);
try
{ File.Delete(hereWeAre + deletableTarget); }
catch (Exception exception)
{ MessageBox.Show(exception.Message); }
Also, please note that I took the liberty of changing your exception handling. While yours is working, it's a better style to rely on the built-in messaging system. That way you'll get more professionally looking error messages. Not that we ever get any errors at run-time, right? ;)