C#释放内嵌的资源文件到指定位置(几种情况的讨论)

简介: C#释放内嵌的资源文件到指定位置(几种情况的讨论)

有时候写小程序我们只希望输出的程序只有一个exe文件而不希望附带其它任何东西。在C#中我们可以内嵌资源文件,并在程序运行时释放。下面通过几种情况来讨论资源文件释放方法。

通常C#中我们不仅可以直接内嵌资源文件,还可以通过resx资源文件添加并内嵌资源。下面就这两种情况一一讨论。

1,直接内嵌的资源文件

可以看到我们引用过得资源文件都会放到项目的Resources文件夹下:

网络异常,图片无法展示
|

右键资源文件-属性:

网络异常,图片无法展示
|

在下面属性窗格-生成的操作设置为嵌入的文件:

网络异常,图片无法展示
|

这样生成的程序,文件就会嵌入进去了!上面我把Resources文件夹里面的tada.wav设置为嵌入并释放。

先写一个释放嵌入文件的函数,到时候调用即可:

/// <summary>/// 释放内嵌资源至指定位置/// </summary>/// <param name="resource">嵌入的资源,此参数写作:命名空间.文件夹名.文件名.扩展名</param>/// <param name="path">释放到位置</param>privatevoidExtractFile(Stringresource, Stringpath)
{
Assemblyassembly=Assembly.GetExecutingAssembly();
BufferedStreaminput=newBufferedStream(assembly.GetManifestResourceStream(resource));
FileStreamoutput=newFileStream(path, FileMode.Create);
byte[] data=newbyte[1024];
intlengthEachRead;
while ((lengthEachRead=input.Read(data, 0, data.Length)) >0)
    {
output.Write(data, 0, lengthEachRead);
    }
output.Flush();
output.Close();
}

原理是通过Assembly来读取资源为缓冲流,再通过文件流写入。这个函数用于释放直接嵌入的文件,那么怎么读取到嵌入的文件呢?看到assembly.GetManifestResourceStream这个函数就是读取资源文件,里面参数是资源文件位置。嵌入的资源文件位置表示方法为:项目默认命名空间.文件夹.文件.扩展名。如果文件直接在项目根目录下(即和代码源文件同目录下),就是:默认命名空间.文件名.扩展名

例如上图中,我把tada.wav设置为嵌入,我们知道它在项目文件夹中的位置是:Resources\tada.wav,项目命名空间为:测试的WinForm程序,我要把它提取到D:\out.wav,那么调用这个函数就这么写:

ExtractFile("测试的WinForm程序.Resources.tada.wav", "D:\\out.wav");

这时,你就发现资源文件已经释放了!

我们也可以手动在项目目录下放入资源文件或者创建文件夹,调用它们后就会显示在项目里面,通过上述操作设置为嵌入,同样的方法可以抽取出来。

2,通过resx资源文件内嵌的资源文件

C#中除了直接内嵌资源,还可以通过新建一个resx资源文件,并把文件添加进去。resx文件就是记录储存资源文件的文件,添加的文件就会记录进这个文件,编译时相应的文件就会嵌入进exe里面去(默认情况下resx文件属性中生成的操作是嵌入)。

项目-添加新项-资源文件即可新建资源文件,双击资源文件即可编辑,我们可以向resx资源文件里面添加文件。

网络异常,图片无法展示
|

网络异常,图片无法展示
|

可见资源文件其实在工程里也被抽象成了一个类,添加进的每个资源文件也被抽象成了一个静态对象,代码中可以直接调用:

网络异常,图片无法展示
|

