组合多个固定宽度的文本文件并将数据分隔为管道分隔的列

时间:2016-12-15 16:50:42

标签: java c# sql sas ssms

我需要帮助创建一些东西来处理数百个分割文本文件(001,002,003),它们都是相同的固定宽度格式,并指定由管道分隔的特定列中的每个字段。例如,原始数据可能如下所示:

123456789HA02HANKS       PAUL       123 3rd Ave #2     NEW YORK      NY10023198601042012235245

并在数据字典中定义为:

Field 1: SSN, start 1, end 9, length 9
Field 2: Name ID, start 10, end 11, length 2 
Field 3: Transaction Number, start 12, end 13, length 2
Field 4: Last Name, start 14, end 29, length 16
Field 5: First Name, start 30, end 41, length 12
Field 6: Mailing Address, start 42, end 76, length 35
Field 7: City, start 77, end 92, length 16
Field 8: State, start 93, end 94, length 2 
Field 9: Zip, start 95, end 99, length 5
Field 10: DOB, start 100, end 107, length 8
Field 11: Phone Number, start 108, end 117, length 10

我需要它看起来像:

123456789|HA|02|HANKS|PAUL|123 3rd Ave #2|NEW YORK|NY|10023|19860104|2012235245

我有一个C#控制台文件阅读器,它结合了多个文件,但我不知道如何将它们分成列。这是我的代码:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace EmilysFileReader
{
    public class Program
    {
        static void Main(string[] args)
        {
            Program prog = new Program();
            Console.WriteLine("This program will attempt to combine all the     files of a given directory.");
        Console.WriteLine("Enter path to the directory:");
        var path = Console.ReadLine();
        string[] files = prog.CollectFiles(path);
        Console.WriteLine("Name for the new file?");
        string filename = Console.ReadLine();
        prog.DoWork(Path.Combine(path, filename), files);
        Console.WriteLine("Finished new file is " + Path.Combine(path, filename));
        Console.WriteLine("Press enter to close.");
        Console.ReadLine();
    }

    private void DoWork(string path, string[] files)
    {
        string filename = path + ".txt";
        foreach (string file in files)
        {
            File.AppendAllText(filename, GetFileContent(file));
        }
    }

    public string[] CollectFiles(string path)
    {
        string[] files = Directory.GetFiles(path);
        Console.WriteLine("Found Files:");
        foreach (string file in files)
        {
            Console.WriteLine(file);
        }
        return files;
    }

    public string GetFileContent(string file)
    {
        return File.ReadAllText(file);
    }


}
}

我需要一种方法在C#,Java,SAS或SSMS中执行此操作。谁能指出我正确的方向?

2 个答案:

答案 0 :(得分:0)

如果您说每行的格式都相同,那么您可以在Java中使用以下内容:

char delimiter = '|';

String text = "123456789HA02HANKS       PAUL       123 3rd Ave #2     NEW YORK      NY10023198601042012235245";

StringBuilder sb = new StringBuilder();

sb.append(text.substring(0, 9)).append(delimiter);
sb.append(text.substring(9, 11)).append(delimiter);
sb.append(text.substring(11, 13)).append(delimiter);
sb.append(text.substring(13, 25).trim()).append(delimiter);
sb.append(text.substring(25, 36).trim()).append(delimiter);
sb.append(text.substring(36, 55).trim()).append(delimiter);
sb.append(text.substring(55, 69).trim()).append(delimiter);
sb.append(text.substring(69, 71)).append(delimiter);
sb.append(text.substring(71, 76)).append(delimiter);
sb.append(text.substring(76, 84)).append(delimiter);
sb.append(text.substring(84));

System.out.println(sb);

当然,这并不是一种有效的方法,因为有些单词是用空格分隔的,有些是不是,有些可以有多个元素。希望你只需要运行一次。

编辑:更好的方法是在您知道元素结尾的索引处插入分隔符|,并修剪每个元素。

答案 1 :(得分:0)

这是SAS中的一个简单问题。要从源文件中读取修复长度值,您只需要一个简单的格式化输入语句。只需将所有内容都读为字符串。

while IFS=' ' read -r line; do
  #echo ${line%*}
  sed -e 's/\t.*$//' | xargs rm
done < $1

您可以使用PROC SQL into子句将名称/信息对列表构建到元数据文件中的宏变量中。

input field1 $10. field2 $2. .... ;

现在很容易构建一个简单的数据步骤,它将读取所有输入文件并写入新的分隔文件。您可以在输入文件名中使用单个通配符让SAS一次读取所有文件。

proc sql noprint ;
  select catx(' ',field,cats('$',length,'.'))
    into :varlist separated by ' '
    from metadata
  ;
quit;

文件名中带有通配符的简单输入无法将文件名列表构建到数据集中,并使用该数据集来驱动数据步骤。

data _null_;
   infile '/mypath/*.dat' truncover ;
   input &varlist ;
   file '/myoutpath/newfile.txt' dsd dlm='|' ;
   put (_all_) (:);
run;