Dexygen
Dexygen

Reputation: 12561

Prepending line to a file in platform-independent way

Within a Tcl application I need to prepend a line of Javascript code to an existing .js file. I googled for "tcl prepend line to file" and didn't find any particularly helpful examples especially in that I need this to be platform-independent.

One approach I found to work is to first open the file for reading, and then for writing, in the following manner:

set fileName [file join $appContentDir deleteBinDir.js]
set _fileR [open $fileName r]
set fileContent [read $_fileR]
close $_fileR

set _fileW [open $fileName w]
puts $_fileW "var path = '[file join $appNwDir bin]';\n"
puts $_fileW $fileContent
close $_fileW

The resulting Javascript code being:

var path = 'C:/opt/dev/dexygen/poc/2eggz/rename_2eggz.vfs/../nw/bin'; //prepended line

var gui = require('nw.gui');
var fs = require('fs');
var p = require("path");

gui.Window.get().on('close', deleteDirectoryContents);

function deleteDirectoryContents() {
    //etc

However in one of the results from google search (http://www.tek-tips.com/viewthread.cfm?qid=1691902) there was mention of needing to prepend a line to a large file in which case I might worry about opening/closing the file twice. Is there another approach that might work?

Upvotes: 1

Views: 250

Answers (3)

glenn jackman
glenn jackman

Reputation: 247210

Using fcopy might be quicker:

file rename file file.orig
set fin [open file.orig r]
set fout [open file w]

puts $fout "first line"
fcopy $fin $fout

close $fin
close $fout
file delete file.orig

Upvotes: 2

Peter Lewerin
Peter Lewerin

Reputation: 13282

You can cut some corners by doing this:

set fileName [file join $appContentDir deleteBinDir.js]
set _fileR [open $fileName r+]
set fileContent [read $_fileR]

set preamble "var path = '[file join $appNwDir bin]';\n"
seek $_fileR 0
puts $_fileR $preamble\n$fileContent
close $_fileR

or this

package require fileutil
set fileName [file join $appContentDir deleteBinDir.js]
set preamble "var path = '[file join $appNwDir bin]';\n"
::fileutil::insertIntoFile $fileName 0 $preamble\n 

Documentation: fileutil (package)

Upvotes: 1

Dexygen
Dexygen

Reputation: 12561

I found that I could do this by opening the file in r+ mode and using seek. The first three lines of code are essentially the same, but then I stored the line to prepend in a variable. This allowed me to a) write the line to the first position in the file and b) write the original file contents to the position in the file equating to the length of the line being prepended

set fileName [file join $appContentDir deleteBinDir.js]
set _fileR [open $fileName r+]
set fileContent [read $_fileR]

set preamble "var path = '[file join $appNwDir bin]';\n"
seek $_fileR 0
puts $_fileR $preamble

seek $_fileR [string length $preamble]
puts $_fileR $fileContent
close $_fileR

The only difference being that there is no second new line after the prepended line, which presumably could be rectified, but functionally makes no difference.

Upvotes: 0

Related Questions