How can you read a file line by line in JavaScript? - javascript

I'm writing a web-app for the iPad that will be loading data from a text file. (A sample data set is around ~400 kb). I have everything set up except the file reading. The way I have set up my code, you pass an object which reads a file line by line.
How can I read a file line by line?
If there is no direct way to read a file line by line, can someone please show me an example of how to read a file into a string object? (so that I can use the split method :P)

This could work, if I understood what you want to do:
var txtFile = new XMLHttpRequest();
txtFile.open("GET", "http://website.com/file.txt", true);
txtFile.onreadystatechange = function()
{
if (txtFile.readyState === 4) { // document is ready to parse.
if (txtFile.status === 200) { // file is found
allText = txtFile.responseText;
lines = txtFile.responseText.split("\n");
}
}
}
txtFile.send(null);

Mobile Safari doesn't have the File API, so I assume you're talking about reading from a web resource. You can't do that. When you read a resource via ajax, the browser will first read it fully into memory and then pass the entire string to your ajax callback as a string.
In your callback, you can take the string and break it into lines, and wrap that up in an object that has the API that your code wants, but you're still going to have the string in memory all at once..

With jQuery:
myObject = {}; //myObject[numberline] = "textEachLine";
$.get('path/myFile.txt', function(myContentFile) {
var lines = myContentFile.split("\r\n");
for(var i in lines){
//here your code
//each line is "lines[i]"
//save in object "myObject":
myObject[i] = lines[i]
//print in console
console.log("line " + i + " :" + lines[i]);
}
}, 'text');

i dont think thats possible until you use ajax to hit some server side code.

Related

Javascript - reading in a file and iterating over sentences

I'm trying to read in a local text file to perform functions like counting syllables, characters etc.,
I am trying to do this by doing:
var txtFile = new XMLHttpRequest();
txtFile.open("GET", "file://path/to/my/file.txt", true);
txtFile.onreadystatechange = function() {
if (txtFile.readyState === 4) { // Makes sure the document is ready to parse.
if (txtFile.status === 200) { // Makes sure it's found the file.
allText = txtFile.responseText;
//lines = txtFile.responseText.split("\r\n"); // Will separate each line into an array
} //"\r\n"
}
}
when I try to log 'txtFile' to the command line it prints [ObjectHtmlRequest], how do i look at what i'm loading and consequently iterate over it?
I also get an error message when i try doing this piece of code
var text = txtFile
//$(this).val();
//document.text_input.my_text.value = newtext;
var words = new Array(text.replace(/\s/g, ' ').split(' '));
which worked before, but i'm guessing it's not now because i'm no longer working with text
Most browsers won't allow JavaScript to use the local filesystem. Chrome definitely won't, I'm not sure about Firefox and the others.
What I do in that case is either :
Use a local web server based on the local directory if the file you want to read is static. I usually start it with python -mhttp.server (Python 3) or python -mSimpleHTTPServer (Python 2).
Use the latest HTML5 File API if you want to let the user choose the file. More information here.
EDIT: Well, what I said isn't entirely true. Chrome allows you to use local files, but you have to start it on the command line with a special switch (--allow-file-access-from-files), and frankly, it's a bother and is only really intended for development. Don't rely on it for anything in production!

Reading text file trough XMLHttpRequest produces syntax error in text file, works tough

