Tcl/Tk
Curso On-Line de Programação

Entrada e saída em arquivos e portas

Tcl oferece um conjunto completo de comandos para realização de entrada e saída em arquivos e portas de comunicação. Em geral trabalhar com portas de comunicação é como trabalhar com arquivos, exigindo apenas um pouco mais de atenção, pois as portas podem parar de responder por alguns instantes. Em especial quando trabalhando com impressoras fiscais, conectadas à porta serial, ou scanners à porta paralela. Nestes casos é preciso introduzir rotinas de tratamento de erros e tentar repetidamente conectar à porta de comunicação. Por essa razão, nesta aula estudaremos também o sistema de tratamento de erros em Tcl.
 

Comandos de entrada e saída

A seguir são apresentados os comandos de entrada e saída em arquivos em Tcl. Alguns comandos possuem variações, assim, para uma descrição detalhada de todos os comandos disponíveis em Tcl para realização de entrada e saída em arquivos e portas de comunicação, consulte a documentação on-line, ou o Tcl/Tk Reference Guide, ou ainda o Tcl/Tk Electronic Reference.
 

Comando Descrição
close Fecha um canal de comunicação.
eof Retorna 1 se foi encontrado o final do arquivo, 0 caso contrário.
fblocked Retorna 1 se a última operação de leitura tiver exaurido todos os dados disponíveis no canal de comunicação, 0 caso contrário.
fconfigure Configura ou obtém as opções relativas ao canal de entrada e saída. São elas: -blocking; -bufferingfull|line|none; -buffersize; -translationauto, binary, cr,crlf e lf; -sockname; -peername; -mode.
fcopy Copia dados de um canal para outro. Pode operar em background e executar um comando à medida em que os dados são transferidos.
fileevent Avalia um script à medida que o canal se torna pisponível para leitura ou gravação.
flush Descarrega o buffer de saída.
gets Lê a próxima linha no canal de entrada, descartando o caractere de nova linha( \n ).
open Abre um canal de comunicação em um dos modos de acesso: r, r+, w, w+, a, a+.
puts Envia uma string para o canal de saída. Opcionalmente, omitindo o caractere de nova linha( \n ).
read Lê todos os caracteres no canal de entrada, ou o número especificado de bytes. Opcionalmente, omitindo o caractere de nova linha( \n ).
seek Posiciona o ponteiro de acesso no arquivo. A origem pode ser: start, current ou end.
socket Abre uma porta TCP, como cliente ou servidor.
tell Retorna a posição atual no arquivo.

Exemplos

open, read, puts, close

# Lê o arquivo de entrada
set entrada [open c:/autoexec.bat r]
set arquivo [read $entrada]
close $entrada
# Exibe o arquivo de entrada na tela
puts "Entrada:\n"
puts "$arquivo\n"
# Copia o arquivo de entrada c:\autoexec.bat para c:\autoexec.bak
set saida [open c:/autoexec.bak w]
puts $saida $arquivo
close $saida
# Lê o arquivo c:\autoexec.bak e o exibe na tela
set entrada [open c:/autoexec.bak r]
set arquivo [read $entrada]
close $entrada
puts "Saida:\n"
puts "$arquivo\n"


Um exemplo avançado

O exemplo a seguir é uma pequena biblioteca para ler e salvar configurações em arquivos de configuração. Arquivos de configuração têm o seguinte formato:

# Comentário
variável1=valor1
variável2=valor2
...
variávelN=valorN
Onde variável1, variável2, variávelN são nomes de variáveis e valor1, valor2, valorN são os valores atribuídos às variáveis.

Arquivos de configuração costuman ter a seguinte nomenclatura:

UNIX:    .nome_do_arquivo
Windows: nome_do_arquivo.ini
No UNIX, salve o arquivo no diretório do usuário: "~/". No Windows, na pasta da aplicação, ou na pasta "C:\Windows\".

Carregue a bliblioteca usando o camando source:

source rc.tcl
Caso tenha colocado o arquivo no mesmo diretório do seu programa. Caso contrário, indique o caminho completo.
 
# rc.tcl - Suporte a arquivos de recursos
#
# Copyright (c) 2000 by Roberto Luiz Souza Monteiro
#
# Veja o arquivo "licenca.termos" para informacoes sobre uso e redistribuicao
# deste arquivo, e para NEGACAO DE TODA E QUALQUER GARANTIA.

