C# 不使用分隔符转换平面文件

C# 不使用分隔符转换平面文件,c#,regex,text,ssis,C#,Regex,Text,Ssis,我想将平面文件test.txt转换为平面文件test-output.txt 以下是该计划: 示例输入:test.txt COD/ID:37 PRJ/NAME: Josephy Murphy PRJ/EMAIL: jmurphy@email.com PRJ/DESCRIPTION: test37, test37, test37 ... COD/ID:38 PRJ/NAME: Paul Newman PRJ/EMAIL: pnewman@email.com PRJ/DESCRIPTION: te

我想将平面文件test.txt转换为平面文件test-output.txt

以下是该计划:
示例输入:test.txt

COD/ID:37
PRJ/NAME: Josephy Murphy
PRJ/EMAIL: jmurphy@email.com
PRJ/DESCRIPTION: test37, test37, test37 ...

COD/ID:38
PRJ/NAME: Paul Newman
PRJ/EMAIL: pnewman@email.com
PRJ/DESCRIPTION: test38, test38, test38 ...

.
.
class Program
{
    private static Regex reg = new Regex(@"COD/ID:\s(?<id>\d+)\r\nPRJ/NAME:\s(?<name>.+?)\r\nPRJ/EMAIL:\s(?<email>\S+?@\S+?\.\S+?)\r\nPRJ/DESCRIPTION:\s(?<description>.*?)\r\n");

    static void Main(string[] args)
    {
        StringBuilder intermediateStringBuilder = new StringBuilder();

        using (StreamReader reader = new StreamReader(@"YourInputPath.txt",true))
        {               
            using (StreamWriter writer = new StreamWriter("YourOutputPath.txt"))
            {
                while (reader.Peek() > 0)
                {
                    string line = reader.ReadLine();
                    if (!string.IsNullOrWhiteSpace(line))
                    {
                        intermediateStringBuilder.AppendLine(line);
                    }
                    else
                    {
                        WriteToFile(intermediateStringBuilder, writer);
                    }
                } 
                WriteToFile(intermediateStringBuilder,writer);
            }
        }
    }

    private static void WriteToFile(StringBuilder intermediateStringBuilder, StreamWriter writer)
    {
        Match m = reg.Match(intermediateStringBuilder.ToString());
        writer.WriteLine("{0}|{1}|{2}|{3}", m.Groups["id"].Value, m.Groups["name"].Value, m.Groups["email"].Value, m.Groups["description"].Value);
        intermediateStringBuilder.Clear();
    }
}

输出示例:test-OUTPUT.txt(不带标签的管道分隔)



屏幕截图链接:


我想将此文件导入SQL Server。但是文件test.txt(15000000行)不是默认的带分隔符的导入文件。

我将使用SSI导入数据,但必须是CSV格式或其他带分隔符的格式。


我考虑过使用REGEX或SSIS脚本组件。我知道SSIS文件的导入过程,但该文件没有格式化。

例如,使用正则表达式:

    class Program
    {
        private static Regex reg = new Regex(@"COD/ID:\s(?<id>\d+)\r\nPRJ/NAME:\s(?<name>.+?)\r\nPRJ/EMAIL:\s(?<email>\S+?@\S+?\.\S+?)\r\nPRJ/DESCRIPTION:\s(?<description>.*?)(?:\n|$)");

        static void Main(string[] args)
        {
            string original = @"
COD/ID: 37
PRJ/NAME: Josephy Murphy
PRJ/EMAIL: jmurphy@email.com
PRJ/DESCRIPTION: test37, test37, test37 ...

COD/ID: 38
PRJ/NAME: Paul Newman
PRJ/EMAIL: pnewman@email.com
PRJ/DESCRIPTION: test38, test38, test38 ...";


            string result = string.Join(
                "\n",
                reg.Matches(original)
                .Cast<Match>()
                .Select(m => string.Format("{0}|{1}|{2}|{3}",m.Groups["id"].Value,m.Groups["name"].Value,m.Groups["email"].Value,m.Groups["description"].Value)));
            Console.WriteLine(result);
        }
    }
