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

如何使用相同格式的tcl智能地将tcl可读格式的变量写回文件,tcl,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)]} {

这段代码有一个名为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
我的
数据.tcl

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

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

我更改了存储列表的格式 从

在保存方法中我改变了

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

而这些变化也达到了目的。

改进建议 您可以简化序列化程序,并使其更加健壮

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

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数据结构

改进你的问题 请允许我说,你的问题不是一个恰当的问题。它并没有说明问题,人们必须阅读字里行间的内容和片段,才能感觉到你在追求什么。此外,代码示例应该减少到最低限度,以演示您感知到的问题。粘贴整个代码工作是没有帮助的

key3 {valueA valueB valueC}
key4 {valueX {valueY valueZ}}
key1 value1
key2 value2
method load {} {
  set fp [open /tmp/data.tcl r]
  set file_data [read $fp]
  array set dataArr $file_data
  close $fp
}
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
  }
}