如何使用读取功能处理大量运行程序我正在尝试运行一个将大量逗号分隔数据打印到控制台的外部应用程序。 输出本质上是一个大型数据表,来自 .NET 应用程序。 “行”以逗号分隔,每行后跟一个换行符。 第一行是标题,需要用这些更新数据表。 我遵循了读取控制台的示例代码,但我遇到了一些问题,其中一些行部分完成(未在换行符处分隔)。 我试图然后剥离部分行并将其附加到下一行的开头,但我仍然缺少几行(约 35 出 4338)。 如果我写入一个文本变量并在程序完成后进行处理,它可以工作,但速度要慢得多(大概是因为字符串很长并且它与外部应用程序不并发,但这只是我的猜测)。
有什么方法可以控制何时调用读取函数,以便我可以一次捕获整行? 是否有任何已知的方法来处理这个问题(数据是 4000 行 x 约 200 列,可能填充了大约 50% 的单元格,并且每个单元格填充了大约 10 个字符的字符串,以防相关)。
我确实可以访问 .NET 源代码,并且可以修改输出以使其对 JSL 友好,以备不时之需。
我正在粘贴我的代码,用“IDx”替换敏感的列名。 提前致谢!
results = Run Program(
Executable(myExecutable),
Options(options),
Read Function(Function({this},
fullValue = this << Read;
lines = Words( fullValue,"\!n" );
lineIndex = 1;
totalLines = totalLines + N Items(lines);
callCount++;
words = Words(lines[1], ",");
if (N Items(words) > 1,
if (extraContent != "", lines[1] = appendExtraContent(lines[1],extraContent),);
newExtraContent = getExtraContent(fullValue);
if (N Items(lines) == 1,
extraContent = extraContent || newExtraContent,
extraContent = newExtraContent
);
if (extraContent != "",
print(lines[NItems(lines)]);
Remove From(lines, N Items(lines));
extraLines++;,
);
if (N Items(lines) >= 1,
if (first == 1,
headers = Words(lines[1],",");
For (i = 14, i <= N Items(headers), i++,
dt << New Column(headers[i], Character);
);
headerCount++;
first = 0;
lineIndex++;
cols = dt << Get Column Names();,);
For( i = lineIndex, i <= N Items(lines), i++,
//print(lines[i]);
count++;
word = break_string_by_sep(lines[i], ",");
if ( N Items(word) > maxHeaders, maxHeaders = N Items(word),);
if (N Items(word) >= 14,
dt << Add Row({
:ID1 = word[1];
:ID2 = word[2];
:ID3 = Num(word[3]);
:ID4 = Num(word[4]);
:ID5 = word[5];
:ID6 = Num(word[6]);
:ID7 = word[7];
:ID8 = Num(word[8]);
:ID9 = word[9];
:ID10 = word[10];
:ID11 = Num(word[11]);
:ID12 = Num(word[12]);
:ID13 = Num(word[13]);
For (k = 14, k <= N Items(cols) , k++,
if (N Items(word) >= k,
AsColumn(dt,cols[k]) = word[k],
);
);
}),
);
);
,);
,);
);
)
);
While (!(results << Is Read EOF), Wait(1));
dt << ShowWindow(1);
);
appendExtraContent = Function({partialValue, extra}, {default local},
fullLine = extra || partialValue;
fullLine;
);
getExtraContent = Function({allLines}, {default local},
lines = Words(allLines, "\!n");
lastValue = N Items(lines);
startValue = Contains(allLines, lines[lastValue]);
last7 = Substr(allLines, -1);
if (last7 == "\!n",
extra = "",
extra = Substr(allLines, startValue);
);
extra;
);
Re: 如何使用读取功能处理大量运行程序尝试这样的事情(为 windows .bat 文件编写以模拟您的外部数据源):
dt = New Table( "fetched", New Column( "a" ), New Column( "b" ), New Column( "c" ), New Column( "d" ), New Column( "bufsize" ) );
// https://stackoverflow.com/questions/2591758/batch-script-loop
bat = Save Text File( "$temp/data.bat", "@echo off\!nfor /l %%x in (1, 1, 100000) do echo %%x, 444, 555, 666" );
buffer = "";
runprog = RunProgram(
executable( "CMD.EXE" ),
options( {"/C", bat} ),
readfunction(
Function( {this},
{data},
While( this << canread,
buffer = buffer || (this << read);
While( Pat Match( buffer, Pat Break( "\!n" ) >> data + "\!n", "" ),
dt << addrow( 1 );
{dt:a, dt:b, dt:c, dt:d} = Words( data, "," );
dt:bufsize = Length( buffer );
If( Mod( N Rows( dt ), 1000 ) == 0,
Wait( 0 )
); // show the updates
);
)
)
)
);
100,000 行表格更新需要一些时间(可能需要 15 秒)。 它以这种方式运行得更快(约 4 秒):
dt = New Table( "fetched", New Column( "a" ), New Column( "b" ), New Column( "c" ), New Column( "d" ), New Column( "bufsize" ) );
// https://stackoverflow.com/questions/2591758/batch-script-loop
bat = Save Text File( "$temp/data.bat", "@echo off\!nfor /l %%x in (1, 1, 100000) do echo %%x, 444, 555, 666" );
buffer = "";
dt << begin Data Update;
runprog = RunProgram(
executable( "CMD.EXE" ),
options( {"/C", bat} ),
readfunction(
Function( {this},
{data},
While( this << canread,
buffer = buffer || (this << read);
While( Pat Match( buffer, Pat Break( "\!n" ) >> data + "\!n", "" ),
dt << addrow( 1 );
{dt:a, dt:b, dt:c, dt:d} = Words( data, "," );
dt:bufsize = Length( buffer );
);
)
)
)
);
Write( "\!nWaiting\!n" );
While( !(runprog << isreadeof), Wait( .01 ) );
dt << end Data Update;
Write( "\!nDone" );
<<开始数据更新可防止表格格式化大量数字。 最后的 while 等待运行程序对象完成读取,然后再次打开数据更新。 CMD.EXE 窗口需要大约 4 秒来滚动 .bat 文件的输出。