ManInTheMiddle
ManInTheMiddle

Reputation: 128

Tcl/Tk write in a specific line

I want to write in a specific line in Textdocument but there´s a Problem with my code, i don´t know where the bug is.

set fp [open C:/Users/user/Desktop/tst/settings.txt w]
set count 0
while {[gets $fp line]!=-1} {
    incr count
    if {$count==28} {
            break
    }
}
puts $fp "TEST"
close $fp

The File only contains TEST. Has anybody an idea?

Upvotes: 2

Views: 3421

Answers (4)

Donal Fellows
Donal Fellows

Reputation: 137567

With short text files (these days, short is up to hundreds of megabytes!) the easiest way is to read the whole file into memory, do the text surgery there, and then write the whole lot back out. For example:

set filename "C:/Users/user/Desktop/tst/settings.txt"

set fp [open $filename]
set lines [split [read $fp] "\n"]
close $fp

set lines [linsert $lines 28 "TEST"]
# Read a line with lindex, find a line with lsearch
# Replace a line with lset, replace a range of lines with lreplace

set fp [open $filename w]
puts $fp [join $lines "\n"]
close $fp

Doing it this way is enormously easier, and avoids a lot of complexities that can happen with updating a file in place; save those for gigabyte-sized files (which won't be called settings.txt in any sane world…)

Upvotes: 4

glenn jackman
glenn jackman

Reputation: 246754

I'd suggest it would be easier to spawn an external program that specializes in this:

exec sed -i {28s/.*/TEST/} path/to/settings.txt

Upvotes: 1

Ashish
Ashish

Reputation: 266

You are using 'w' as access argument, which truncates the file. So you will loose all data from file while opening. Read more about open command

You can use 'r+' or 'a+'.

Also To write after a particular line you can move the pointer to the desired location.

set fp [open C:/Users/user/Desktop/tst/settings.txt r+]
set count 0

while {[gets $fp line]!=-1} {
    incr count
    if {$count==28} {
            break
    }
    set offset [tell $fp]
}
seek $fp $offset
puts $fp "TEST"
close $fp

To replace a complete line it would be easier to do in following way. Rewrite all the lines and write new data on the desired line.

set fp [open C:/Users/user/Desktop/tst/settings.txt r+]
set count 0
set data [read $fp]
seek $fp 0
foreach line [split $data \n] {
    incr count
    if {$count==28} {
        puts $fp "TEST"
    } else {
        puts $fp $line
    }
}
close $fp

Upvotes: 2

Peter Lewerin
Peter Lewerin

Reputation: 13252

package require fileutil

set filename path/to/settings.txt

set count 0
set lines {}
::fileutil::foreachLine line $filename {
    incr count
    if {$count == 28} {
        break
    }
    append lines $line\n
}
append lines TEST\n
::fileutil::writeFile $filename $lines

This is a simple and clean way to do it. Read the lines up to the point where you want to write, and then write back those lines with your new content added.

Upvotes: 1

Related Questions