C#控制台字符串解析文本文件:仅限名称或路径

时间:2017-03-14 14:18:51

标签: c# string parsing

我有一个C#应用程序,它使用以下行读取文本文件:

pip install -U google-api-python-client

我需要的是以这种方式来自每一行的两个值:

从第1行开始:     c:\ecpg\BL_Publish_Staging_CFCS_PSC_Outage_Notification_16\myfile2.cfm c:\ecpg\BL_Publish_Staging_CFCS_PSC_Outage_Notification_16\includes\my file1.blahh4 变量的值为“myfile2.cfm”,filename变量的值为“”[empty]

从第2行开始:     filepath变量的值为'my file1.blahh4',filename的值为'includes'[也是\ includes \子文件夹]

我尝试了filepathindexof之类的代码,但到目前为止还没有成功。我认为一些RegEx应该有所帮助吗?基本上,在文件或文件夹名称开始之前,斜杠将始终为3。

谢谢!

4 个答案:

答案 0 :(得分:1)

您可以使用Path解析路径 有关详细信息,请参阅以下代码:

var path = @"c:\ecpg\BL_Publish_Staging_CFCS_PSC_Outage_Notification_16\myfile2.cfm";
var pathFileName = Path.GetFileName(path); // "myfile2.cfm"

var baseDirectory = @"c:\ecpg\BL_Publish_Staging_CFCS_PSC_Outage_Notification_16";
var pathDirectory = Path.GetDirectoryName(path).Replace(baseDirectory, ""); // ""

编辑请参阅下面的代码,该代码设置了LowerInvariant的路径,以确保替换按预期工作。

var baseDirectory = @"c:\ecpg\BL_Publish_Staging_CFCS_PSC_Outage_Notification_16".ToLowerInvariant();
var paths = new string[] {
    @"c:\ecpg\BL_Publish_Staging_CFCS_PSC_Outage_Notification_16\myfile2.cfm",
    @"c:\ecpg\BL_Publish_Staging_CFCS_PSC_Outage_Notification_16\includes\my file1.blahh4"
};

var sanitizedPaths = new List<Tuple<string,string>>();
foreach(var path in paths.Select(p => (p ?? String.Empty).ToLowerInvariant()))
{
    var fileName = Path.GetFileName(path);
    var directory = Path.GetDirectoryName(path).Replace(baseDirectory, String.Empty);

    sanitizedPaths.Add(new Tuple<string, string>(fileName, directory));
}

// sanitizedPaths[0] -> "myfile2.cfm" | ""
// sanitizedPaths[1] -> "my file1.blahh4" | "\includes"

编辑2 使用Uri并根据您的基本目录始终为3段的事实,以下内容应执行以下操作:

var paths = new string[] {
    @"c:\ecpg\BL_Publish_Staging_CFCS_PSC_Outage_Notification_16\myfile2.cfm",
    @"c:\ecpg\BL_Publish_Staging_CFCS_PSC_Outage_Notification_16\includes\my file1.blahh4",
    @"c:\ecpg\BL_Publish_Staging_CFCS_PSC_Outage_Notification_16\includes\subFolder\other file.extension"
};

var sanitizedPaths = new List<Tuple<string, string>>();
foreach (var path in paths.Select(p => (p ?? String.Empty).ToLowerInvariant()))
{
    var uri = new Uri(path);
    var pathWithoutBaseDirectory = String.Join("/", uri.Segments.Skip(4));

    var fileName = Path.GetFileName(pathWithoutBaseDirectory);
    var directory = Path.GetDirectoryName(pathWithoutBaseDirectory);

    sanitizedPaths.Add(new Tuple<string, string>(fileName, directory));
}

答案 1 :(得分:1)

使用Path类获取文件名和文件目录:

var baseDirectory = @"c:\ecpg\BL_Publish_Staging_CFCS_PSC_Outage_Notification_16\";
var files = new[]
{
    @"c:\ecpg\BL_Publish_Staging_CFCS_PSC_Outage_Notification_16\myfile2.cfm",
    @"c:\ecpg\BL_Publish_Staging_CFCS_PSC_Outage_Notification_16\includes\my file1.blahh4"
};

这里是LINQ查询

var query = from file in files
            let directoryName = Path.GetDirectoryName(file)
            select new
            {
                filename = Path.GetFileName(file),
                filepath = directoryName.StartsWith(baseDirectory)
                        ? directoryName.Substring(baseDirectory.Length) : ""
            };

输出:

[
  {
    filename: "myfile2.cfm",
    filepath: ""
  },
  {
    filename: "my file1.blahh4",
    filepath: "includes"
  }
]

答案 2 :(得分:1)

我要做的是在递归循环中使用FileInfo类来获取所有文件的列表。您可以使用FileInfo分隔路径和文件名。然后使用您正在处理的基本文件夹的字符串长度,并从每个文件的路径中对其进行子串。

这样的东西?

using System;
using System.Collections.Generic;
using System.IO;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            RelativePaths p = new RelativePaths(@"u:\test");
            foreach (var str in p.MyFiles)
            {
                Console.WriteLine(str);
            }
            Console.ReadKey();
        }
    }

    class MyFileInfo
    {
        public MyFileInfo(string path, string filename)
        {
            Path = path;
            Filename = filename;
        }

        public string Path { get; private set; }
        public string Filename { get; private set; }

        public override string ToString() => $"{Path}, {Filename}";
    }

    class RelativePaths
    {
        List<MyFileInfo> myPaths = new List<MyFileInfo>();

        public RelativePaths(string startingPath = @"U:\test")
        {
            DirectoryInfo dir = new DirectoryInfo(startingPath);
            PathSeparator(dir.FullName, dir);
        }

        public MyFileInfo[] MyFiles => myPaths.ToArray();

        public void PathSeparator(string originalPath, DirectoryInfo dir)
        {
            // Files in dir
            foreach (var file in dir.GetFiles())
            {
                myPaths.Add(new MyFileInfo(file.DirectoryName.Substring(originalPath.Length),
                                           file.Name));

            }

            foreach (var folder in dir.GetDirectories())
            {
                PathSeparator(originalPath, folder);
            }
        }
    }
}

原始路径:

U:\测试\子目录

U:\测试\ testfile1.txt

U:\测试\的子文件夹\ fileinsub1.txt

U:\测试\的子文件夹\ subfolder2

u:\ test \ subfolder \ subfolder2 \ two deep.txt

结果是:

,testfile1.txt

\ subfolder,fileinsub1.txt

\ subfolder \ subfolder2,两个deep.txt

请注意,结果位于MyFileInfo类型的列表中,因此您可以使用您认为合适的数据输出。这只是一个例子。您可能希望使用扩展方法创建静态类,但使用递归方法查看每个文件夹是可能有用的概念。请注意,您可以将源代码直接复制到新的控制台项目中,然后在Visual Studio中运行它,只需更改起始路径即可。

答案 3 :(得分:0)

试试这个:

var s1 =@"c:\ecpg\BL_Publish_Staging_CFCS_PSC_Outage_Notification_16\myfile2.cfm";
var s2 =@"c:\ecpg\BL_Publish_Staging_CFCS_PSC_Outage_Notification_16\includes\my file1.blahh4";

var filename = Path.GetFileName(s1);
var p1 = Path.GetDirectoryName(s1);
if (!p1.ToLowerInvariant().Contains(@"\includes"))
    p1 = "";
var p2 = Path.GetDirectoryName(s2);
if (!p2.ToLowerInvariant().Contains(@"\includes"))
    p2 = "";