【问题标题】:Is it possible to store a file in a C# project and create it when needed?是否可以将文件存储在 C# 项目中并在需要时创建它?
【发布时间】:2020-11-02 17:35:12
【问题描述】:

我只是想知道是否可以将文件存储在 C# (Winform) 项目中并在需要时创建它? 基本场景:我的项目使用数据库文件来存储数据(简单访问 .mdb 文件),如果打开 exe 时它不存在,它将创建存储的文件,以便用户仍然可以使用该程序。 (我需要那个数据库文件,一个简单的 txt 不适合,它是我考试的存储管理器应用程序)

我什至不知道如何搜索它,它可能不可能。我不能使用网站下载备份文件,考试不允许。

【问题讨论】:

  • 是的,您可以在项目中包含其他文件。项目 -> 添加 -> 现有项目 -> 所有文件类型 -> 浏览到您的文件
  • 我如何为用户创建它? if !File.Exist("database.mdb") { /*这里怎么做?*/ }
  • 只需提前创建并添加到您的项目中。否则,我不确定我是否理解这个问题。您要存储文件还是创建文件?
  • 您可以在您的项目中添加一个文件夹,将其命名为DataBases(或其他不使用保留字\术语的名称),右键单击该文件夹 -> 添加现有项目。选择您的数据库。在解决方案资源管理器中选择新项目:在其属性中,设置 Build Action = none 和 Copy to OutputDirectory = Copy if newer。每次在 DataBases 文件夹(Debug\DatabasesRelease\Databases)中构建项目时,如果没有更新的副本,就会创建您的数据库。
  • 对于数据库的特殊情况,我不会将默认值与程序捆绑在一起,我只需要从头开始创建它所需的脚本(这将是一堆CREATE TABLE 指令)和在需要创建数据库时运行。这也非常适合更新现有数据库的结构(迁移)。

标签: c# database winforms ms-access


【解决方案1】:

是的,有可能。

您可以通过将文件设置为嵌入式资源来将文件存储在 Dll 或可执行文件中。因此,将文件添加到您的项目中,然后在 Visual Studio 中单击它并在属性窗格中将其构建操作从“内容”更改为“嵌入资源”

当您编译程序时,这将导致文件包含在二进制文件的可执行文件或 Dll 的资源部分中。

在您的代码中,您可以通过 System.Reflection 命名空间中的 Assembly 类访问嵌入的资源。该方法称为“GetManifestResourceStream”,它是一个实例化方法。因此,您需要获取对嵌入资源所在的程序集的引用。如果它在当前可执行文件中,只需使用 System.Reflection.Assembly.GetEntryAssembly()。

GetManifestResourceStream 方法接受嵌入资源名称的名称。该名称由您作为嵌入资源添加的文件的命名空间决定。因此,如果您将文件放在项目的根目录中,那么它将是项目默认命名空间加上文件名的任何内容。

假设您添加了“trees.png”并将其放在项目根目录中名为“Images”的文件夹中。现在假设项目根命名空间是 XYZ.ImageEditor。因此,提供给 GetManifestResourceStream 的嵌入资源的名称将是“XYZ.ImageEditor.Images.trees.png”。

还有一个名为 GetManifestResourceNames() 的方法将返回程序集中嵌入的所有资源名称的列表,因此会在此列表中返回 tree.png 的全名。您可以使用它来枚举嵌入在程序集中的文件。

一旦你有了资源流,你可以使用 System.IO.File.WriteAllText 或 System.IO.File.WriteAllBinary 等将其写入文件。或者手动打开文件流并从读取的字节写入它资源流。这部分有很多不同的方法。

【讨论】:

  • 查看另一个答案,因为 c# 中内置了一个资源系统,该系统通过程序集属性自动将资源公开给您的代码。它会生成一个 Resources.resx 文件,该文件会为您生成资源代码,因此您可以通过“XYZ.MyNamespaceHere.Resources.TreePNG”访问它们,其中 TreePNG 是您提供资源的键。
  • 好吧,但我不明白如何在 exe 旁边创建或复制 png 不存在时,因为用户删除或其他东西。 (或我场景中的数据库)它们是否类似于 File.CreateFile(Resources.MyFile) ?
  • 为什么用户会删除它而不是exe?如果您认为用户随机讨厌 mdb 文件,只需将 db 的副本重命名为 data.dll,然后如果您发现真正的 database.mdb 丢失,请将文件复制 data.dll 到 database.mdb..
  • 数据库文件不能在 C:\Program File\ MyProgram 因为写入权限,所以它被放置到 %AppData% 并且如果用户在他的窗口中切换到另一个配置文件数据库将丢失。
  • @North5014 - 是的,数据文件不应该在 %ProgramFiles% 中,因为那里的权限,但您的应用可以将其放入 %ProgramData% 中。
【解决方案2】:

你要找的东西叫Resources,资源是外部资源,比如图标或背景图片等。

也许这可能会有所帮助: https://docs.microsoft.com/en-us/dotnet/framework/resources/creating-resource-files-for-desktop-apps

【讨论】:

    【解决方案3】:

    您可以将文件作为嵌入式资源添加到项目中。 在运行时,如果文件丢失,您可以从资源中获取流并使用该流写入文件。

    [编辑] 将您的文件作为现有文件添加到项目中,并将其构建操作设置为“嵌入式资源”。 请注意默认命名空间。这将是您的资源的前缀。这里的项目是 CreateFileIfMissing。

        string filename = "test.png";
        if ( System.IO.File.Exists( filename ) == false )
        {
            var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream( $"CreateFileIfMissing.{filename}" );
            using ( var fileStream = System.IO.File.Create( filename ) )
            {
                stream.CopyTo( fileStream );
            }
        }
    

    【讨论】:

    • "在运行时,如果文件丢失,您可以从资源中获取一个流并使用该流来写入文件" 您能给我看一个示例代码吗?我会非常感激。
    • @North5014 - Stack Overflow 不是代码编写服务。尝试使用您在此处的答案中给出的建议来创建您自己的代码,该代码 (1) 检查磁盘上是否存在文件,以及 (2) 如果不存在,则从您的应用程序中保存文件(资源)。如果您遇到困难,请ask a new question 展示您尝试过的方法并详细说明它是如何不起作用的。
    • 至少你可以告诉我命令名称@GordThompson
    • 我们甚至没有讨论检查 file.exist 是否存在,而是从资源写入磁盘...@GordThompson 你真的不是来帮助我的,只是有毒。
    猜你喜欢
    • 1970-01-01
    • 2017-06-15
    • 1970-01-01
    • 1970-01-01
    • 2012-02-23
    • 1970-01-01
    • 2015-08-17
    • 2020-03-27
    • 2012-06-01
    相关资源
    最近更新 更多