Resource from assembly as a stream - c#

I have an image in a C# WPF app whose build action is set to 'Resource'. It's just a file in the source directory, it hasn't been added to the app's resource collection through the drag/drop properties dialog. I'm trying to write it as a stream, but I can't open it despite trying quite a few variations of dots, slashes, namespaces and seemingly everything else.
I can access it to use elsewhere either in xaml with "pack://application:,,,/Resources/images/flags/tr.png", but I can't get at a stream containing it.
Most places seem to say use
using(BinaryReader reader = new BinaryReader(System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("ResourceBlenderExpress.Resources.images.flags.tr.png"))) {
using(BinaryWriter writer = new BinaryWriter(File.OpenWrite(imageFile))) {
while((read = reader.Read(buffer, 0, buffer.Length)) > 0) {
writer.Write(buffer, 0, read);
}
writer.Close();
}
reader.Close();
}
Which I haven't had any luck with.

You're probably looking for Application.GetResourceStream
StreamResourceInfo sri = Application.GetResourceStream(new Uri("Images/foo.png"));
if (sri != null)
{
using (Stream s = sri.Stream)
{
// Do something with the stream...
}
}

GetManifestResourceStream is for traditional .NET resources i.e. those referenced in RESX files. These are not the same as WPF resources i.e. those added with a build action of Resource. To access these you should use Application.GetResourceStream, passing in the appropriate pack: URI. This returns a StreamResourceInfo object, which has a Stream property to access the resource's data.

If I get you right, you have a problem to open the resource stream, because you do not know its exact name? If so, you could use
System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceNames()
to get a list of names of all included resources. This way you can find the resource name that was assignd to your image.

There's no need to call the Close() method, it will be automatically called by Dispose() at the end of the using clause. So your code might look like this:
using(BinaryReader reader = new BinaryReader(System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("ResourceBlenderExpress.Resources.images.flags.tr.png")))
using(BinaryWriter writer = new BinaryWriter(File.OpenWrite(imageFile)))
{
while((read = reader.Read(buffer, 0, buffer.Length)) > 0)
{
writer.Write(buffer, 0, read);
}
}

Related

finding file in root of wpf application

I'm trying to load a file with pack://application: The file is situated in the root of my project but I keep getting a null reference error. However When I do an absolute reference it finds the file and loads just fine.
What am I missing here?
This doesn't work
var txt = Application.GetContentStream(new Uri(#"pack://application:,,,/Layout.xml"));
string full = new StreamReader(txt.Stream).ReadToEnd();
or any variation with Pack://Application,,,/
This works, but I don't want to use it and seems bad practice anyway
var path = AppDomain.CurrentDomain.BaseDirectory.Substring(0, (AppDomain.CurrentDomain.BaseDirectory.Length - 10));
var txt = path + #"Layout.xml";
string full = new StreamReader(txt).ReadToEnd();
First, ensure that the file is definitely copied into your output ./bin/ directory on compile:
This worked perfectly for me in my WPF application:
const string imagePath = #"pack://application:,,,/Test.txt";
StreamResourceInfo imageInfo = Application.GetResourceStream(new Uri(imagePath));
byte[] imageBytes = ReadFully(imageInfo.Stream);
If you want to read it as binary (e.g. read an image file), you'll need this helper function. You probably won't need this, as you're reading an .xml file.
public static byte[] ReadFully(Stream input)
{
byte[] buffer = new byte[16 * 1024];
using (MemoryStream ms = new MemoryStream())
{
int read;
while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, read);
}
return ms.ToArray();
}
}
For more, see Microsoft on Pack URIs in WPF.
I'm not familiar with the way you are trying to achieve this. I use to solve this kind of problem differently:
First, embed the file you are trying to access in you application. This is done by setting the Build-Step-Property of the File (Properties-Window, when file is selected in VS) to Embedded Resource.
In your application, you can recieve a stream to that resource like that:
var stream = this.GetType().Assembly.GetManifestResourceStream("Namespace.yourfile.txt");
If you are unsure of the string you have to pass to GetManifestResourceStream(..), you can inspect what embedded resources are available and look for the one that is accociated with your file like so:
var embeddedResources = this.GetType().Assembly.GetManifestResourceNames()

How to create a log file that logs the detail of each file copied in C#?

I m developing an application that reads files from a remote server and copies it onto the local drive.
The code I m using to read and write the file is -
string saveTo1 = savePath + #"\" + filename[i];
byte[] buffer = new byte[32768];
using (Stream input = getResponse.GetResponseStream())
{
using (FileStream output = new FileStream(saveTo1, FileMode.OpenOrCreate))
{
int bytesRead;
while ((bytesRead = input.Read(buffer, 0, buffer.Length)) > 0)
{
output.Write(buffer, 0, bytesRead);
}
output.Close();
}
}
How can I create a log file that keeps track of the details of file copy and also records if there is any error while copying the files?
Thanks in advance :)
You can log in different ways.
EventLogger (as already suggested)
Custom file log (as already
answered)
Log Engine: I suggest you
log4net. It's very powerfull
and highly customizable.
Any way, I would shape the code in this way, where MyLogManager implement one of the previous solutions:
string saveTo1 = savePath + #"\" + filename[i];
byte[] buffer = new byte[32768];
try
{
using (Stream input = getResponse.GetResponseStream())
{
using (FileStream output = new FileStream(saveTo1, FileMode.OpenOrCreate))
{
int bytesRead;
while ((bytesRead = input.Read(buffer, 0, buffer.Length)) > 0)
{
output.Write(buffer, 0, bytesRead);
}
output.Close();
}
}
//logging good news and info
MyLogManager("Good news", FileDetails);
}
catch(Exception ex)
{
//logging bad news and exceptions info
MyLogManager("Bad news", ExceptionDetails);
}
Yes it is perfectly possible. Just create a file using the system.io file operations and for each file copied you open the log file and add a line. If you have an exception then rather than throwing it and breaking the application you can simply copy the exception details to the log file.
I would prefer to use this approach as you can tailor it to do exactly what you want.
there are so many logging framework available on the net. I would suggest NLog. Download and include it in ur Project.
You can do the following method,
try
{
//Write your code here
//OnSuccess : NLogger.Debug("file copied")
}
catch(Exception)
{
NLogger.Error("Exception Details");
}
There are advantages using NLog which takes care of Archival, File handles, etc.
What you are desiring is a simple log. You can make it more useful.
Check here:
.NET Logging Tools and Libraries

