Ich versuche, eine externe Anwendung auszuführen, die große Mengen kommagetrennter Daten auf der Konsole ausgibt. Die Ausgabe ist im Wesentlichen eine große Datentabelle, die von einer .NET-Anwendung stammt. Die "Zeilen" sind durch Komma getrennt und jeder Zeile folgt ein Zeilenumbruchzeichen. Die erste Zeile sind Überschriften und die Datentabelle muss mit diesen aktualisiert werden. Ich habe den Beispielcode befolgt, der die Konsole liest, aber ich stoße auf Probleme, bei denen einige der Zeilen teilweise vollständig sind (nicht am Zeilenumbruch getrennt). Ich versuche dann, die Teilzeile abzustreifen und an den Anfang der nächsten Zeile anzufügen, aber mir fehlen immer noch ein paar Zeilen (~ 35 von 4338). Wenn ich in eine Textvariable schreibe und verarbeite, sobald das Programm fertig ist, funktioniert es, aber es ist viel langsamer (vermutlich, weil die Zeichenfolge sehr lang ist und nicht gleichzeitig mit der externen Anwendung läuft, aber das ist nur meine Vermutung).
Gibt es Möglichkeiten zu steuern, wann die Lesefunktion aufgerufen wird, damit ich ganze Zeilen gleichzeitig erfassen kann? Gibt es eine bekannte Methode, um damit umzugehen (die Daten bestehen aus 4000 Zeilen und ~ 200 Spalten, wobei wahrscheinlich etwa 50% der Zellen gefüllt sind, und die Daten etwa 10-Zeichen-Zeichenfolgen pro gefüllter Zelle, falls dies relevant ist).
Ich habe Zugriff auf den .NET-Quellcode und kann die Ausgabe ändern, um sie JSL-freundlich zu machen, falls dies erforderlich ist.
Ich füge meinen Code ein und ersetze sensible Spaltennamen durch "IDx". Danke im Voraus!
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;
);
versuchen Sie so etwas (geschrieben für Windows .bat-Datei, um Ihre externe Datenquelle zu simulieren):
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
);
)
)
)
);
Die 100.000 Zeilen brauchen einige Zeit mit der Tabellenaktualisierung (vielleicht 15 Sekunden). Es läuft viel schneller (~ 4 Sekunden) auf diese Weise:
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" );
<