如何使用tcl以相同的格式智能地将tcl可读格式的变量写回文件

时间:2018-03-13 17:36:29

标签: tcl

此代码有一个名为class1的类,方法有set,get,load,save

# Class1 definition
oo::class create class1 {
    variable dataArr

    method set {key value} {
        set dataArr($key) $value
    }

    method get {key} {
        if {[info exist dataArr($key)]} {
            return $dataArr($key)
        }
    }

    method load {} {
        set fp [open /home/karthikc/data.tcl r]
        set file_data [read $fp]
        puts $file_data
        eval  $file_data
        close $fp
    }

    method save {{newFilePath ""}} {
        if [info exists filePath] {
            set tmpFP $filePath  
        }
        if {$newFilePath ne ""} { 
            set tmpFP $newFilePath
        }

        if ![info exists tmpFP] {
            puts"neither newFilePath argument is passed nor filePath variable is present"
            return 0
        } 

        try {
            set fhandle [open $tmpFP w]

            if ![info exists dataArr] {
                puts "dataArr variable doesn't exist in the object [self]"
                return 0
            }
            foreach key [array names dataArr] {
                set kvPair [list $key $dataArr($key)]
                lappend dataLst $kvPair
                puts $fhandle "my set $key $dataArr($key)"
                puts "my set $key $dataArr($key)"
            }


            set filePath $tmpFP
            puts "dictionary is successfully saved in the file path"
        } on error {result opts} {
            puts $result
            puts "Return options Directory"
            puts $opts
            return 0
        } finally {
            if [info exist fhandle] {
                close $fhandle
            }
        }
        return 1
    }
}

我使用的是这样的:

# create object instance
set obj [class1 new]

# call load method
$obj load

# call save method
$obj save /home/karthikc/data.tcl

我的data.tcl

my set key1 value1
my set key2 value2
my set key3 [list valueA valueB valueC]
my set key4 [list valueX [list valueY valueZ]]

我想回写相同格式或其他列表列表

2 个答案:

答案 0 :(得分:1)

改进建议

您可以简化SERIALIZER,并在整个过程中使其更加强大。

首先,不要将对象的状态序列化为脚本,而是将文字映射(Tcl中的关联数组或字典)序列化。并按原样阅读:

data.tcl可能如下:

key3 {valueA valueB valueC}
key4 {valueX {valueY valueZ}}
key1 value1
key2 value2

您的load方法可以使用array set直接阅读此内容:

method load {} {
  set fp [open /tmp/data.tcl r]
  set file_data [read $fp]
  array set dataArr $file_data
  close $fp
}

您的save方法可以直接使用array get并生成格式化输出:

method save2 {{newFilePath ""}} {
  if {[array exists dataArr]} {
    set fhandle [open $newFilePath w]
    set out ""
    foreach {k v} [array get dataArr] {
      append out $k " " [list $v] \n
    }
    puts $fhandle $out
    close $fhandle
  }
}

这个想法的关键是避免eval,因此,代码注入。序列化格式匹配1:1的一流Tcl数据结构。

改善您的问题

请允许我说,你的问题不是一个合适的问题。它没有说明问题,人们必须在线条和片段之间进行阅读,以感知你所追求的是什么。此外,代码示例应该减少到最小,以证明您的感知问题。粘贴整个代码工作没有帮助。

答案 1 :(得分:0)

我改变了存储列表的格式 来自

my set key1 value1
my set key2 value2
my set key3 [list valueA valueB valueC]
my set key4 [list valueX [list valueY valueZ]]

my set key1 value1
my set key2 value2
my set key3 {valueA valueB valueC}
my set key4 {valueX {valueY valueZ}}

并在保存方法中我改变了

puts $fhandle "my set $key $dataArr($key)"

puts $fhandle [list my set $key $dataArr($key)]

这些改变是有目的的。