How to learn nsIZipWriter and nsIZipReader? [closed] - asynchronous

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I was wondering how to use JavaScript to do async zip writing and reading.

Here is an example for zip reading using nsIZipReader, zip writing goes in a similar way. The example reads a zip file from /tmp/example.zip and prints the content of the first file to the console.
Remarks:
I'm using nsIInputStreamPump for async I/O I found a reference to this API at the Streams guide on MDN. This interface offers a .asyncRead method which takes an object that implements nsIStreamListener (and nsIRequestObserver).
I have compared the running time of this example with the synchronous zip reading example at MDN and found that reading the time used by the blocking read is significantly smaller (reading a zip file from RAM disk: from 1-2ms to 0.1-0.3ms) (measured using console.time('foo'); before the reusableStreamInstance.init invocation and console.timeEnd('foo'); after reusableStreamInstance.readBytes).
I am using .readBytes instead of .read to avoid truncation of data if the file contains a null byte.
I haven't implemented any error handling (zip not existent, zip doesn't contain a file, zip/file cannot be opened), but I do close the zipreader regardless of whether an error occurs.
let { Cc: classes, Cu: utils, Ci: interfaces } = Components;
Cu.import('resource://gre/modules/FileUtils.jsm');
let pathToZip = '/tmp/example.zip';
let nsiFileZip = new FileUtils.File(pathToZip);
let streamListener = {
buffer: null,
// nsIRequestObserver
onStartRequest: function(aRequest, aContext) {
this.buffer = [];
},
// nsIStreamListener
onDataAvailable:
function(aRequest, aContext, aInputStream, aOffset, aCount) {
let reusableStreamInstance = Cc['#mozilla.org/scriptableinputstream;1']
.createInstance(Ci.nsIScriptableInputStream);
reusableStreamInstance.init(aInputStream);
let chunk = reusableStreamInstance.readBytes(aCount);
this.buffer.push(chunk);
},
// nsIRequestObserver
onStopRequest: function(aRequest, aContext, aStatusCode) {
console.log('end', aStatusCode);
var data = this.buffer.join('');
console.log(data);
}
};
let pump = Cc['#mozilla.org/network/input-stream-pump;1']
.createInstance(Ci.nsIInputStreamPump);
let zr = Cc['#mozilla.org/libjar/zip-reader;1']
.createInstance(Ci.nsIZipReader);
try {
zr.open(nsiFileZip);
// null = no entry name filter.
var entries = zr.findEntries(null);
while (entries.hasMore()) {
var entryPointer = entries.getNext();
var entry = zr.getEntry(entryPointer);
if (!entry.isDirectory) {
var stream = zr.getInputStream(entryPointer);
pump.init(stream, 0, -1, 0, 0, true);
pump.asyncRead(streamListener, null);
// For the demo, we only take one file, so break now.
break;
}
}
} finally {
zr.close();
}

Related

IMPORTDATA not grabbing live data from XML