I am reading a text file trough XMLHttpRequest inside Firefox trough the normal means, the text file consist of a single line of picture filenames seperated with a pipe symbol ('|').
Everything works in the end, my image list gets read, i can parse it just fine and load my pictures.
Here is the code for the curious.
bilderListeDatei.open("GET","./bilder/liste?nocachetrick="+jetzt.getTime(),true);
bilderListeDatei.onreadystatechange = function ()
{
if (bilderListeDatei.readyState === 4)
{
if (bilderListeDatei.status === 200)
{
bilderListe = bilderListeDatei.responseText.split("|");
elementeZuLaden += bilderListe.length;
for(var i in bilderListe)
{
var j = bilder.push(new Image());
bilder[j-1].onload = function()
{
elementeGeladen++;
if(elementeZuLaden == elementeGeladen){elementeLadenFertig = true;}
}
bilder[j-1].src = "./bilder/" + bilderListe[i];
//alert(j);
}
}
}
}
As said the syntax error is produced inside my text file, not the code, that works flawlessly.
Any idea how i could get rid of that (ignored by the rest of the programm) error message?
EDIT:
The error message because it got mangled up in the comment:
Zeitstempel: 18.01.2013 14:15:01
Fehler: Syntax-Fehler
Quelldatei: http://192.168.2.102/seitenbastel/bilder/liste?nocachetrick=1358514901070
Zeile: 1, Spalte: 1
Quelltext:
65.jpg|67.jpg|69.jpg|71.jpg|73.jpg|75.jpg|77.jpg|79.jpg|81.jpg|83.jpg|85.jpg|87.jpg|89.jpg|91.jpg|93.jpg|95.jpg|97.jpg
XMLHttpRequest will try to parse the results as XML, in general, to create the responseXML object. Your data is presumably not XML. You either need to tell the browser that in your Content-Type header (e.g. setting it to text/plain in your case) or tell the browser that you don't actually want a parsed DOM representation at all by setting responseType = "text" on the XHR object if you only plan to use the text.

jquery.get(url) synchronization

OS X 10.6.8, Chrome 15.0.874.121
I'm experiencing an issue with javascript/jquery: I want to download a header file from base url, then add some more text to it and than spit it out to the client. I'm using the following code:
var bb = new window.WebKitBlobBuilder;
$.get('js/header.txt', function(data) {
bb.append(data);
console.log("finished reading file");
});
console.log("just before getting the blog");
var blob = bb.getBlob('text/plain');
// append some more
saveAs(blob,"name.dxf");
But that fails because getting the file is only finished way after the saveAs(blob) is executed. I know I can fix it with:
var bb = new window.WebKitBlobBuilder;
$.get('js/header.txt', function(data) {
bb.append(data);
//append some more
var blob = bb.getBlob('text/plain');
saveAs(blob,"name.dxf");
});
But that does not really look attractive: I only want to use the get statement only to append the header to the blob, and if I want to read a footer from the file system, I have to do a get inside a get, and spit out the blob in the inner get
Are there alternative ways to withhold the code after the get statement from executing until the whole file has been successfully loaded?
No.*
But, if you want it to look more attractive, try to describe semantically what you are trying to achieve and then write functions accordingly. Maybe:
function loadBlob (loadHeader, loadBody) {
loadHeader(loadBody);
}
loadBlob(function (oncomplete) {
$.get("js/header.txt", function(data) {
bb.append(data);
oncomplete();
});
}, function () {
var blob = bb.getBlob('text/plain');
// append some more
saveAs(blob,"name.dxf");
});
I don't know, is that more attractive? Personally, I find the original just fine, so maybe mine isn't any better, but the point is to use sematics.
* You could use setTimeout to poll and see if the response has been received. That's technically an alternative, but certainly not more attractive, is it?

WIX: Where and how should my CustomAction create and read a temporary file?

