读取定长文本文件时如何保留白色space
How to preserve white space when reading fixed length text file
我正在阅读一个 .txt 文件,本质上,它是一个包含行和列的 csv 类型文件,只有列由文字 [space] 字符分隔。每列都有这些字符的预定义长度,如数据定义文件中所给。
下面是我试过的,但是它忽略了白色space。这些数字是我用来区分列的。
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|[=12=].00|404|AP
我想尝试使用 java 来进行字符串格式化。这个我还没想好。
如果列宽固定,为什么还要费心使用正则表达式?考虑以下因素:
<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
函数是故障安全的(在这方面),因此您甚至不必担心空行或缺少列。然而,fileReadLine
修剪尾随空格,所以你在这里运气不好。此时只有 Java 可以提供帮助(使用 Stream
或 BufferedReader
阅读您的文件)。
感谢@Alex 提供了一个很好的解决方案。 Java 是要走的路,他的方法非常实用。我只是想展示我是如何将它实现到构建查询中的。
留下一个列和行的数组,您可以使用 QueryAddColumn
将其放入查询对象中。我不得不弄乱列的长度,但是 java 方法是再次 go.Thanks @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;
}
(评论太长)
关于原始问题的旁注,白色 space 正被正则表达式删除,而不是 FileReadLine. Though personally I find the 更具可读性 - 技术上它 可以 用正则表达式来完成。
例如,您可以创建一个匹配整行的表达式,并使用多个子表达式来匹配每个字段中所需的字符数。然后使用生成的反向引用创建管道分隔字符串,即 || ....
代码: 使用 CF11 测试
// ^ - starting with
// $ - ending with
// ( ) - subexpression or capturing group
// - backreference, 1 corresponds to first subexpression
result = REReplace(line1
,"^(.{7})(.{10})(.{47})(.{34})(.{14})(.{13})(.{15})(.{22})(.{28})(.{18})(.{2})\s+$"
, "||||||||||"
);
示例数据:
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()
,您将看到 spaces 被 保留。所以问题是原始表达式。
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 |
我正在阅读一个 .txt 文件,本质上,它是一个包含行和列的 csv 类型文件,只有列由文字 [space] 字符分隔。每列都有这些字符的预定义长度,如数据定义文件中所给。
下面是我试过的,但是它忽略了白色space。这些数字是我用来区分列的。
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|[=12=].00|404|AP
我想尝试使用 java 来进行字符串格式化。这个我还没想好。
如果列宽固定,为什么还要费心使用正则表达式?考虑以下因素:
<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
函数是故障安全的(在这方面),因此您甚至不必担心空行或缺少列。然而,fileReadLine
修剪尾随空格,所以你在这里运气不好。此时只有 Java 可以提供帮助(使用 Stream
或 BufferedReader
阅读您的文件)。
感谢@Alex 提供了一个很好的解决方案。 Java 是要走的路,他的方法非常实用。我只是想展示我是如何将它实现到构建查询中的。
留下一个列和行的数组,您可以使用 QueryAddColumn
将其放入查询对象中。我不得不弄乱列的长度,但是 java 方法是再次 go.Thanks @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;
}
(评论太长)
关于原始问题的旁注,白色 space 正被正则表达式删除,而不是 FileReadLine. Though personally I find the
例如,您可以创建一个匹配整行的表达式,并使用多个子表达式来匹配每个字段中所需的字符数。然后使用生成的反向引用创建管道分隔字符串,即 || ....
代码: 使用 CF11 测试
// ^ - starting with
// $ - ending with
// ( ) - subexpression or capturing group
// - backreference, 1 corresponds to first subexpression
result = REReplace(line1
,"^(.{7})(.{10})(.{47})(.{34})(.{14})(.{13})(.{15})(.{22})(.{28})(.{18})(.{2})\s+$"
, "||||||||||"
);
示例数据:
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()
,您将看到 spaces 被 保留。所以问题是原始表达式。
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 |