C#释放内嵌的资源文件到指定位置的方法
通常C#中我们不仅可以直接内嵌资源文件,还可以通过resx
资源文件添加并内嵌资源。下面就这两种情况一一讨论。
1,直接内嵌的资源文件
可以看到我们引用过得资源文件都会放到项目的Resources
文件夹下:
右键资源文件-属性:
在下面属性窗格-生成的操作设置为嵌入的文件:
这样生成的程序,文件就会嵌入进去了!上面我把Resources
文件夹里面的tada.wav
设置为嵌入并释放。
先写一个释放嵌入文件的函数,到时候调用即可:
/// <summary>
/// 释放内嵌资源至指定位置
/// </summary>
/// <param name="resource">嵌入的资源,此参数写作:命名空间.文件夹名.文件名.扩展名</param>
/// <param name="path">释放到位置</param>
private void ExtractFile(String resource, String path)
{
Assembly assembly = Assembly.GetExecutingAssembly();
BufferedStream input = new BufferedStream(assembly.GetManifestResourceStream(resource));
FileStream output = new FileStream(path, FileMode.Create);
byte[] data = new byte[1024];
int lengthEachRead;
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>
private void ExtractNormalFileInResx(byte[] resource, String path)
{
FileStream file = new FileStream(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>
private void ExtractAudioFileInResx(Stream fileInResx, String path)
{
Stream input = fileInResx;
FileStream output = new FileStream(path, FileMode.Create);
byte[] data = new byte[1024];
int lengthEachRead;
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>
private void ExtractImageFileInResx(Bitmap image, String path)
{
MemoryStream memoryStream = new MemoryStream();
image.Save(memoryStream, image.RawFormat);
byte[] data = memoryStream.ToArray();
FileStream file = new FileStream(path, FileMode.Create);
file.Write(data, 0, data.Length);
file.Flush();
file.Close();
}
主要是先把BitMap
对象转为流,这样就通过文件流就能输出了!
(4) 文本文件
文本文件直接变为字符串string
形式储存,输出为文本文件就很简单了。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!