I'm using Google Sheet's IMPORTDATA function to grab information from an XML file that is pulling from an API but the information I pull into the sheet isn't up to date.
How can I modify my sheet to pull in up-to-date data?
Compare the sheet: https://docs.google.com/spreadsheets/d/1W0Bt5z-Tky-tNhG_JtfE4FfjTRgQNRu_eQu2qVhQ-_E/edit?usp=sharing (LiveScores sheet)
To the XML: https://www67.myfantasyleague.com/2019/export?TYPE=liveScoring&L=64741&APIKEY=&W=14&DETAILS=1&JSON=0
Observe franchise id="0015" in both sets of data.
The sheet states <franchise id="0005" score="0.00" gameSecondsRemaining="21600" playersYetToPlay="6" playersCurrentlyPlaying="0" isHome="0">
The XML states <franchise id="0015" score="11.14" gameSecondsRemaining="20004" playersYetToPlay="4" playersCurrentlyPlaying="2"> (This data is for a football game that is currently being played as I'm writing this so the above example may not be exact, but it WON'T be score of 0.00, for example.
Any help would be amazing, thanks!
Have you tried using IMPORTXML? Google Sheets IMPORTXML Page
In IMPORTXML, you can just use the Inspect Element feature to pull the xpath.
Hope this helps. Let me know if I can help further.
Edit: Instructions To Change When Data Is Imported
In the toolbar go to the script editor
Now in the scripts, paste the code listed bellow
/**
* Go through all sheets in a spreadsheet, identify and remove all spreadsheet
* import functions, then replace them a while later. This causes a "refresh"
* of the "import" functions. For periodic refresh of these formulas, set this
* function up as a time-based trigger.
*
* Caution: Formula changes made to the spreadsheet by other scripts or users
* during the refresh period COULD BE OVERWRITTEN.
*
* From: https://stackoverflow.com/a/33875957/1677912
*/
function RefreshImports() {
var lock = LockService.getScriptLock();
if (!lock.tryLock(5000)) return; // Wait up to 5s for previous refresh to end.
// At this point, we are holding the lock.
var id = "YOUR-SHEET-ID";
var ss = SpreadsheetApp.openById(id);
var sheets = ss.getSheets();
for (var sheetNum=0; sheetNum<sheets.length; sheetNum++) {
var sheet = sheets[sheetNum];
var dataRange = sheet.getDataRange();
var formulas = dataRange.getFormulas();
var tempFormulas = [];
for (var row=0; row<formulas.length; row++) {
for (col=0; col<formulas[0].length; col++) {
// Blank all formulas containing any "import" function
// See https://regex101.com/r/bE7fJ6/2
var re = /.*[^a-z0-9]import(?:xml|data|feed|html|range)\(.*/gi;
if (formulas[row][col].search(re) !== -1 ) {
tempFormulas.push({row:row+1,
col:col+1,
formula:formulas[row][col]});
sheet.getRange(row+1, col+1).setFormula("");
}
}
}
// After a pause, replace the import functions
Utilities.sleep(5000);
for (var i=0; i<tempFormulas.length; i++) {
var cell = tempFormulas[i];
sheet.getRange( cell.row, cell.col ).setFormula(cell.formula)
}
// Done refresh; release the lock.
lock.releaseLock();
}
}
This snippet of code came from Periodically refresh IMPORTXML() spreadsheet function
Last and definitely the least, replace the "YOUR-SHEET-ID"
NOTE: I have not personally tested this code and I cannot vouch for it. I recommend making a copy and testing it there first.
Hopefully, this solves the issue of your data not being imported as often as you want. If you want to manually get "fresh" data, you can just delete/cut the import function and paste it back in.
try in A2:
=ARRAYFORMULA(IFNA(VLOOKUP(C2:C, PlayerList!A:F, {2, 6}, 0)))
and in C2:
=ARRAYFORMULA(QUERY(REGEXEXTRACT(QUERY(IMPORTDATA(
"https://www67.myfantasyleague.com/2019/export?TYPE=liveScoring&L=64741&APIKEY=&W=14&DETAILS=1&JSON=0?273"),
"where Col1 contains 'player id'", 0),
"(player id=""(\d+)).+?(score=""(\d+.\d+))"),
"select Col2,Col4"))
spreadsheet demo

Cannot identify language in SALT

I just started using SALT for a project i am working on. It is said to work with Python but I find quite a bit of difference in thier syntax and overall format. I have pasted a code for a simple task which just opens and imports and loads some libraries onto the SALT console. I hope someone can check abnd see if he/she can instantly identify the language being used and what the code does. This is because i have a suspicion that the code is a mixture between C, Python as well as Java... if that is so doen't that mean it should be a totally different language on its own?
code:
var rtwxlib = import'rtwxlib';
var string = import'string';
var monitor = rtwxlib.Monitor
{
EvActivate = func() { print "Activate\n"; };
EvShutdown = func() { print "Shutdown\n"; };
EvProgress = func(self, fDone, msg = "") {
print("Progress: %d %s \r"::format(fDone*100, msg));
};
EvEventMsg = func(self, msg) {
print("\nEvent: %s\n"::format(iStat, msg));
};
};
var solver = rtwxlib.Solver(monitor);
solver::Open("test.wrx");
solver::DelGeometry();
solver::SaveAs('testresults.wrx');
solver::Close();
I was able to indentify the syntax of the language used as C. I beieve the problem I had which confused me was the libraries used for this code which I later found out was for a particular program. Thank you to all those who tried to help though :)

In Kotlin, how do I read the entire contents of an InputStream into a String?

I recently saw code for reading entire contents of an InputStream into a String in Kotlin, such as:
// input is of type InputStream
val baos = ByteArrayOutputStream()
input.use { it.copyTo(baos) }
val inputAsString = baos.toString()
And also:
val reader = BufferedReader(InputStreamReader(input))
try {
val results = StringBuilder()
while (true) {
val line = reader.readLine()
if (line == null) break
results.append(line)
}
val inputAsString = results.toString()
} finally {
reader.close()
}
And even this that looks smoother since it auto-closes the InputStream:
val inputString = BufferedReader(InputStreamReader(input)).useLines { lines ->
val results = StringBuilder()
lines.forEach { results.append(it) }
results.toString()
}
Or slight variation on that one:
val results = StringBuilder()
BufferedReader(InputStreamReader(input)).forEachLine { results.append(it) }
val resultsAsString = results.toString()
Then this functional fold thingy:
val inputString = input.bufferedReader().useLines { lines ->
lines.fold(StringBuilder()) { buff, line -> buff.append(line) }.toString()
}
Or a bad variation which doesn't close the InputStream:
val inputString = BufferedReader(InputStreamReader(input))
.lineSequence()
.fold(StringBuilder()) { buff, line -> buff.append(line) }
.toString()
But they are all clunky and I keep finding newer and different versions of the same... and some of them never even close the InputStream. What is a non-clunky (idiomatic) way to read the InputStream?
Note: this question is intentionally written and answered by the author (Self-Answered Questions), so that the idiomatic answers to commonly asked Kotlin topics are present in SO.
Kotlin has a specific extension just for this purpose.
The simplest:
val inputAsString = input.bufferedReader().use { it.readText() } // defaults to UTF-8
And in this example, you could decide between bufferedReader() or just reader(). The call to the function Closeable.use() will automatically close the input at the end of the lambda's execution.
Further reading:
If you do this type of thing a lot, you could write this as an extension function:
fun InputStream.readTextAndClose(charset: Charset = Charsets.UTF_8): String {
return this.bufferedReader(charset).use { it.readText() }
}
Which you could then call easily as:
val inputAsString = input.readTextAndClose() // defaults to UTF-8
On a side note, all Kotlin extension functions that require knowing the charset already default to UTF-8, so if you require a different encoding you need to adjust the code above in calls to include encoding for reader(charset) or bufferedReader(charset).
Warning: You might see examples that are shorter:
val inputAsString = input.reader().readText()
But these do not close the stream. Make sure you check the API documentation for all of the IO functions you use to be sure which ones close and which do not. Usually, if they include the word use (such as useLines() or use()) they close the stream after. An exception is that File.readText() differs from Reader.readText() in that the former does not leave anything open and the latter does indeed require an explicit close.
See also: Kotlin IO related extension functions
【Method 1 | Manually Close Stream】
private fun getFileText(uri: Uri):String {
val inputStream = contentResolver.openInputStream(uri)!!
val bytes = inputStream.readBytes() //see below
val text = String(bytes, StandardCharsets.UTF_8) //specify charset
inputStream.close()
return text
}
inputStream.readBytes() requires manually close the stream: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.io/java.io.-input-stream/read-bytes.html
【Method 2 | Automatically Close Stream】
private fun getFileText(uri: Uri): String {
return contentResolver.openInputStream(uri)!!.bufferedReader().use {it.readText() }
}
You can specify the charset inside bufferedReader(), default is UTF-8:
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.io/java.io.-input-stream/buffered-reader.html
bufferedReader() is an upgrade version of reader(), it is more versatile:
How exactly does bufferedReader() work in Kotlin?
use() can automatically close the stream when the block is done:
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.io/use.html
An example that reads contents of an InputStream to a String
import java.io.File
import java.io.InputStream
import java.nio.charset.Charset
fun main(args: Array<String>) {
val file = File("input"+File.separator+"contents.txt")
var ins:InputStream = file.inputStream()
var content = ins.readBytes().toString(Charset.defaultCharset())
println(content)
}
For Reference - Kotlin Read File
Quick solution works well when converting InputStream to string.
val convertedInputStream = String(inputStream.readAllBytes(), StandardCharsets.UTF_8)

SQLite storage API Insert statement freezes entire firefox in bootstrapped(Restartless) AddOn

Data to be inserted has just two TEXT columns whose individual length don't even exceed 256.
I initially used executeSimpleSQL since I didn't need to get any results.
It worked for simulataneous inserts of upto 20K smoothly i.e. in the bakground no lag or freezing observed.
However, with 0.1 million I could see horrible freezing during insertion.
So, I tried these two,
Insert in chunks of 500 records - This didn't work well since even for 20K records it showed visible freezing. I didn't even try with 0.1million.
So, I decided to go async and used executeAsync alongwith Bind etc. This also shows visible freezing for just 20K records. This was the whole array being inserted and not in chunks.
var dirs = Cc["#mozilla.org/file/directory_service;1"].
getService(Ci.nsIProperties);
var dbFile = dirs.get("ProfD", Ci.nsIFile);
var dbService = Cc["#mozilla.org/storage/service;1"].
getService(Ci.mozIStorageService);
dbFile.append('mydatabase.sqlite');
var connectDB = dbService.openDatabase(dbFile);
let insertStatement = connectDB.createStatement('INSERT INTO my_table
(my_col_a,my_col_b) VALUES
(:myColumnA,:myColumnB)');
var arraybind = insertStatement.newBindingParamsArray();
for (let i = 0; i < my_data_array.length; i++) {
let params = arraybind.newBindingParams();
// Individual elements of array have csv
my_data_arrayTC = my_data_array[i].split(',');
params.bindByName("myColumnA", my_data_arrayTC[0]);
params.bindByName("myColumnA", my_data_arrayTC[1]);
arraybind.addParams(params);
}
insertStatement.bindParameters(arraybind);
insertStatement.executeAsync({
handleResult: function(aResult) {
console.log('Results are out');
},
handleError: function(aError) {
console.log("Error: " + aError.message);
},
handleCompletion: function(aReason) {
if (aReason != Components.interfaces.mozIStorageStatementCallback.REASON_FINISHED)
console.log("Query canceled or aborted!");
console.log('We are done inserting');
}
});
connectDB.asyncClose(function() {
console.log('[INFO][Write Database] Async - plus domain data');
});
Also, I seem to get the async callbacks after a long time. Usually, executeSimpleSQL is way faster than this.If I use SQLite Manager Tool extension to open the DB immediately this is what I get ( as expected )
SQLiteManager: Error in opening file mydatabase.sqlite - either the file is encrypted or corrupt
Exception Name: NS_ERROR_STORAGE_BUSY
Exception Message: Component returned failure code: 0x80630001 (NS_ERROR_STORAGE_BUSY) [mozIStorageService.openUnsharedDatabase]
My primary objective was to dump data as big as 0.1 million + and then later on perform reads when needed.

Setting Constraints in Adobe Illustrator [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
Closed 7 years ago.
Improve this question
Is there a way to put restrictions on objects in Adobe Illustrator?
I want to place multiple objects to a POI. The objects themselves should always look at the POI. In addition, the orientation of the objects shall be updated, when the POI is moved.
Is there a way to define this type of logic in Adobe Illustrator?
Thanks for your help!
Jan
You can write a script to do that.
One issue is how to determine which of the objects is the correct one.
As a quick hacky solution is to use a naming convention: say the POI object contains the characters "POI" in it's name.
Once you've got the POI object it's just a matter of using atan2 to get the from every other object to the POI:
var dx = POI.x - obj.x;
var dy = POI.y - obj.y;
var angle = atan2(dy,dx);
Here's a quick script:
/*
* Rotates a bunch of selected items towards a chosen target
*
* Usage: select at least 2 objects and mark the "look at" target by having POI in the name of the item
*/
#target illustrator
var d = app.activeDocument;//current document
var s = d.selection;//current selection
var hasDocCoords = app.coordinateSystem == CoordinateSystem.DOCUMENTCOORDINATESYSTEM;
var poi = getPOI(s);//get an object that contains 'poi'/'POI' in the name
if(s.length > 1 && poi != undefined){//if there are at least 2 objects and one's a POI
var lookAt = getPos(poi);//get the position to look at
for(var i = 0 ; i < s.length; i++){//for each object
if(s[i] != poi){//that isn't the poi
var pos = getPos(s[i]);//get the position
//get the angle using atan2 and the difference vector between the two positions(current object and poi)
var angle = Math.atan2(pos[1]-lookAt[1],pos[0]-lookAt[0]);
//check if there's a rotation applied, if so, remove it first
if(s[i].tags.length > 0){
if(s[i].tags[0].name == "BBAccumRotation"){
s[i].rotate(s[i].tags[0].value* -57.2957795);//reverse rotate
s[i].tags[0].remove();
}
}
//if it doesn't have a rotation tag, add one so it can be removed when the script is reapplied
if(s[i].tags.length == 0){
var t = s[i].tags.add();
t.name = "BBAccumRotation";
t.value = angle;
}
s[i].rotate(angle * 57.2957795);//finally convert radians to degrees and apply the rotation
}
}
app.redraw();
}
function getPOI(s){//find POI in selection
for(var i = 0 ; i < s.length; i++)
if (s[i].name.toUpperCase().indexOf("POI") >= 0) return s[i];
}
function getPos(o){
var pos = hasDocCoords ? d.convertCoordinate (o.position, CoordinateSystem.DOCUMENTCOORDINATESYSTEM, CoordinateSystem.ARTBOARDCOORDINATESYSTEM) : o.position;
pos[0] += o.width;//offset to centre of object
pos[1] -= o.height;
return pos;
}
You can save it as something like Look At POI.jsx in the right location (ILLUSTRATOR_INSTALL_DIR/Presets/LOCALE/Scripts) so it becomes accessible via File > Scripts > Look At POI
To use it, select at least 2 objects make sure one contains POI in the name.
Here's a quick preview:
Note that the triangles are symbols. This makes it easy to adjust rotation (as you can see in the Symbols panel) globally if it needs tweaking. Another way is to add an offset to the angle in the script, but this feels flexible enough :)
A non scripted version might using the Symbol Spinner Tool but it's a slow and not very precise process:

Resources