Hello and welcome to our community! Is this your first visit?
Enjoy an ad free experience by logging in. Not a member yet? Register.

# Thread: can you write to a specific text file line using FileSystemObject

1. ## can you write to a specific text file line using FileSystemObject

Hi All,

I copied this from the internet....

One weakness with the FileSystemObject is that it cannot be used to directly modify specific lines in a text file; for example, you cannot write code that says, in effect, "Skip down to the fifth line in this file, make a change, and then save the new file." To modify line 5 in a 10-line text file, a script must instead:
1.
Read in the entire 10-line file.

2.
Write lines 1-4 back to the file.

3.
Write the modified line 5 to the file.

4.
Write lines 6-10 back to the file.

If the above is correct what exactly is the code to do that.

Also, I thought you could specify a line to read, if so would that also work to write.

Martin.

• it's probably easier to load the whole file into a string, .split(/\r?\n/) the string into an array of lines, set line 5 ( lines[5]='new text data'; ), and save the file with a string made from running .join("\r\n") on the array.

• Nothing to do with the FileSystemObject.

That's just how text files work. Excepting on some mainframe systems, a text file is just a "blob" of text so far as the operating system is concerned, and the OS has no idea that there is even such a concept as "lines". Heck, for all the OS knows, you might want your lines to end with a "\$" character or a "#" character. There is nothing at all special about the newline character (or characters, on Windows) so far as the operating system is concerned.

It is true that operating systems support "seeks" to a specific offset in a file (e.g., "go to byte number 7,327") and then allow you to read any number of bytes (e.g., "then read 37 bytes"). But the operating system does *NOT* keep track of where the LINES of a text file start.

So the only practical way to use "seeks" and "reads" is to have "lines" in the file that are all the same length. Which means that all your "lines" would have to reserve as much room as the longest possible line. Say we arbitrarily decided that lines must be no longer then 72 characters (that used to be a real limit, back in the 1960s, on some operating systems!). So if you had a line longer than that, you'd have to split it into multiple lines. And if you had one shorter, you'd have wasted space.

Needless to say, as computers got more sophisticated and "documents" started having lines that were hundreds of characters long, the idea of fixed length lines quickly went out of style, and so today text files are just blobs.

This is one reason that databases were invented: So that you *COULD* have the concept of "records". Maybe it's time you stopped trying to use text files for tasks better handled by a database?

• And RndMe's solution is a fine one if you only want to simply replace a single line.

But what happens when you want to replace line 73 with 14 new lines?

It's still not too hard, but it does explain why text editors and word processors do all their work in memory: The read the entire document into memory, manipulate it as needed, and then write the entire document back out all in one blob.

• Originally Posted by Old Pedant
And RndMe's solution is a fine one if you only want to simply replace a single line.

But what happens when you want to replace line 73 with 14 new lines?.
then you set line 73 with a string that has it's own linebreaks (13 of them), and everything works as expected...

• Yes, yes. Or any of a half dozen other techniques.