在代码中要想使用资源文件,直接通过资源类名.文件名的方式即可调用。 (例如我这里:res.aaas

不过要想调用他们,我们必须知道抽象为代码的文件到底是什么类型。经研究可分为下列情况:

(1)普通类型文件

添加进去的资源文件一般都会被抽象成byte[]类型对象,我们写一个函数实现提取出来:

/// <summary>/// 释放resx里面的普通类型文件/// </summary>/// <param name="resource">resx里面的资源</param>/// <param name="path">释放到的路径</param>privatevoidExtractNormalFileInResx(byte[] resource, Stringpath)
{
FileStreamfile=newFileStream(path, FileMode.Create);
file.Write(resource, 0, resource.Length);
file.Flush();
file.Close();
}

直接调用资源类里面的字节数组输出即可。例如我要把res.resx里面的a.txt输出到D:\a.txt,就这样调用该函数:

ExtractNormalFileInResx(res.a, "D:\\a.txt");

(2)音频文件

添加进去的音频文件都被抽象为了UnmanagedMemoryStream类型,这里专门写一个函数来提取音频文件:

/// <summary>/// 释放resx文件里面的音频资源文件/// </summary>/// <param name="fileInResx">在resx里面的音频文件</param>/// <param name="path">释放到的路径</param>privatevoidExtractAudioFileInResx(StreamfileInResx, Stringpath)
{
Streaminput=fileInResx;
FileStreamoutput=newFileStream(path, FileMode.Create);
byte[] data=newbyte[1024];
intlengthEachRead;
while ((lengthEachRead=input.Read(data, 0, data.Length)) >0)
    {
output.Write(data, 0, lengthEachRead);
    }
output.Flush();
output.Close();
}

通过文件流读取并输出,实现文件提取。

调用函数方式同上。

(3)图像文件

每个添加进resx文件的图片文件都被抽象为了BitMap类型。

这里专门写一个函数提取图片文件:

/// <summary>/// 释放resx里的图片资源文件/// </summary>/// <param name="image">resx里的图片资源</param>/// <param name="path">释放到的路径</param>privatevoidExtractImageFileInResx(Bitmapimage, Stringpath)
{
MemoryStreammemoryStream=newMemoryStream();
image.Save(memoryStream, image.RawFormat);
byte[] data=memoryStream.ToArray();
FileStreamfile=newFileStream(path, FileMode.Create);
file.Write(data, 0, data.Length);
file.Flush();
file.Close();
}

主要是先把BitMap对象转为流,这样就通过文件流就能输出了!

(4) 文本文件

文本文件直接变为字符串string形式储存,输出为文本文件就很简单了,这里不再赘述。

相关文章
|
存储 C#
C#资源文件和C#枚举如何结合使用?
最近悟出来一个道理,在这儿分享给大家:学历代表你的过去,能力代表你的现在,学习代表你的将来。我们都知道计算机技术发展日新月异,速度惊人的快,你我稍不留神,就会被慢慢淘汰!因此:每日不间断的学习是避免被淘汰的不二法宝。
1369 0
|
C#
C#资源文件与与资源名称字符串之间的互相转化
原文:C#资源文件与与资源名称字符串之间的互相转化 1.使用ResourceManager string st = Properties.Resources.ResourceManager.GetString(tableName);value = Properties.
1078 0
|
C# 区块链 安全
C#图片存到资源文件,以及调用图片
版权声明:欢迎评论和转载,转载请注明来源。 https://blog.csdn.net/zy332719794/article/details/8971154 在程序中会用到图片,有两种方法,一种是将图片放在运行文件夹中,直接调用,另一种是将图片放入资源文件中。
1202 0
|
3月前
|
开发框架 前端开发 .NET
C#编程与Web开发
【4月更文挑战第21天】本文探讨了C#在Web开发中的应用,包括使用ASP.NET框架、MVC模式、Web API和Entity Framework。C#作为.NET框架的主要语言,结合这些工具,能创建动态、高效的Web应用。实际案例涉及企业级应用、电子商务和社交媒体平台。尽管面临竞争和挑战,但C#在Web开发领域的前景将持续拓展。
150 3
|
3月前
|
SQL 开发框架 安全
C#编程与多线程处理
【4月更文挑战第21天】探索C#多线程处理,提升程序性能与响应性。了解C#中的Thread、Task类及Async/Await关键字,掌握线程同步与安全,实践并发计算、网络服务及UI优化。跟随未来发展趋势,利用C#打造高效应用。
162 3
|
15天前
|
存储 C#
揭秘C#.Net编程秘宝:结构体类型Struct,让你的数据结构秒变高效战斗机,编程界的新星就是你!
【8月更文挑战第4天】在C#编程中,结构体(`struct`)是一种整合多种数据类型的复合数据类型。与类不同,结构体是值类型,意味着数据被直接复制而非引用。这使其适合表示小型、固定的数据结构如点坐标。结构体默认私有成员且不可变,除非明确指定。通过`struct`关键字定义,可以包含字段、构造函数及方法。例如,定义一个表示二维点的结构体,并实现计算距离原点的方法。使用时如同普通类型,可通过实例化并调用其成员。设计时推荐保持结构体不可变以避免副作用,并注意装箱拆箱可能导致的性能影响。掌握结构体有助于构建高效的应用程序。
39 7
|
1天前
|
安全 C# 开发者
【C# 多线程编程陷阱揭秘】:小心!那些让你的程序瞬间崩溃的多线程数据同步异常问题,看完这篇你就能轻松应对!
【8月更文挑战第18天】多线程编程对现代软件开发至关重要,特别是在追求高性能和响应性方面。然而,它也带来了数据同步异常等挑战。本文通过一个简单的计数器示例展示了当多个线程无序地访问共享资源时可能出现的问题,并介绍了如何使用 `lock` 语句来确保线程安全。此外,还提到了其他同步工具如 `Monitor` 和 `Semaphore`,帮助开发者实现更高效的数据同步策略,以达到既保证数据一致性又维持良好性能的目标。
7 0