如何在不定义路径的情况下读取现有文本文件

66

大多数示例演示了如何从确切位置读取文本文件(例如"C:\Users\Owner\Documents\test1.txt")。但是,如何在不编写完整路径的情况下读取文本文件,以便在复制到其他计算机时我的代码可以正常工作。使用Visual Studio我将2个文本文件添加到项目(控制台项目),并不知道最佳方法来读取这些文件。希望我清楚地描述了我的问题。也许我需要以不同方式添加那些txt文件(例如直接添加到与.exe文件相同的文件夹中)?


1
你想要实现什么?类似于 Read("test1.txt"); 这样的操作吗? - Lucas
4
除了其他回答中提到的内容,还想补充一点:请记得将该文件添加为内容(content),以便复制到输出目录。为此,请右键单击解决方案资源管理器(test1.txt)中项目中的文件,选择属性,然后将“生成操作(Build Action)”选择为“内容(content)”,并将“复制到输出目录(Copy to Output Directory)”设置为“始终复制(Copy always)”或“仅在更改时复制(Copy if newer)”。 - saamorim
9个回答

76
你可以使用 Directory.GetCurrentDirectoryPath.Combine
var path = Path.Combine(Directory.GetCurrentDirectory(), "fileName.txt");

它将在应用程序的当前目录中寻找文件fileName.txt


15
Directory.GetCurrentDirectory() 返回一个字符串,其中包含当前工作目录的路径,并且不以反斜杠(\)结尾。使用 Path.Combine() 而不是字符串拼接。 - CodeCaster
4
它适用于当前驱动器的目录,而不是应用程序的目录。 - CME64
4
@DarrenDavies,请不要把这个问题放在心上。以下是对我有用的内容:“System.AppDomain.CurrentDomain.BaseDirectory” ,因为我的应用程序不是控制台应用程序。你可以编辑你的答案,这样我就可以取消给你的反对票。我刚刚注意到原帖中提到的是一个控制台应用程序。 - CME64
4
@RansomAni-Gizzle - 这个解决方案有效且满足了提问者的要求,这就是为什么它被接受作为答案的原因。我建议你学习并尊重其他社区成员,并在再次给我投票之前先阅读实际提出的问题。请注意,不要改变原文的意思。 - Darren
5
在我的情况中,需要去掉文件名部分的前导反斜杠。应该像这样: var path = Path.Combine(Directory.GetCurrentDirectory(), "fileName.txt"); 否则,结果将是 "\fileName.txt",这不是预期的结果。这在VS 2015上进行了测试。 - Shangwu
显示剩余5条评论

42

如果您的应用程序是一项网络服务,则Directory.CurrentDirectory无法正常工作。

请改用System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "yourFileName.txt"))


2
是的。Directory.CurrentDirectory 将会是 C:\Program Files (x86)\IIS Express - andydavies
我无法让它工作,它总是返回path2(仅右侧)。我不知道是否有遗漏。 - Csibi Norbert

16

当你提供一个路径时,它可以是绝对/根路径,也可以是相对路径。如果提供的是相对路径,则会通过获取运行进程的工作目录来解析。

示例:

string text = File.ReadAllText("Some\\Path.txt"); // relative path

以上代码与以下代码具有相同的效果:

string text = File.ReadAllText(
    Path.Combine(Environment.CurrentDirectory, "Some\\Path.txt"));
如果您有文件始终位于相对于应用程序的相同位置,请只需包含相对路径,它们应该可以在不同计算机上正确解析。

3

您需要决定文件相对于哪个目录。一旦确定了,就可以按照以下方式构建完整路径:

string fullPathToFile = Path.Combine(dir, fileName);

