我正在读一个.txt文件,它本质上是一个包含行和列的csv类型文件,只有列由文字[空格]字符分隔。每列都有这些字符的预定义长度,如数据定义文件中所示。
以下是我尝试过的内容,但它忽略了空格。这些数字是我给你区分列的原因。
function formatTextFile(input){
var readFile = fileOpen(input,"read");
var line1 = FileReadLine(readFile);
var line2 = FileReadLine(readFile);
line2 = REReplace(line2,"[^(.{7}.{10}.{47}.{34}.{14}.{13}.{15}.{22}.{28}.{18}.{2})]+[ ]", "|", "all");
return line2;
}
这是:
的输出|1. 16-1268|5/2/201|31530|$0.00|404|AP
我考虑过尝试使用java来进行字符串格式化。我还没想出来。
答案 0 :(得分:2)
感谢@Alex提供了一个出色的解决方案。 Java是可行的方法,他的方法非常实用。我只是想表明我是如何实现它来构建查询的。
左侧有一个列和行数组,您可以将它们放入QueryAddColumn
的查询对象中。我不得不搞乱列长,但java方法是要走的路。再次感谢@Alex。
function formatTextFile(input){
var fileReader = createObject("java","java.io.FileReader").init(input);
var bufferedReader = createObject("java","java.io.BufferedReader").init(fileReader);
var lineReader = createObject("java","java.io.LineNumberReader").init(bufferedReader);
var columnLengths = [7,10,47,34,14,13,16,22,75,18,2];
var rows = ArrayNew(2);
var line = lineReader.readLine();
//skip empty lines
while(!structKeyExists(Local,"line")&&!len(trim(Local.line))){
line = lineReader.readLine();
}
while(isDefined("line")){
var cells = ArrayNew(1);
var offset = 1;
for(var i = 1; i<=ArrayLen(columnLengths); i++){
cells.add(mid(line,offset,columnLengths[i]));
offset+=columnLengths[i];
ArrayAppend(rows[i],cells[i]);
}
line = lineReader.readLine();
}
return rows;
}
答案 1 :(得分:1)
如果你有固定的列宽,为什么还要打扰正则表达式呢?请考虑以下事项:
private static Func<DatabaseDataContext, DateTime, Staff_Time_TBL>
queryFor =
CompiledQuery.Compile((DatabaseDataContext db, DateTime dDate) =>
db.Staff_Time_TBLs.Where(a => a.Date_Data == dDate &&
a.Time_Data_1 == null && a.Time_Data_2 == null).FirstOrDefault());
<cfscript>
line = "ab 12 xy 654 +1234 ";
columnLengths = [4, 4, 3, 6, 1, 8];
o = readFixedLine(line, columnLengths);
function readFixedLine(line, columnLengths) {
var cells = [];
var offset = 1;
for (length in columnLengths) {
cells.add( mid(line, offset, length) );
offset += length;
}
return cells;
}
// cells read (the dump doesn't display whitespaces)
writeDump(o);
/*
whitespaces represented as asterisks
[1] ab**
[2] 12**
[3] xy*
[4] 654***
[5] +
[6] 1234****
*/
// proving that whitespaces are kept
for (entry in o) {
writeOutput( len(entry) & "<br>" );
}
/*
4
4
3
6
1
8
*/
</cfscript>
函数是故障安全的(在这方面),因此您甚至不必担心空行或缺少列。但是,mid
修剪尾随空格,所以你在这里运气不好。此时只有Java可以提供帮助(使用fileReadLine
或Stream
读取您的文件。)
答案 2 :(得分:1)
(评论太长)
关于原始问题的旁注,正空表格正在删除空格,而不是FileReadLine。虽然我个人认为other approaches更具可读性 - 但从技术上来说,可以使用正则表达式完成。
例如,您可以创建一个与整行匹配的表达式,并使用多个子表达式来匹配每个字段中所需的字符数。然后使用生成的反向引用来创建管道分隔的字符串,即\1|\2|\3 ....
代码: 使用CF11进行测试
// ^ - starting with
// $ - ending with
// ( ) - subexpression or capturing group
// \1 - backreference, 1 corresponds to first subexpression
result = REReplace(line1
,"^(.{7})(.{10})(.{47})(.{34})(.{14})(.{13})(.{15})(.{22})(.{28})(.{18})(.{2})\s+$"
, "\1|\2|\3|\4|\5|\6|\7|\8|\9|\10|\11"
);
示例数据:
A1 B C D E F G H I J K
A2 B C D E F G H I J K
A3 B C D E F G H I J K
如果转储结果并检查每个字段的len()
,您将看到 的空格被保留。所以问题是原始表达。
for (currValue in listToArray(line1, "|")) {
writeOutput("<br>["& len(currValue) &"] "& currValue );
}
<强>结果:强>
[7 ] A1 |
[10] B |
[47] C |
[34] D |
[14] E |
[13] F |
[15] G |
[22] H |
[28] I |
[18] J |
[2 ] K |