J'essaie d'exécuter une application externe qui imprime de grandes quantités de données séparées par des virgules sur la console. La sortie est essentiellement une grande table de données, provenant d'une application .NET. Les "lignes" sont séparées par des virgules et chaque ligne est suivie d'un caractère de saut de ligne. La première ligne sont des en-têtes et la table de données doit être mise à jour avec ceux-ci. J'ai suivi l'exemple de code qui lit la console, mais je rencontre des problèmes où certaines lignes arrivent partiellement complètes (non séparées à la nouvelle ligne). J'essaie ensuite de supprimer la ligne partielle et de l'ajouter au début de la ligne suivante, mais il me manque encore quelques lignes (~ 35 sur 4338). Si j'écris dans une variable de texte et que je traite une fois le programme terminé, cela fonctionne, mais c'est beaucoup plus lent (probablement parce que la chaîne est très longue et qu'elle n'est pas concurrente avec l'application externe, mais c'est juste ma supposition).
Existe-t-il des moyens de contrôler le moment où la fonction de lecture est invoquée afin que je puisse capturer des lignes complètes à la fois ? Existe-t-il une méthode connue pour gérer cela (les données sont de 4000 lignes par ~ 200 colonnes avec probablement environ 50% des cellules remplies et les données d'environ 10 chaînes de caractères par cellule qui sont remplies, au cas où cela serait pertinent).
J'ai accès au code source .NET et je peux modifier la sortie pour la rendre compatible JSL, au cas où cela serait nécessaire.
Je colle mon code en remplaçant les noms de colonnes sensibles par "IDx". Merci d'avance!
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;
);
essayez quelque chose comme ça (écrit pour le fichier .bat de Windows pour simuler votre source de données externe):
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
);
)
)
)
);
Les 100 000 lignes prennent un certain temps avec la mise à jour de la table (15 secondes, peut-être). Il s'exécute beaucoup plus rapidement (~ 4 secondes) de cette façon :
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" );
<