组合多个固定宽度的文本文件并将数据分隔到管道分隔的列中
问题描述:
我需要帮助创建一些内容以处理数百个分隔文本文件(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中执行此操作的方法。任何人都可以将我指向正确的方向吗?
答
如果说每一行的格式一样,那么你可以使用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);
当然,有没有真正这样做,因为有些字用空格分开的有效方式,有些不是,有些可以有多个要素。希望你只需要运行一次。
编辑:这样做的一个更好的方法可能是在您知道元素末尾的索引处插入您的分隔符|,并修剪每个元素。
答
这是SAS中的一个简单问题。要从源文件中读取固定长度值,您只需要一个简单的格式化输入语句。只是将所有内容都看作字符串。
input field1 $10. field2 $2. .... ;
您可以使用PROC SQL into子句从元数据文件中将名称/信息对列表构建到宏变量中。
proc sql noprint ;
select catx(' ',field,cats('$',length,'.'))
into :varlist separated by ' '
from metadata
;
quit;
现在很容易构建一个简单的数据步骤,读取所有输入文件并写入新的分隔文件。您可以在输入文件名中使用单个通配符,让SAS一次读取所有文件。
data _null_;
infile '/mypath/*.dat' truncover ;
input &varlist ;
file '/myoutpath/newfile.txt' dsd dlm='|' ;
put (_all_) (:);
run;
它与文件名通配符简单的输入不工作,你可以建立文件名列表变成数据集,并使用该数据集驱动数据的一步。
data _null_;
set filelist;
infile fixed filevar=filename end=eof truncover ;
do while (not eof);
input &varlist ;
file '/myoutpath/newfile.txt' dsd dlm='|' ;
put (_all_) (:);
end;
run;