如果你不提供基本目录dir,那么你将完全取决于进程的工作目录,这是有可能超出你的控制范围的。例如,应用程序的快捷方式可能会指定它。使用文件对话框也可能会更改它。
对于控制台应用程序来说,直接使用相对文件是合理的,因为控制台应用程序被设计为工作目录是关键输入并且是执行环境的一个明确定义部分。然而,对于非GUI应用程序来说情况并非如此,这就是为什么我建议你使用一些明确定义的基本目录显式地将相对文件名转换为完整绝对路径。
现在,既然你有一个控制台应用程序,只要期望的文件位于工作目录中,使用相对路径是合理的。但是很常见的情况是这不是这样的。通常工作目录用于指定用户的输入和输出文件存储位置。它通常不指向程序文件所在的位置。
最后一个选项是你不尝试将这些程序文件部署为外部文本文件。也许更好的选择是将它们作为资源链接到可执行文件中。这样它们就与可执行文件绑定在一起,你可以完全回避这个问题。

2
你绝对需要知道要读取的文件在哪里。但是,这些信息可能是相对的,因此它可能很适合其他系统。
所以它可能与当前目录有关(从Directory.GetCurrentDirectory()获取),或与应用程序可执行路径有关(例如,如果使用Windows Forms,则会想到Application.ExecutablePath,或通过Assembly.GetEntryAssembly().Location),或与一些特殊的Windows目录相关,如“文档和设置”(您应该使用Environment.GetFolderPath()Environment.SpecialFolder枚举的一个元素)。
请注意,“当前目录”和可执行文件的路径不一定相同。你需要知道去哪里找!
在任何情况下,如果你需要操作路径,请使用Path类来拆分或组合路径的各个部分。

1
作为控制台项目,您可以通过字符串数组args传递要读取的文本文件的路径。
static void Main(string[] args)
{
}

在 Main 中,您可以检查是否传递了参数。
if (args.Length == 0){ System.Console.WriteLine("Please enter a parameter");}

提取一个参数
string fileToRead = args[0];

几乎所有语言都支持参数传递的概念,并遵循类似于C#的模式。
要了解更多关于C#的信息,请参见http://msdn.microsoft.com/en-us/library/vstudio/cb20e19t.aspx

1

这将在工作目录中加载一个文件:

        static void Main(string[] args)
        {
            string fileName = System.IO.Path.GetFullPath(Directory.GetCurrentDirectory() + @"\Yourfile.txt");

            Console.WriteLine("Your file content is:");
            using (StreamReader sr = File.OpenText(fileName))
            {
                string s = "";
                while ((s = sr.ReadLine()) != null)
                {
                    Console.WriteLine(s);
                }
            }

            Console.ReadKey();
        }

如果您正在使用控制台,也可以这样做。它会提示用户编写文件的路径(包括带有扩展名的文件名)。
        static void Main(string[] args)
        {

            Console.WriteLine("****please enter path to your file****");
            Console.Write("Path: ");
            string pth = Console.ReadLine();
            Console.WriteLine();
            Console.WriteLine("Your file content is:");
            using (StreamReader sr = File.OpenText(pth))
            {
                string s = "";
                while ((s = sr.ReadLine()) != null)
                {
                    Console.WriteLine(s);
                }
            }

            Console.ReadKey();
        }

如果您使用winforms,可以尝试这个简单的例子:

        private void button1_Click(object sender, EventArgs e)
        {
            string pth = "";
            OpenFileDialog ofd = new OpenFileDialog();

            if (ofd.ShowDialog() == DialogResult.OK)
            {
                pth = ofd.FileName;
                textBox1.Text = File.ReadAllText(pth);
            }
        }

0

注意前导的\\

string path2 = "\\folderName\\fileName.json";
string text = File.ReadAllText(Path.Combine(Directory.GetCurrentDirectory(), path2));

如果 path2 不包含根目录(例如,如果 path2 不以分隔符字符 \\ 或驱动器规范开头),则结果是两个路径的连接,中间有一个分隔符字符。如果 path2 包含根目录,则返回 path2。

Path.Combine 方法 (System.IO) | Microsoft Learn


0

获取路径有很多种方法。可以参考CurrentDirectory。此外,您可以通过使用Assembly.GetExecutingAssembly().Location获取应用程序的完整文件名,然后使用Path类获取目录名称。


如果程序集位于全局程序集缓存中,会发生什么? - Dan
一个pb。不适合所有情况,但可以从exe中调用。 - ElDog

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