类程序
{
private static Regex reg=new Regex(@“COD/ID:\s(?\d+)\r\nPRJ/NAME:\s(?++)\r\nPRJ/EMAIL:\s(?\s+?@\s+?\。\r\nPRJ/DESCRIPTION:\s(?.*?(:\n |$);
静态void Main(字符串[]参数)
{
字符串原始=@“
化学需氧量/识别号:37
PRJ/姓名:Josephy Murphy
PRJ/电邮:jmurphy@email.com
PRJ/描述:test37,test37,test37。。。
化学需氧量/识别号:38
PRJ/姓名:保罗·纽曼
PRJ/电邮:pnewman@email.com
PRJ/描述:test38,test38,test38…”;
string result=string.Join(
“\n”,
注册匹配项(原件)
.Cast()
.Select(m=>string.Format(“{0}{1}{2}{3}”、m.Groups[“id”].Value、m.Groups[“name”].Value、m.Groups[“email”].Value、m.Groups[“description”].Value));
控制台写入线(结果);
}
}
编辑

COD/ID:37
PRJ/NAME: Josephy Murphy
PRJ/EMAIL: jmurphy@email.com
PRJ/DESCRIPTION: test37, test37, test37 ...

COD/ID:38
PRJ/NAME: Paul Newman
PRJ/EMAIL: pnewman@email.com
PRJ/DESCRIPTION: test38, test38, test38 ...

.
.
class Program
{
    private static Regex reg = new Regex(@"COD/ID:\s(?<id>\d+)\r\nPRJ/NAME:\s(?<name>.+?)\r\nPRJ/EMAIL:\s(?<email>\S+?@\S+?\.\S+?)\r\nPRJ/DESCRIPTION:\s(?<description>.*?)\r\n");

    static void Main(string[] args)
    {
        StringBuilder intermediateStringBuilder = new StringBuilder();

        using (StreamReader reader = new StreamReader(@"YourInputPath.txt",true))
        {               
            using (StreamWriter writer = new StreamWriter("YourOutputPath.txt"))
            {
                while (reader.Peek() > 0)
                {
                    string line = reader.ReadLine();
                    if (!string.IsNullOrWhiteSpace(line))
                    {
                        intermediateStringBuilder.AppendLine(line);
                    }
                    else
                    {
                        WriteToFile(intermediateStringBuilder, writer);
                    }
                } 
                WriteToFile(intermediateStringBuilder,writer);
            }
        }
    }

    private static void WriteToFile(StringBuilder intermediateStringBuilder, StreamWriter writer)
    {
        Match m = reg.Match(intermediateStringBuilder.ToString());
        writer.WriteLine("{0}|{1}|{2}|{3}", m.Groups["id"].Value, m.Groups["name"].Value, m.Groups["email"].Value, m.Groups["description"].Value);
        intermediateStringBuilder.Clear();
    }
}
类程序
{
private static Regex reg=new Regex(@“COD/ID:\s(?\d+)\r\nPRJ/NAME:\s(?++)\r\nPRJ/EMAIL:\s(?\s+?@\s+?\。\r\nPRJ/DESCRIPTION:\s(?.*?)\r\n);
静态void Main(字符串[]参数)
{
StringBuilder intermediateStringBuilder=新建StringBuilder();
使用(StreamReader=newstreamreader(@“YourInputPath.txt”,true))
{               
使用(StreamWriter=newstreamwriter(“YourOutputPath.txt”))
{
while(reader.Peek()>0)
{
字符串行=reader.ReadLine();
如果(!string.IsNullOrWhiteSpace(行))
{
intermediateStringBuilder.AppendLine(行);
}
其他的
{
WriteToFile(intermediateStringBuilder、writer);
}
} 
WriteToFile(intermediateStringBuilder、writer);
}
}
}
私有静态void WriteToFile(StringBuilder、intermediateStringBuilder、StreamWriter-writer)
{
Match m=reg.Match(intermediateStringBuilder.ToString());
writer.WriteLine(“{0}{1}{1}{2}{3}”、m.Groups[“id”].Value、m.Groups[“name”].Value、m.Groups[“email”].Value、m.Groups[“description”].Value);
intermediateStringBuilder.Clear();
}
}

在这种情况下,您可以不使用正则表达式,因为上下文是已知的

使用以下命令:

public class EntryN
{
   public string id { get; set; }
   public string name { get; set; }
   public string email { get; set; }
   public string description { get; set; }

   public EntryN()
   {
      this.id = this.name = this.email = this.description = string.Empty;
   }
   public string ToLine()
   { 
       return this.id + "|" + this.name + "|" + this.email + "|" + this.description; 
   }
}

var entries = new List<EntryN>();
using (var sl = new StreamReader(@"c:\YOURPATH.txt", true))
{
    var entry = new EntryN();
    var line = string.Empty;
    while ((line = sl.ReadLine()) != null)
    {
       if (line.StartsWith("COD/ID:"))
          entry.id = line.Substring(8).Trim();
       else if (line.StartsWith("PRJ/NAME:"))
          entry.name = line.Substring(10).Trim();
       else if (line.StartsWith("PRJ/EMAIL"))
          entry.email = line.Substring(11).Trim();
       else if (line.StartsWith("PRJ/DESCRIPTION"))
          entry.description = line.Substring(17).Trim();
      else if (line.Trim() == string.Empty)
      {
          entries.Add(entry);
          entry = new EntryN();
      }
    }
    if (!entry.Equals(new EntryN()))
       entries.Add(entry);
    sl.Close();
}

var resulted = entries.Select(p => p.ToLine()).ToList();

请把这些文本(或至少是综合样本)放在问题中。请分享你的尝试。这是必须的。有什么困难吗?您卡在哪里了?我想将此文件导入SQL Server。但是文件test.txt(15000000行)不是默认的带分隔符的导入文件。我将使用SSI导入数据,但必须是CSV格式或其他带分隔符的格式。我考虑过使用正则表达式或脚本组件SSI。您的建议是什么?最好的选择是创建一个源SSIS脚本组件,该组件使用Florian Schmidinger的正则表达式分割行,并为每个客户返回一行,然后使用其他SSIS步骤处理行并将其写入文件。不要使用字符串操作函数,生成的临时字符串会对内存和垃圾收集造成巨大压力恭喜!使用正则表达式(regex)的完美解决方案。@J.LopesSilvestre是的,但是有数百万行,你可能会在内存方面遇到麻烦(我刚刚读了你的评论)。。。因此,这应该是如何使用较小的文件执行此操作的示例—实际上,性能会受到影响!然后,解决方案将逐行读取并写入文本文件?使用System.IO的方法;要读取和写入文本文件。@J.LopesSilvestre,此方法将解析整个内容。。。有15万条线路你会遇到麻烦。。。我将尝试实施一个解决方案,可以处理这个问题。。。给我几句赞美的话!它工作得很好!非常感谢。只是更正一下。对于那些使用旧版本.Net 3.5版的用户,需要调整代码以使其正常工作。Include方法:private static bool IsNullOrWhiteSpace(此字符串值){if(value==null)返回true;返回string.IsNullOrEmpty(value.Trim();}并更改intermediateStringBuilder.Clear();由intermediateStringBuilder创建。长度=0;很乐意帮忙。顺便说一句,请将您以前的尝试添加到问题中,即使没有成功。在提问之前,一定要试着至少张贴一些东西来证明你的努力。否则,您的问题将被关闭,并最终被删除。确定。谢谢你的提示。什么是首字母缩略词BTW?由于生成了大量临时字符串,这段代码对于大型文件有严重的性能问题。每个
子字符串
StartsWith
Trim
调用都会创建一个新的临时字符串,必须对其进行垃圾收集,从而使CPU和内存都处于紧张状态。这里应该使用正则表达式,因为它不会生成任何临时字符串,从而更好地处理大型文件。即使是通过
进行拆分也将是一个显著的改进。此外,由于生成临时字符串,最终的字符串连接也会影响性能。这可以通过使用来避免,例如:
String.Join(“|”,entries)