2

到目前为止,我一直在应用我在 Bob Tabors 绝对初学者系列中学到的知识,并为我的女儿编写了一个小型控制台文字游戏,要求我生成一个随机的 5 个字母单词。

我以前File.ReadAllLines(path)用来从我系统上的文本文件 (wordlist.txt) 生成字符串数组,并Random.next生成我将从数组中提取的索引。

我从这里的一些帖子中了解到如何将文件作为资源嵌入,但现在我找不到指向它的语法(路径)。或者我现在必须以不同的方式访问它,因为它是嵌入的?

提前致谢

4

2 回答 2

7

如果没有一个好的、最小的完整的代码示例,就不可能提供具体的建议。

但是,基本问题是:当您将文件作为资源嵌入时,它不再是文件。也就是说,原始文件仍然存在,但资源本身无论如何都不是文件。它在您的程序集中存储为某种特定类型的数据;从文件源嵌入的资源通常以二进制数据对象的形式结束。

如何使用这些数据取决于您所说的“嵌入”是什么意思。在 C# 程序中存储资源实际上有两种常见的方法:您可以在项目中使用“Resources”对象,该对象通过项目的...Properties.Resources类(反过来使用ResourceManager.NET 中的类)公开资源。或者您可以简单地将文件添加到项目本身,然后选择“嵌入式资源”构建选项。

如果您使用的是“资源”设计器,那么您可能会通过几种不同的方式添加文件。一种是使用“新文本文件...”选项,它允许您将新文本复制/粘贴或键入资源中。这在代码中作为对象的string属性公开Properties.Resources。如果您使用“现有文件...”选项添加资源并选择 Visual Studio 识别为文本文件的文件,也会发生同样的事情。

否则,该文件将作为类byte[]中的属性公开的对象包含在内Properties.Resources

如果您使用了“嵌入式资源”构建选项而不是“资源”设计器,那么您的数据将通过调用Assembly.GetManifestResourceStream(string)方法获得,该方法返回一个Stream对象。可以将其包装起来StreamReader以允许逐行读取。

该方法的直接替换File.ReadAllLines(string)如下所示……

使用“嵌入式资源”:

string[] ReadAllResourceLines(string resourceName)
{
    using (Stream stream = Assembly.GetEntryAssembly()
        .GetManifestResourceStream(resourceName))
    using (StreamReader reader = new StreamReader(stream))
    {
        return EnumerateLines(reader).ToArray();
    }
}

IEnumerable<string> EnumerateLines(TextReader reader)
{
    string line;

    while ((line = reader.ReadLine()) != null)
    {
        yield return line;
    }
}

使用Properties.Resources

你可以在使用类时做类似的事情Properties.Resources。它看起来几乎相同:

string[] ReadAllResourceLines(string resourceText)
{
    using (StringReader reader = new StringReader(resourceText))
    {
        return EnumerateLines(reader).ToArray();
    }
}

称为 like string[] allLines = ReadAllResourceLines(Properties.Resources.MyTextFile);,其中MyTextFile是您在设计器中添加的资源的属性名称(即string您在第二个示例中传递的是文件本身的文本,而不是资源的名称)。

如果您添加了 Visual Studio 无法识别为文本文件的现有文件,则属性类型将byte[]改为,string您将需要另一种稍微不同的方法:

string[] ReadAllResourceLines(byte[] resourceData)
{
    using (Stream stream = new MemoryStream(resourceData))
    using (StreamReader reader = new StreamReader(stream))
    {
        return EnumerateLines(reader).ToArray();
    }
}

请注意,在所有三个示例中,关键是数据最终包装在一个TextReader实现中,然后用于单独读取每一行以填充数组。这些都使用EnumerateLines()我上面展示的相同的辅助方法。

当然,既然您已经了解了如何检索数据,您可以对其进行调整以以各种其他方式使用数据,例如,如果您真的不想要或不需要将文本表示为string对象数组。

于 2015-04-28T06:50:16.523 回答
0

如果您使用的是资源文件并添加了一个文本文件,您可以使用

string text=Properties.Resources.<ResourceName>

这里 Resources 是您项目的默认资源。如果您添加了自定义资源文件,您可以使用其名称而不是 Properties.Resources

如果您的内容是一个文件,那么它表示为一个字节。在您的简单文本的情况下,如果您包含一个文本文件,它将是一个字符串。

对于任何其他文件,您可以使用将内容转换为文本(如果是文本)的语法

string text=Encoding.ASCII.GetString(Properties.Resources.<ResourceName>);

如果您的文件有任何其他编码(如 UTF Unicode ),您可以在 Encoding 下使用 UTF8 或此类类

于 2015-04-28T06:22:02.517 回答