Using unseakable stream more than once

using (var stream = GetS3ObjectStream(fooObj))
{
WriteStreamToFtp(stream, "ftp://firstserver");
WriteStreamToFtp(stream, "ftp://SecondServer");
}
First one would work, but the second one will create just an empty file
GetS3ObjectStream gets a stream for Amazon Simple storage object. It's unseakable stream and you can't change the cursor position in it.
Now, I either have to somehow restrict to use the stream object more than once or I have to to move the cursor to the beginning.
any ideas?
upd: yeah of course you can simply save the stream in temp. variable, but if you don't wanna do that, what then? is it ok to make methods that take streams and leave them with such side-effects?
what if I close and dispose the source stream in the method?
You can either re-create your stream or buffer it into a byte[] or MemoryStream before use.
Edit: I forgot to mention a solution which does not buffer:
Open the two destination streams
Open the source stream
Until the source is drained, read a buffer of N bytes and write the buffer to both destination streams (you can even do the writing in parallel using Parallel.Invoke())
Here’s an example of how it may be done reading the stream just once (without initializing a temporary copy of the stream’s contents).
This assumes that you can replace your WriteStreamToFtp call with access to the actual target stream. Note that the FtpStream constructor is placeholder code.
using (var source = GetS3ObjectStream(fooObj))
using (var target1 = new FtpStream("ftp://firstserver"))
using (var target2 = new FtpStream("ftp://SecondServer"))
{
byte[] buffer = new byte[1024];
while (true)
{
int count = source.Read(buffer, 0, buffer.Length);
if (count == 0)
break;
target1.Write(buffer, 0, count);
target2.Write(buffer, 0, count);
}
}

Download Files From Resource Library in c# .net

I am developing an application where from several screens user has to download a sample file(excel) to work with. What will be the preferable way to do so.
What i am doing is
Placing the file in the directory where application is executing and download the files using Application.StartupPath. This does not sounds like a very good solution. As at anytime user could edit the files or delete the files or such things.
What i want to do is
I want to add all the files in my resources and download files from the resources. I add the files but i need a little help on how to download it from resources.
Thanks
you can use:
class ResourceHelper
{
public static void MakeFileOutOfAStream(string stream, string filePath)
{
using(var fs = new FileStream(filePath,FileMode.Create,FileAccess.ReadWrite))
{
CopyStream(GetStream(stream), fs);
}
}
static void CopyStream(Stream input, Stream output)
{
byte[] buffer = new byte[32768];
int read;
while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
{
output.Write(buffer, 0, read);
}
}
static Stream GetStream(string stream)
{
return Assembly.GetExecutingAssembly().GetManifestResourceStream(stream));
}
}
and with stream pass the complete name of you resource, that is the namespace + the resource file name ( evantual folder are to be considered as namespace part ) case sensitive. Remember to flag the file in your project as embedded resource.
You can use Assembly.GetManifestResourceStream and save the stream in some file to work with it.
Here is a simple example:
using (var resource = Assembly.GetManifestResourceStream("resource_key"))
using (var file = File.OpenWrite(filename))
{
var buffer = new byte[1024];
int len;
while ((len = resource.Read(buffer, 0, buffer.Length)) > 0)
{
file.Write(buffer, 0, len);
}
}
Please note. There is no way to store the file changes back to the resources.

Convert a Stream to a FileStream in C#

What is the best method to convert a Stream to a FileStream using C#.
The function I am working on has a Stream passed to it containing uploaded data, and I need to be able to perform stream.Read(), stream.Seek() methods which are methods of the FileStream type.
A simple cast does not work, so I'm asking here for help.
Read and Seek are methods on the Stream type, not just FileStream. It's just that not every stream supports them. (Personally I prefer using the Position property over calling Seek, but they boil down to the same thing.)
If you would prefer having the data in memory over dumping it to a file, why not just read it all into a MemoryStream? That supports seeking. For example:
public static MemoryStream CopyToMemory(Stream input)
{
// It won't matter if we throw an exception during this method;
// we don't *really* need to dispose of the MemoryStream, and the
// caller should dispose of the input stream
MemoryStream ret = new MemoryStream();
byte[] buffer = new byte[8192];
int bytesRead;
while ((bytesRead = input.Read(buffer, 0, buffer.Length)) > 0)
{
ret.Write(buffer, 0, bytesRead);
}
// Rewind ready for reading (typical scenario)
ret.Position = 0;
return ret;
}
Use:
using (Stream input = ...)
{
using (Stream memory = CopyToMemory(input))
{
// Seek around in memory to your heart's content
}
}
This is similar to using the Stream.CopyTo method introduced in .NET 4.
If you actually want to write to the file system, you could do something similar that first writes to the file then rewinds the stream... but then you'll need to take care of deleting it afterwards, to avoid littering your disk with files.

Categories

Resources