Such as:
Code:
addedlines = [ ];
... code to push any number of lines into addedlines ...
newlines = oldlines.slice(0,37).concat( addedlines ).concat( oldlines.slice(38);
But the important part is that you do all the manipulation *in memory* and then write the entire "blob" back to the file system. You don't depend on the FileSystemObject (or anything in the file system) to understand "lines" for you, as "lines" are not a natural part of files, per se. That's all I was trying to emphasize.

• Hi All,

I know I am not very good at explain things so I have put a working example of what I can do in this post.

In a lot of cases with the things I ask I like to try the what if and see what comes up and sometimes a code which maybe useful to someone for some use or other may come of it.

Let me explain what I was trying to do.
I have a stored file on the PC which can be read, appended and written using the fso method.

I was trying to work out a way to read the file and find a word on a line. If possible using some code to tell me what line that word was on. Once the line number was known some other code would delete that line from the file but keep all the other lines as they were. This was all to happen without needing to actually open the stored file by using the fso to do all the actions.

In the working example below, I can open the stored file and show the list in a textarea using the fso read all to display the file.

I can then use the shown code to split the lines and look for a specific word in each of those lines and if found to ignore the line. The other lines checked where the target word is not there are written into a second list textarea.

The second list textarea can then be resaved as the original stored file using the fso to write over the existing.

Here is what I can do, but am sure there is a better way, less code, no need to have textarea and so on. But I could be wrong.

Code:
<script>
i=0;
function StartCheck()
{
document.getElementById("one_line_of_information").value="";
document.getElementById("new_stored_List").value="";
runCheck();
}
function runCheck()
{
var makelines = document.getElementById("stored_information_textarea").value;
document.getElementById("one_line_of_information").value=makelines.split(/\r?\n/)[i];
i=i+1
var pos = 0;
var found = false;
var text = document.getElementById("one_line_of_information").createTextRange();
for (var fi=0; fi<=pos && (found=text.findText(document.getElementById("what_to_remove").value)) != false; fi++)
{
text.moveStart("character", 1);
text.moveEnd("textedit");
}
if (found)
{
text.moveStart("character", -1);
text.findText(document.getElementById("what_to_remove").value);
pos++;
fi=0;
}
else
{
document.getElementById("new_stored_List").value+=document.getElementById("one_line_of_information").value;
document.getElementById("new_stored_List").value+="\n";
if (i>makelines.split(/\r?\n/)[i].length){document.getElementById("one_line_of_information").value="";i=0;cleartimeout(u);}
}
u=setTimeout("runCheck()",1)
}
</script>

<BR>

The stored information shown displayed in a textarea.

<BR>

<textarea id="stored_information_textarea" value="" wrap="off" cols=100 rows=10>
0.Example below given numbered lines so you can see what was removed.
1.Demonstration search and remove a data line from the stored text file.
3.It is not known what will be here.
4.Lots of stuff will be recorded as a line of text for the site.
5.It's what I am trying to do for site.
6.Lines would not have a number in the real textarea but just be a next line as shown above.
7.The final output can be written back to the existing file name using fso in the normal way.
</textarea>

<BR><BR>

<textarea id="one_line_of_information" value="" wrap="off" cols=100 rows=2></textarea>

<BR><BR>

<textarea id="new_stored_List" value="" wrap="off" cols=100 rows=10></textarea>

<BR><BR>

Remove line/s containing this word <input type="text" id="what_to_remove" name="what_to_remove" value="general"> &nbsp; Try the word..... site .....in field.

<BR><BR>

<button onclick="StartCheck()">Remove Lines</button>

<BR><BR>

I know someone will tell me it only works in IE but that is fine for it's purpose, if you want to give example to make the find work in different browsers, please feel free to post a code.

Martin.

• i cached your element lookups so you're not performing getElementById() many times in the loop, though you should move some of them to pure string variables instead of using textboxes, but this is a start towards optimization:

Code:
i = 0;

function StartCheck() {
document.getElementById("one_line_of_information").value = "";
document.getElementById("new_stored_List").value = "";
runCheck();
} /* end StartCheck() */

function runCheck() {
var makelines = document.getElementById("stored_information_textarea").value,
toRemove=document.getElementById("what_to_remove").value,
oneLine=document.getElementById("one_line_of_information"),
newList=document.getElementById("new_stored_List");

oneLine.value = makelines.split(/\r?\n/)[i];
i = i + 1
var pos = 0;
var found = false;
var text = oneLine.createTextRange();
for (var fi = 0; fi <= pos && (found = text.findText(toRemove)) != false; fi++) {
text.moveStart("character", 1);
text.moveEnd("textedit");
} /* next fi++ */

if (found) {
text.moveStart("character", - 1);
text.findText(toRemove);
pos++;
fi = 0;
} else {
newList.value += oneLine.value;
newList.value += "\n";
if (i > makelines.split(/\r?\n/)[i].length) {
oneLine.value = "";
i = 0;
cleartimeout(u);
}
} /* end if(found) */
u = setTimeout("runCheck()", 1)
} /* end runCheck() */

• If those truly are lines in the text file, then I see no reason to use textRange. And I see no reason to even display the text in a <textarea>, though doing so doesn't hurt.

K.I.S.S.
Code:
<script type="text/javascript">
function removeLineContaining( containingWhat )
{
var fso = new ActiveXObject("Scripting.FileSystemObject");
var infile = fso.OpenTextFile("c:\\path\\to\\file.txt");
var removed = [ ];
infile.Close( );
for ( var n = lines.length-1; n >= 0; --n )
{
if ( line[n].indexOf(containingWhat) >= 0 )
{
removed.push( lines[n] );
lines.splice( n, 1 );
}
}
var outfile = fso.CreateTextFile("c:\\path\\to\\file.txt", true); // true==overwrite
outfile.write( lines.join("\n") );
outfile.Close();
return removed;
}
That returns all the removed lines in an array, as well.

• Hello Old Pedant,

I tried the suggested fso code to remove a line in a .txt file containing something without showing any displayed textarea, in this case the word "here" which only appears in one place on line 3.

This is the saved .txt file contents as before....
0.Example below given numbered lines so you can see what was removed.
1.Demonstration search and remove a data line from the stored text file.
3.It is not known what will be here.
4.Lots of stuff will be recorded as a line of text for the site.
5.It's what I am trying to do for site.
6.Lines would not have a number in the real textarea but just be a next line as shown above.
7.The final output can be written back to the existing file name using fso in the normal way.

The code as you wrote did not seem to do anything so just to check I entered into the code the actual word so there was no doubt what the indexOf was looking for. In one test I also used some lettering for the .split() so it knew where to split, just in case the \n was the problem.

However, so far nothing I have tried seems to work. Can you point out where I am going wrong in the code below.

Code:
<script type="text/javascript">
function removeLineContaining()
{
var fso = new ActiveXObject("Scripting.FileSystemObject");
var infile = fso.OpenTextFile("("c:\\path\\to\\file.txt");
var removed = [ ];
infile.Close( );
for ( var n = lines.length-1; n >= 0; --n )
{
if ( line[n].indexOf("here") >= 0 )
{
removed.push( lines[n] );
lines.splice( n, 1 );
}
}
var outfile = fso.CreateTextFile("("c:\\path\\to\\file.txt", true); // true==overwrite
outfile.write( lines.join("\n") );
outfile.Close();
return removed;
}
</script>

Martin.

• It doesn't work because it stops working on this line:
Code:
    var infile = fso.OpenTextFile("("c:\\path\\to\\file.txt");
And nothing after that happens. That is completely bogus. You have *THREE* quote marks in a line, which is impossible to be right. Quotes must appear in pairs.

• Hi,

I am sorry about that. My last post of the code was an error when I pasted your original example path address back in so as to not show the real one I am using.

The only changes below from your original is the removing of (containingWhat) and my addition of the "here" word hard coded into the code so there can be no doubt what is being checked for the indexOf.

I am okay with the C: file path as I already read, write and append files using the fso so know my target address to read and write are correct.

However, as I said I seem to be missing something in the code below because it just won't work for me. I am thinking is there and upper lower case issue and I note you have used outfile.write when I have often used whatever.WriteLine but I have tried swapping various things and still nothing.

Code:
<script type="text/javascript">
function removeLineContaining()
{
var fso = new ActiveXObject("Scripting.FileSystemObject");
var infile = fso.OpenTextFile("c:\\path\\to\\file.txt");
var removed = [ ];
infile.Close( );
for ( var n = lines.length-1; n >= 0; --n )
{
if ( line[n].indexOf("here") >= 0 )
{
removed.push( lines[n] );
lines.splice( n, 1 );
}
}
var outfile = fso.CreateTextFile("c:\\path\\to\\file.txt", true); // true==overwrite
outfile.write( lines.join("\n") );
outfile.Close();
return removed;
}
</script>
Martin.

• Hi again,

Panic over I found the error. I knew it would be something simple. It was a missing s from the word lines.

One of those cases where you cannot see the forest for the trees I just assumed all the lines words were in there the same.

Thanks very much for the code and it will be put to use.

Also thanks to.... rnd me whose ideas are also being put to good use.

Martin.

• LOL! I was just about to write a post saying the same thing.

Yep, it works with that one change.

Though I made another more useful change to my version:
Code:
<script type="text/javascript">
function removeLineContaining(what)
{
var fso = new ActiveXObject("Scripting.FileSystemObject");
var infile = fso.OpenTextFile("C:\\inetpub\\wwwroot\\dearabby\\forjohn.txt");
var removed = [ ];
infile.Close( );
for ( var n = lines.length-1; n >= 0; --n )
{
if ( lines[n].indexOf(what) >= 0 )
{
removed.push( lines[n] );
lines.splice( n, 1 );
}
}
var outfile = fso.CreateTextFile("C:\\inetpub\\wwwroot\\dearabby\\output.txt", true); // true==overwrite
outfile.write( lines.join("\n") );
outfile.Close();
return removed;
}
removeLineContaining("Rate");
</script>
See it? That was the whole point of the name "Containing": You could specify *what* you were looking for the line to contain as the argument to the function.

• Hi,

My approach to the indexOf is the use of the value from a remote input field via a document.getElementById("whatevertheword").value as that value changes from time to time to remove a different line.

I use this.... if ( lines[n].indexOf(document.getElementById("whatevertheword").value) >= 0 ) which functions fine.

If you see a problem with that method do say.

Martin.

•
Page 1 of 2 12 Last

#### Posting Permissions

• You may not post new threads
• You may not post replies
• You may not post attachments
• You may not edit your posts
•