I have embed sample.txt(it contains just one line "aaaa" ) file into project's resources like in this answer.
When I'm trying to read it like this:
string s = File.ReadAllText(global::ConsoleApplication.Properties.Resources.sample);
I'm getting System.IO.FileNotFoundException' exception.
Additional information: Could not find file 'd:\Work\Projects\MyTests\ConsoleApplication\ConsoleApplication\bin\Debug\aaaa'.
So seemingly it's trying to take file name from my resource file instead of reading this file. Why is this happening? And how can I make it read sample.txt
Trying solution of #Ryios and getting Argument null exception
using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("ConsoleApplication.Resources.sample.txt"))
{
TextReader tr = new StreamReader(stream);
string fileContents = tr.ReadToEnd();
}
The file is located in d:\Work\Projects\MyTests\ConsoleApplication\ConsoleApplication\Resources\sample.txt
p.s. Solved. I had to set Build Action - embed resource in sample.txt properties
You can't read Resource Files with File.ReadAllText.
Instead you need to open a Resource Stream with Assembly.GetManifestResourceStream.
You don't pass it a path either, you pass it a namespace. The namespace of the file will be the Assemblies Default Namespace + The folder heieracy in the project the file is in + the name of the file.
Imagine this structure
Project (xyz.project)
Folder1
Folder2
SomeFile.Txt
So the namespace for the file will be:
xyz.project.Folder1.Folder2.SomeFile.Txt
Then you would read it like so
using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("xyz.project.Folder1.Folder2.SomeFile.Txt"))
{
TextReader tr = new StreamReader(stream);
string fileContents = tr.ReadToEnd();
}
Hello the proposed solution doesn't work
This return null:
Assembly.GetExecutingAssembly().GetManifestResourceStream("xyz.project.Folder1.Folder2.SomeFile.Txt")
Another way is to use a MemoryStream from the Ressource Data:
byte[] aa = Properties.Resources.YOURRESSOURCENAME;
MemoryStream MS =new MemoryStream(aa);
StreamReader sr = new StreamReader(MS);
Not ideal but it works
Related
I have tried multiple solutions on here but non of them I can get to work. All i want to do is read a text file from my resources folder rather than the actual local folder.
File name: TextFile.txt
Set to embedded resource.
"Local File" Code that works:
string[] spaces = File.ReadAllLines("C:\\Users\\a\\source\\repos\\a\\bin\\Debug\\TextFile.txt");
Current Code:
var assembly = Assembly.GetExecutingAssembly();
var resourceName = "TextFile.txt";
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
using (StreamReader reader = new StreamReader(stream))
{
string result = reader.ReadToEnd();
}
string[] spaces = File.ReadAllLines(resourceName);
But I am getting the following error:
System.ArgumentNullException: 'Value cannot be null.
Parameter name: stream'
On this line:
using (StreamReader reader = new StreamReader(stream))
EDIT1 Tried this as per link (Why does GetManifestResourceStream returns null while the resource name exists when calling GetManifestResourceNames?) and this NULL ERROR:
var assembly = Assembly.GetExecutingAssembly();
var resourceName = "programname.TextFile.txt";
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
using (StreamReader reader = new StreamReader(stream))
{
string result = reader.ReadToEnd();
}
string[] spaces = File.ReadAllLines(resourceName);
Same error, am I putting the namespace bit in the wrong place?
Edit 2, tried this:
var assembly = Assembly.GetExecutingAssembly();
var resourceName = "programname.Resources.TextFile.txt";
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
using (StreamReader reader = new StreamReader(stream))
{
string result = reader.ReadToEnd();
}
string[] spaces = File.ReadAllLines(resourceName);
New error:
System.IO.FileNotFoundException: 'Could not find file 'C:\Users\a\source\repos\a\bin\Debug\programname.Resources.TextFile.txt'.'
Location of TextFile.txt
programname
Resources
TextFile.txt
Got this to work by opening Resources.resx, Setting Access Modifier to Public Then adding the file in there.
Then replaced:
string[] spaces = File.ReadAllLines("C:\\Users\\a\\source\\repos\\a\\bin\\Debug\\TextFile.txt")
With:
var resourceText = Properties.Resources.TextFile;
var Lines= resourceText.Replace("\r", "").Split('\n');
A little background:
MSDN:
If you add a resource to your project in the normal way, it will
automatically provide a typesafe wrapper for that resource.
For example, in the Solution Explorer, expand the "Properties" node
and double click the "Resources.resx" entry. Then add an image via the
"Add Resource" button. Give that resource a name, say "MyImage".
You will then be able to programmatically access that image via
"Properties.Resources.MyImage"
This is the simple and recommended way; it will let you edit the name in the resource file and will check while coding that the name is correct.
Note that the names are stripped of the extension and, as other c# names, are case-sensitive!
The other way doesn't register the resources with the .resx file but only add them to the resource folder and marks them as embedded.
To use them you can't use a code as simple as the one above. Instead you need to find out the name (Intellisense will not help you there) and them use calls to the Reflection namespace.
Note that here the names are __not_- stripped of the extension but still are case-sensitive!
Example:
If we don't know the exact name we can search in the assembly:
var assembly = System.Reflection.Assembly.GetExecutingAssembly();
var ress = assembly.GetManifestResourceNames()
.Where(x => x.Contains(somepattern)).First();
Usually the 1st way is much recommended. Typesafety and Intellisense support alone are well worth mainainting the resx file!
Now we can open a stream to read the resource:
List<string> results = new List<string>(); ;
using (Stream stream = assembly.GetManifestResourceStream(ress))
using (StreamReader reader = new StreamReader(stream))
{
while (reader.Peek()>=0) results.Add(reader.ReadLine());
}
This function will return the correct resource name for your file:
string resourceName = assembly.GetManifestResourceNames()
.Single(str => str.EndsWith("TextFile.txt"));
2nd issue:
For string[] spaces = File.ReadAllLines(resourceName);
You can't use the same resourceName (embedded resource). If you need to read text line by line use for example:
using (StreamReader reader = new StreamReader(stream))
{
while (reader.Peek() >= 0)
{
Console.WriteLine(reader.ReadLine());
}
}
I have added a resource file to my project (C#, windows service - TopShelp):
I have added a text file to the resource:
Now I want to read the test file, this is what I have tried:
ResourceManager rm = new ResourceManager("My.Project.Name.Resources", Assembly.GetExecutingAssembly());
It does not find anything, ResourceSets count = 0.
Update
As suggested in the comments, I also tried adding the resource under:
Project > Properties > Resources
And tried the following code, which did not find anything:
ResourceManager rm = new ResourceManager("My.Project.Name.Resources", Assembly.GetExecutingAssembly());
Check your Resources.Designer.cs file. You should have there static string property named stop_words_utf8 (or whatever name for the file you choose). You use it like this:
Resources.stop_words_utf8
It is static string property
You can always try:
var assembly = Assembly.GetExecutingAssembly();
var resourceName = "MyCompany.MyProduct.MyFile.txt";
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
using (StreamReader reader = new StreamReader(stream))
{
string result = reader.ReadToEnd();
}
Check that your file exists through Assembly.GetManifestResourceNames method.
Is it possible to attach a text file resource to my Winform exe. So when I run the "Form.exe" in another computer then it copy the text file to a specified folder. Please suggest a method to achieve the same. Thanks
If the resource name is a string:
var assembly = Assembly.GetExecutingAssembly();
using (var stream = assembly.GetManifestResourceStream(resourceName))
using (var reader = new StreamReader(stream))
{
string text = reader.ReadToEnd();
File.WriteAllText(fileName, text);
}
else:
File.WriteAllText(fileName, Properties.Resources.TextFile1);
And also make sure that you have set the Build Action of the resource file to "Embedded Resource".
First you need to add your file as a resource in your project.
This explains what to do
Then select your file and in the properties change the "Build Action" to "Embedded Resource". This will now embed your file in your output (.exe).
To extract the file you need to do the following;
String myProject = "Name of your project";
String file = "Name of your file to extract";
String outputPath = #"c:\path\to\your\output";
using (System.IO.Stream stream = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(myProject + ".Resources." + file))
{
using (System.IO.FileStream fileStream = new System.IO.FileStream(outputPath + "\\" + file, System.IO.FileMode.Create))
{
for (int i = 0; i < stream.Length; i++)
{
fileStream.WriteByte((byte)stream.ReadByte());
}
fileStream.Close();
}
}
Ideally you should check that the file does not already exist before you do this. Don't forget also to catch exceptions. Which can be very common when dealing with the file system.
Add the text file to your project resources
Properties -> Resources -> Add Resource
Read the data from the resource using
var text = Properties.Resources.textFile;
Write to the file with
File.WriteAllText(#"C:\test\testOut.txt", text);
I was wondering, if anyone could tell me how to point a StreamReader to a file inside the current working directory of the program.
E.g.: say I have program Prog saved in the directory "C:\ProgDir\". I commit "\ProgDir" to a shared folder. Inside ProgDir is another directory containing files I'd like to import into Prog (e.g. "\ProgDir\TestDir\TestFile.txt") I'd like to make it so that the StreamReader could read those TestFiles, even when the path to the directory has changed;
(E.G., on my computer, the path to the Testfiles is
C:\ProgDir\TestDir\TestFile.txt
but on the other person's computer, the directory is
C:\dev_code\ProgDir\TestDir\TestFile.txt
).
How would I get a StreamReader to be ale to read from TestFile.txt on the other person's computer? (to clarify, the filenames do not change, the only change is the path ProgDir)
I tried the following:
string currentDir = Environment.CurrentDirectory;
DirectoryInfo directory = new DirectoryInfo(currentDir);
FileInfo file = new FileInfo("TestFile.txt");
string fullDirectory = directory.FullName;
string fullFile = file.FullName;
StreamReader sr = new StreamReader(#fullDirectory + fullFile);
( pulled this from : Getting path relative to the current working directory?)
But I'm getting "TestFile does not exist in the current context". Anyone have any idea as to how I should approach this?
Thank you.
Is the Folder "TestDir" always in the executable directory?
if so, try this
string dir =System.IO.Path.GetDirectoryName(
System.Reflection.Assembly.GetExecutingAssembly().Location);
string file = dir + #"\TestDir\TestFile.txt";
This will give you the path of the exe plus the folder inside it and the textfile
You can use the GetFullPath() method. Try this:
string filePath = System.IO.Path.GetFullPath("TestFile.txt");
StreamReader sr = new StreamReader(filePath);
A few things:
First, FileInfo.FullName gives the absolute path for the file, so you don't need to prepend the full directory path before the file in the StreamReader instance.
Second, FileInfo file = new FileInfo(TestFile.txt); should fail unless you actually have a class called TestFile with a txt property.
Finally, with almost every File method, they use relative paths already. So you SHOULD be able to use the stream reader on JUST the relative path.
Give those few things a try and let us know.
Edit: Here's what you should try:
FileInfo file = new FileInfo("TestFile.txt");
StreamReader sr = new StreamReader(fullFile.FullName);
//OR
StreamReader sr = new StreamReader("TestFile.txt");
However, one thing I noticed is that the TestFile is located in TestDir. If your executable is located in ProgDir as you're stating, then this will still fail because your relative path isn't right.
Try changing it to TestDir\TestFile.txt instead. IE: StreamReader sr = new StreamReader("TestDir\TestFile.txt");
The FileInfo constructor takes a single parameter of type string. Try putting quotes around TestFile.txt.
Change
FileInfo file = new FileInfo(TestFile.txt);
to
FileInfo file = new FileInfo("TestFile.txt");
Unless TestFile is an object with a property named txt of type string, in which case you have to create the object before trying to use it.
The easiest way would be to just use the file name (not the full path) and "TestDir" and give the StreamReader a relative path.
var relativePath = Path.Combine(".","TestDir",fileName);
using (var sr = new StreamReader(relativePath))
{
//...
}
I had a similar issue and resolved it by using this method:
StreamReader sr = File.OpenText(MapPath("~/your_path/filename.txt"))
This could be a good option if you need a more relative path to the file for working with different environments.
You can use path.combine to get the current directory to build and then combine the file path you need
new StreamReader(Path.Combine(Environment.CurrentDirectory, "storage"));
System.IO.Path.GetDirectoryName(new System.Uri(System.Reflection.Assembly.GetExecutingAssembly().CodeBase).LocalPath)
How can I read from an embedded XML file - an XML file that is part of a c# project?
I've added a XML file to my project and I want to read from it. I want the XML file to compile with the project because I don't want that it will be a resource which the user can see.
Any idea?
Make sure the XML file is part of your .csproj project. (If you can see it in the solution explorer, you're good.)
Set the "Build Action" property for the XML file to "Embedded Resource".
Use the following code to retrieve the file contents at runtime:
public string GetResourceTextFile(string filename)
{
string result = string.Empty;
using (Stream stream = this.GetType().Assembly.
GetManifestResourceStream("assembly.folder."+filename))
{
using (StreamReader sr = new StreamReader(stream))
{
result = sr.ReadToEnd();
}
}
return result;
}
Whenever you want to read the file contents, just use
string fileContents = GetResourceTextFile("myXmlDoc.xml");
Note that "assembly.folder" should be replaced with the project name and folder containing the resource file.
Update
Actually, assembly.folder should be replaced by the namespace in which a class created in the same folder as the XML file would have by default. This is typically defaultNamespace.folder0.folder1.folder2......
You can also add the XML file as a Resource and then address its contents with Resources.YourXMLFilesResourceName (as a string, i.e. using a StringReader).
Set the Build Action to Embedded Resource, then write the following:
using (Stream stream = typeof(MyClass).Assembly.GetManifestResourceStream("MyNameSpace.Something.xml")) {
//Read the stream
}
You can use Reflector (free from http://www.red-gate.com/products/reflector/) to find the path to the embedded XML file.
Then, it's just a matter of
Assembly a = typeof(Assembly.Namespace.Class).Assembly;
Stream s = a.GetManifestResourceStream("Assembly.Namespace.Path.To.File.xml");
XmlDocument mappingFile = new XmlDocument();
mappingFile.Load(s);
s.Close();
Add the file to the project.
Set the "Build Action" property to "Embedded Resource".
Access it this way:
GetType().Module.Assembly.GetManifestResourceStream("namespace.folder.file.ext")
Notice that the resource name string is the name of the file,
including extension, preceded by the default namespace of the project.
If the resource is inside a folder, you also have to include it in the
string.
(from http://www.dotnet247.com/247reference/msgs/1/5704.aspx, but I used it pesonally)
#3Dave really helped (up vote given), however my resource helper was in a different assembly so I did the below
public string GetResourceFileText(string filename, string assemblyName)
{
string result = string.Empty;
using (Stream stream =
System.Reflection.Assembly.Load(assemblyName).GetManifestResourceStream($"{assemblyName}.{filename}"))
{
using (StreamReader sr = new StreamReader(stream))
{
result = sr.ReadToEnd();
}
}
return result;
}
Called by
GetResourceFileText("YourFileNameHere.ext", Assembly.GetExecutingAssembly().GetName().Name);