#
# rc_load rc_array rc_file
#
# Carrega um arquivo de recursos em um vetor associativo
#
# rc_array: vetor associativo onde cada elemento corresponde
#           a uma variavel no arquivo de recursos
#
# rc_file: arquivo de recursos
#
# Retorno: 1 - arquivo encontrado
#          0 - arquivo nao encontrado
#
# Linhas de comentarios comecam com o caractere sustenido(#)
# Linhas em branco sao ignoradas
# Recursos devem estar no formato: variavel=valor
#
proc rc_load {rc_array rc_file} {
    global $rc_array
    
    set rc_found 1
    
    if {[file exists $rc_file]} {
        set handle [open $rc_file r]
        set rc [read $handle]
        close $handle
        
        set rc_list [split $rc "\n"]
        
        if {[llength $rc_list] > 0} {
            for {set i 0} {$i < [llength $rc_list]} {incr i} {
                set rc_line [lindex $rc_list $i]

                set rc_line [string trim $rc_line]
                
                if {[string index $rc_line 0] != "#"} {
                    if {[string trim $rc_line] != ""} {
                        set rc_line_list [split $rc_line "="]
                        if {[llength $rc_line_list] == 2} {
                            set name [string trim [lindex $rc_line_list 0]]
                            set value [string trim [lindex $rc_line_list 1]]
                            
                            # Cria os elementos do vetor associativo
                            set ${rc_array}($name) $value
                        }
                    }
                }
            }
        }
    } else {
        set rc_found 0
    }
    
    return $rc_found
}

#
# rc_save rc_array rc_file
#
# Salva um vetor associativo em um arquivo de recursos
#
# rc_array: vetor associativo onde cada elemento corresponde
#           a uma variavel no arquivo de recursos
#
# rc_file: arquivo de recursos
#
# Recursos estarao no formato: variavel=valor
#
proc rc_save {rc_array rc_file} {
    global $rc_array
    
    set rc_list [array get $rc_array]
    
    set handle [open $rc_file w+]

    for {set i 0} {$i <= [expr "[llength $rc_list] - 2"]} {incr i} {
        set rc_line ""
        append rc_line [lindex $rc_list $i] "=" [lindex $rc_list [expr "$i + 1"]]
        
        incr i
        
        puts $handle $rc_line
    }
    
    close $handle
}


Trantando erros

Tcl oferece um recurso bastante poderoso para tratar erros: o comando catch. A sintaxe de catch é:

catch script variável
Onde script é o código Tcl cujos erros serão interceptados e variável é o nome de uma variável onde será salvo qualquer erro retornado pelo script. Caso ocorra um erro catch retornará 1, caso contrário retornará 0.

Exemplo:

set erro ""
set ocorreu_erro [ catch {
                       # Le o arquivo de entrada
                       set entrada [open c:/autoexec.bat r]
                       set arquivo [read $entrada]
                       close $entrada
                   } erro
]
if {$ocorreu_erro == 1} {
    puts "Ocorreu o seguinte erro enquanto tentava abrir o arquivo c:/autoexec.bat\n"
    puts "Erro: $erro\n"
} else {
    # Exibe o arquivo de entrada na tela
    puts "Entrada:\n"
    puts "$arquivo\n"
}


Gerando erros

Você pode retornar erros de suas funções através do comando return:

return [-code código] [-erroinfo informação] [-errorcode código_de_erro]
Onde código pode ser ok, error, return, break, continue ou um valor inteiro, informação contém uma descrição do erro e código_de_erro contém um código para o erro ocorrido.

Você também pode gerar erros através do comando error:

error mensagem [informação] [código_de_erro]
As variáveis globais errorInfo e errorCode receberão os valores informação e código_de_erro respectivamente.

Para uma descrição detalhada de todos os comandos disponíveis em Tcl para realização de entrada e saída em arquivos e portas de comunicação e tratamento de erros, consulte a documentação on-line, ou o Tcl/Tk Reference Guide, ou ainda o Tcl/Tk Electronic Reference.

Para maiores informações envie e-mail para info@souzamonteiro.com.


http://www.souzamonteiro.com
info@souzamonteiro.com

Copyright(C) 2000 by Roberto Luiz Souza Monteiro