使用File.ReadAllLines从嵌入的文本文件中读取

3
我一直在应用我在Bob Tabor的入门系列中所学到的知识,为我的女儿写了一个小型控制台文字游戏,需要我生成一个随机的5个字母的单词。
之前我使用File.ReadAllLines(path)从系统上的文本文件(wordlist.txt)生成字符串数组,然后使用Random.next生成索引来提取该数组中的元素。
我从这里的一些帖子中学到如何将文件作为资源嵌入,但现在我找不到指向它的语法(路径)。或者说,它被嵌入后我需要以不同的方式访问它吗?
提前感谢您。

我认为你需要使用StreamReader来实现这个功能:https://dev59.com/MnA75IYBdhLWcg3wZ4Nr - cbr
感谢您的回复。我意识到我的解释不够清晰,而且缺乏代码示例,这并没有帮助到您。在发布之前,我查看了那个示例,但只能看到它会为我检索一个字符串。我有一个文本文件,每行都有一个5个字母的单词(5733行),我需要将这些单词放入一个字符串数组中。然后我生成一个随机整数,并将其用作从数组中提取字符串的索引。一切都进行得很顺利,直到我想知道如何将文本文件包含在最终的.exe文件中 :) - Tater
2个回答

10

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

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

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

如果您正在使用"资源"设计器,则可能有几种不同的方法添加文件。其中一种是使用"新建文本文件..."选项,它允许您将新文本复制/粘贴或键入到资源中。在代码中,这被公开为Properties.Resources对象上的string属性。如果您使用"现有文件..."选项并选择Visual Studio识别为文本文件的文件,则会发生相同的事情。
否则,该文件将作为Properties.Resources类中的属性公开为byte[]对象。
如果您使用"嵌入式资源"构建选项而不是"资源"设计器,则可以通过调用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();
    }
}

称为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 对象的数组。

1
如果您正在使用资源文件并添加了一个文本文件,您可以使用以下代码:
string text=Properties.Resources.<ResourceName>

这里的Resources是您项目的默认资源。如果您已经添加了一个自定义Resource File,那么您可以使用它的名称而不是Properties.Resources。

如果您的内容是一个文件,则它会被表示为一个byte。对于简单文本,它将是一个字符串,如果您包括了一个文本文件。

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

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

如果您的文件有任何其他编码(如UTF Unicode),您可以在Encoding下使用UTF8或类似的类来处理它们。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接