I have a script CustomAction (Yes, I know all about the opinions that say don't use script CustomActions. I have a different opinion.)
I'd like to run a command, and capture the output. I can do this using the WScript.Shell COM object, then invoking shell.Exec(). But, this flashes a visible console window for the executed command.
To avoid that, I understand I can use the shell.Run() call, and specify "hidden" for the window appearance. But .Run() doesn't give me access to the StdOut of the executed process, so that means I'd need to create a temporary file and redirect the exe output to the temp file, then later read that temp file in script.
Some questions:
is this gonna work?
How do I generate a name for the temporary file? In .NET I could use a static method in the System.IO namespace, but I am using script here. I need to insure that the use has RW access, and also that no anti-virus program is going to puke on this.
Better ideas? I am trying very hard to avoid C/C++.
I could avoid all this if there were a way to query websites in IIS7 from script, without resorting to the IIS6 Compatibility pack, without using .NET (Microsoft.Web.Administration.ServerManager), and without execing a process (appcmd list sites).
I already asked a separate question on that topic; any suggestions on that would also be appreciated.
Answering my own question...
yes, this is going to work.
Use the Scripting.FileSystemObject thing within Javascript. There's a GetTempName() method that produces a file name suitable for temporary use, and a GetSpecialFolder() method that gets the location of the temp folder. There's even a BuildPath() method to combine them.
so far I don't have any better ideas.
Here's the code I used:
function GetWebSites_IIS7_B()
{
var ParseOneLine = function(oneLine) {
...regex parsing of output...
};
LogMessage("GetWebSites_IIS7_B() ENTER");
var shell = new ActiveXObject("WScript.Shell");
var fso = new ActiveXObject("Scripting.FileSystemObject");
var tmpdir = fso.GetSpecialFolder(SpecialFolders.TemporaryFolder);
var tmpFileName = fso.BuildPath(tmpdir, fso.GetTempName());
var windir = fso.GetSpecialFolder(SpecialFolders.WindowsFolder);
var appcmd = fso.BuildPath(windir,"system32\\inetsrv\\appcmd.exe") + " list sites";
// use cmd.exe to redirect the output
var rc = shell.Run("%comspec% /c " + appcmd + "> " + tmpFileName, WindowStyle.Hidden, true);
// WindowStyle.Hidden == 0
var ts = fso.OpenTextFile(tmpFileName, OpenMode.ForReading);
var sites = [];
// Read from the file and parse the results.
while (!ts.AtEndOfStream) {
var oneLine = ts.ReadLine();
var line = ParseOneLine(oneLine);
LogMessage(" site: " + line.name);
sites.push(line);
}
ts.Close();
fso.DeleteFile(tmpFileName);
return sites;
}

Loaded data truncated when using nsIFileInputStream & nsIConverterInputStream

I'm working on a project (BrowserIO - go to browserio dot googlecode dot com if you want to check out the code and work on it. Help welcome!) in which I'm using Firefox's nsIFileInputStream in tandem with nsIConverterInputStream, per their example (https://developer.mozilla.org/en/Code_snippets/File_I%2F%2FO#Simple), but only a portion of the full data is being loaded. The code is:
var file = Components.classes["#mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
file.initWithPath(path);
var data = "";
var fstream = Components.classes["#mozilla.org/network/file-input-stream;1"].createInstance(Components.interfaces.nsIFileInputStream);
var cstream = Components.classes["#mozilla.org/intl/converter-input-stream;1"].createInstance(Components.interfaces.nsIConverterInputStream);
fstream.init(file, -1, 0, 0);
cstream.init(fstream, "UTF-8", 0, 0); // you can use another encoding here if you wish
var str = {};
cstream.readString(-1, str); // read the whole file and put it in str.value
data = str.value;
cstream.close(); // this closes fstream
If you want to see this behavior, checkout the code from the BrowserIO project page, and use Firebug to set a breakpoint at the data = str.value; line in file_io.js. Then select a text file from the list, and click the "Open" button. In Firebug, in the watch panel set a watch for str.value. Look at the file... It should be truncated, unless it's really short.
For reference, the code above is the main body of the openFile() function in trunk/scripts/file_io.js.
Anybody have any clue what's happening with this?
See nsIConverterInputStream; basically, -1 doesn't mean "give me everything" but rather "give me the default amount", which the docs claim is 8192.
More generally, if you want to exhaust the contents of an input stream, you have to loop until it's empty. Nothing in any of the stream contracts guarantees that the amount of data returned by a call is the entirety of the contents of the stream; it could even return less than it has immediately available if it wanted.
I discovered how to do the file read without converting, to avoid issues from not knowing the file encoding type. The answer is to use nsIScriptableInputStream with nsIFileInputStream:
var sstream = Components.classes["#mozilla.org/scriptableinputstream;1"].createInstance(Components.interfaces.nsIScriptableInputStream);
fstream.init(file, 0x01, 0004, 0);
sstream.init(fstream);
data = sstream.read(sstream.available());

Categories

Resources