Página 1 de 1

Tamanho das variáveis nos .MEM

Enviado: 20 Mar 2010 17:01
por clodoaldomonteiro
Olá amigos.

Tenho algumas variaveis que preciso guardar em um arquivo .mem, tipo DrvAutoHelp, que tem 11 caracteres, ms só que quando mando guardar no arquivo .mem com o comando SAVE, ele grava o nome da variável com no máximo 10 caracteres.

Tem como corrigir essa deficiência do xHarbour?

Re: Tamanho das variáveis nos .MEM

Enviado: 20 Mar 2010 17:45
por rochinha
Amiguinho,

A muito tempo não uso arquivos .MEM e seus comandos de manipulação.

Tive a necessidade de gravar informações em arquivos que não .DBF e recorri a funções encontradas em meus livros embolorados.

A tempos faço uso delas e não tenho problema com tamanho dos conteúdos.

Funções:

Código: Selecionar todos

/*
 *
 * *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
 * Descricao: Funcoes para tratamento de arrays
 * *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
 *
 */
Function EK_SAVEARR(Arg1, Arg2, Arg3)        //Arg1=Array, Arg2=archivo, Arg3=doserror
   local Local1:= Fcreate(Arg2), Local2
   Arg3:= Ferror()
   If (Arg3 == 0)
      Local2:= _eksavesub(Arg1, Local1, @Arg3)
      Fclose(Local1)
      If (Local2 .AND. Ferror() != 0)
         Arg3:= Ferror()
         Local2:= .F.
      EndIf
    Else
      Local2:= .F.
   EndIf
   Return Local2

Static Function _EKSAVESUB(Arg1, Arg2, Arg3)
   local Local1, Local2, Local3
   private lret
   lret:= .T.
   Local1:= ValType(Arg1)
   Fwrite(Arg2, Local1, 1)
   If (Ferror() == 0)
     Do Case
      Case Local1 = "A"
         Local2:= Len(Arg1)
         Fwrite(Arg2, L2Bin(Local2), 4)
         If (Ferror() == 0)
           AeVal(Arg1, {|_1| lret:= _eksavesub(_1, Arg2)})
          Else
           lret:= .F.
         EndIf
      Case Local1 = "B"
         lret:= .F.
      Case Local1 = "C"
         Local2:= Len(Arg1)
         Fwrite(Arg2, L2Bin(Local2), 4)
         Fwrite(Arg2, Arg1)
      Case Local1 = "D"
         Local2:= 8
         Fwrite(Arg2, L2Bin(Local2), 4)
         Fwrite(Arg2, DToC(Arg1))
      Case Local1 = "L"
         Local2:= 1
         Fwrite(Arg2, L2Bin(Local2), 4)
         Fwrite(Arg2, iif(Arg1, "T", "F"))
      Case Local1 = "N"
         Local3:= Str(Arg1)
         Local2:= Len(Local3)
         Fwrite(Arg2, L2Bin(Local2), 4)
         Fwrite(Arg2, Local3)
     Endcase
    Else
      lret:= .F.
   Endif
   Arg3:= ferror()
   Return lret

Function EK_RESTARR(Arg1, Arg2)       // Arg1=Archivo, Arg2=doserror
   Local Local1:= Fopen(Arg1), Local2
   Arg2:= Ferror()
   If (Arg2 == 0)
      Local2:= _ekrestsub(Local1, @Arg2)
      FClose(Local1)
    Else
      Local2:= {}
   Endif
   Return Local2

Static Function _EKRESTSUB(Arg1, Arg2)
   local Local1:= " ", Local2, Local3, Local4, Local5, Local6
   Fread(Arg1, @Local1, 1)
   Local3:= Space(4)
   Fread(Arg1, @Local3, 4)
   Local2:= Bin2L(Local3)
   Arg2:= Ferror()
   If (Arg2 == 0)
      Do Case
         Case Local1 = "A"
            Local4:= {}
            For Local6 := 1 To Local2
               AAdd(Local4, _ekrestsub(Arg1))
            Next Local6
         Case Local1 = "C"
            Local4:= Space(Local2)
            Fread(Arg1, @Local4, Local2)
         Case Local1 = "D"
            Local5:= Space(8)
            Fread(Arg1, @Local5, 8)
            Local4:= CToD(Local5)
         Case Local1 = "L"
            Local5:= " "
            Fread(Arg1, @Local5, 1)
            Local4:= Local5 = "T"
         Case Local1 = "N"
            Local5:= Space(Local2)
            Fread(Arg1, @Local5, Local2)
            Local4:= Val(Local5)
      Endcase
         Arg2:= ferror()
   Endif
   Return Local4
Mesmo que o trecho abaixo pareça não tenha nada a ver com o tópico servirá de ajudar para saber como usar:

Código: Selecionar todos

Function ListaOpcoes( _array_, _controle_, _sarray_ )
   local oTBLDlg, oTBLLbx, cTBLDlg := _array_[1], lSave := .f.
   DEFINE DIALOG oTBLDlg RESOURCE "dlgTBLAux"
          REDEFINE LISTBOX oTBLLbx VAR cTBLDlg ITEMS _array_ ID 101 OF oTBLDlg 
                   oTBLLbx:bLdblClick := {|nRow,nCol|( lSave:=.t., oTBLDlg:end() )}
          REDEFINE BUTTON ID 5 OF oTBLDlg ACTION ( lSave:=.t., oTBLDlg:end() )
          REDEFINE BUTTON ID 4 OF oTBLDlg ACTION ( lSave:=.f., oTBLDlg:end() )
          REDEFINE BUTTON ID 3 OF oTBLDlg ACTION ( AddOpcoes( _array_, _sarray_ ), ;
                                                   oTBLLbx:Reset() , ;
                                                   oTBLLbx:SetItems(_array_) , ;
                                                   oTBLLbx:Refresh() )
          // MODIFICAR REDEFINE BUTTON ID 2 OF oTBLDlg ACTION fun()
          REDEFINE BUTTON ID 6 OF oTBLDlg ACTION ( nExcluir:=oTBLLbx:GetPos(), ;
                                                   iif( DelOpcoes( _array_, _sarray_, nExcluir ), ;
                                                        ( oTBLLbx:Reset() , ; // ( oTBLLbx:Del(nExcluir) , ;
                                                          oTBLLbx:SetItems(_array_) , ;
                                                          oTBLLbx:Refresh() ), .t. ) )
   ACTIVATE DIALOG oTBLDlg CENTERED VALID ( oTBLDlg := nil, .t.  )
   if lSave
      _controle_:cText(cTBLDlg+SPACE(80))
      _controle_:Refresh()
   endif
   return nil

Function AddOpcoes( _array_, _sarray_ )
   local lSave := .f., cArrData := SPACE(25)
   SET _3DLOOK ON
   DEFINE FONT fntHelv2     NAME "Helv"          SIZE  6, 6
   DEFINE DIALOG oDlg RESOURCE "dlgEstCTab" TITLE "Preferencia" FONT fntHelv2
          REDEFINE SAY oCtrl100 PROMPT "Preferencia" ID 100 OF oDlg
          REDEFINE GET oCtrl101 VAR cArrData PICTURE "@!" ID 101 OF oDlg
          REDEFINE BUTTON ID 1 OF oDlg ACTION ( lSave:=.t., oDlg:end() )
          REDEFINE BUTTON ID 2 OF oDlg ACTION ( lSave:=.f., oDlg:end() )
   ACTIVATE DIALOG oDlg CENTERED
   if lSave
      aLenArray:=len(_array_)
      ASize(_array_, aLenArray+1 )
      AIns(_array_, aLenArray+1 )
      _array_[aLenArray+1] := cArrData
      EK_SAVEARR( ASort(_array_), _sarray_ )
   endif
   return nil

Function DelOpcoes( _array_, _sarray_, _posicao_ )
   if MsgYesNo( 'Excluir '+_array_[_posicao_] )
      aLenArray:=len(_array_)
      ADel( _array_, _posicao_ )
      ASize(_array_, aLenArray-1 )
      EK_SAVEARR( _array_, _sarray_ )
      return .t.
   else
      return .f.
   endif
Como eu uso em meus sistemas?

Primeiro eu verifico se meu arquivo Array existe na pasta do sistema:

Código: Selecionar todos

...
public aHistos  := EK_RESTARR( "histos.arr" )
...
Em um de meus GETs, simulo combos e passo as variáveis:

Código: Selecionar todos

...
VALID ListaOpcoes( aHistos, oGet109, "histos.arr" )
...
Use o segundo parâmetro, se for o caso para passar a variável do GET e refrescar seu conteúdo.

Minha função ListaOpções se encarrega de mostrar em um browse, as informações salvas e alguns botões/funções me permitem incluir, excluir, etc.

Analise com cuidado o código e implemente em sua aplicação.

Re: Tamanho das variáveis nos .MEM

Enviado: 20 Mar 2010 18:16
por alxsts
Olá!

Clodoaldo:
na inguagem Clipper, embora seja possível a declaração de nomes de variáveis, procedures e functions com mais de dez caracteres (o compilador não gera erro), apenas os dez caracteres iniciais são considerados. Assim, a variável declarada com o nome DrvAutoHelp consta na tabela de símbolos como DrvAutoHel. O limite para nomes de campos em um DBF é o mesmo.

Certamente o [x]Harbour seguiu este mesmo caminho.

Re: Tamanho das variáveis nos .MEM

Enviado: 21 Mar 2010 07:46
por clodoaldomonteiro
Pessoal!

Fiz o seguinte teste no xHarbour:

Código: Selecionar todos

   v1234567890:='clodoaldo'
   v12345678901:='monteiro'
   v1234567890123453456789:='de'
   ? v1234567890, v12345678901, v1234567890123453456789
   wait
   retu
O resultado foi:
clodoaldo monteiro de
Então, com certeza o harbour reconhece mais de 15 caracteres no nomes da variáveis.
Vejam que o radical das variáveis é o mesmo, mas ainda assim o harbour diferenciou elas.

Agora, se eu usar o comando:

Código: Selecionar todos

SAVE TO (MeuArquivoMem) ALL LIKE V*   // grava configuracoes,
Será gerado um arquivo .mem com três variáveis de nome: "v123456789", cada uma com seu conteúdo diferente.

Ai, quando recuperamos o arquivo .mem o xharbour traz uma única variável com o nome: "v123456789" e o conteúdo da última.

Em anexo está o arquivo .mem

Re: Tamanho das variáveis nos .MEM

Enviado: 21 Mar 2010 08:15
por clodoaldomonteiro
Encontrei o comando SAVE no arquivo STD.CH, que vem originalmente no clipper 5.3.

Código: Selecionar todos

#command SAVE ALL LIKE <skel> TO <(file)>                               ;
      => __MSave( <(file)>, <(skel)>, .t. )

#command SAVE TO <(file)> ALL LIKE <skel>                               ;
      => __MSave( <(file)>, <(skel)>, .t. )

#command SAVE ALL EXCEPT <skel> TO <(file)>                             ;
      => __MSave( <(file)>, <(skel)>, .f. )

#command SAVE TO <(file)> ALL EXCEPT <skel>                             ;
      => __MSave( <(file)>, <(skel)>, .f. )

#command SAVE [TO <(file)>] [ALL]                                       ;
      => __MSave( <(file)>, "*", .t. )


No xHarbour tá assim:

Código: Selecionar todos

#command SAVE TO <(f)> [<b:EXTENDED>]   ALL LIKE <(p)>     => __MVSave( <(f)>, <(p)>, .t. ,<.b.>)
#command SAVE ALL LIKE <(p)> TO <(f)>   [<b:EXTENDED>]   => __MVSave( <(f)>, <(p)>, .t. ,<.b.>)
#command SAVE ALL EXCEPT <(p)> TO <(f)> [<b:EXTENDED>]  => __MVSave( <(f)>, <(p)>, .f. ,<.b.>)
#command SAVE TO <(f)> [<b:EXTENDED>]  ALL EXCEPT <(p)>   => __MVSave( <(f)>, <(p)>, .f. ,<.b.>)
#command SAVE [TO <(f)>] [ALL]      [<b:EXTENDED>]    => __MVSave( <(f)>, "*", .t. ,<.b.>)
Vi que nesse arquivo tem vários comandos que usamos corriqueiramento quando estamos programando.

Vocês acham que teríamos como alterar esses comandos?
Pois vejam que o comando SAVE chama a FUNÇÂO __MSave(), mas onde posso editar ela?

Re: Tamanho das variáveis nos .MEM

Enviado: 21 Mar 2010 10:20
por sygecom
Você encontra nos fontes do xHarbour, isso que você procura esta em:
\xHarbour\source\vm\memvars.c

Re: Tamanho das variáveis nos .MEM

Enviado: 21 Mar 2010 11:26
por clodoaldomonteiro
Leonardo!

Eu não tenho essa pasta, mas pela lógica, depois de editar e midificar esse arquivo, teria que compilar novamente?

Re: Tamanho das variáveis nos .MEM

Enviado: 21 Mar 2010 11:34
por Maligno
Ao que parece pelos relatos das suas experiências com .MEM, imagino que os autores (conscientemente ou não) limitaram o tamanho dos símbolos em 10 caracteres. Com os fontes do [x]Harbour, você até pode modificar isso, mas terá de recompilar o [x]Harbour, para obter o "SEU" compilador. E isso terá de ser refeito todas as vezes em que trocar de versão, até que um dia alguém do time de desenvolvimento resolva acabar com essa limitação. Porque não tenta se comunicar com eles e requisitar essa modificação?

Note um detalhe interessante: .MEM é algo meio fora de moda. Se até agora ainda existe essa limitação, pode ser porque ninguém dá bola pra .MEM. Talvez seja interessante começar a pensar em trocar a forma de armazenamento. Particularmente, eu prefiro INI para casos semelhantes.

Re: Tamanho das variáveis nos .MEM

Enviado: 21 Mar 2010 16:51
por asimoes
Senhores,

Por esta limitação dos arquivos .mem, o ideal é usar arquivos .ini

Re: Tamanho das variáveis nos .MEM

Enviado: 21 Mar 2010 18:47
por rochinha
Amiguinho Clodoaldo,

Voce esta usando Clipper e quer adaptar as funções do xHarbour? será perda de tempo.

Os .CH do Clipper não são usados pelo xHarbour e voce não precisa adaptar os .CH padrão do xHarbour porque os mesmos já estão compatibilizados.

Utilize a idéia que passei e obterá bons resultados, ou utilize arquivos .INI como o Maligno frisou.

Realmente se o xHarbour é uma evolução do Clipper, se melhoraram o alcance de registros do .DBf e Arrays porque não melhoraram para os Arquivos .MEM? não sei.

Voce fez comparação de variáveis existentes em código e variáveis existentes dentro de um .MEM. Dentro do Código voce pode usar variáveis com tamanho maior, mas nem tanto.

Tamanho das variáveis nos .MEM

Enviado: 30 Ago 2022 14:07
por clodoaldomonteiro
Depois de um tempinho, voltando aqui pra deixar uma função pra verificar a validade de um Arquivo MEM.
Cada variável salva tem um tamanho fixo de 10 caracteres, sendo que o 11. e 12. são respectivamente NUL e (ÃÌÎ)-uma das três letras.
- para as variáveis tipo String e Data os caracteres NUL e "Ã" indicam o término do nome da variável.
- para as variáveis tipo Número e Data os caracteres NUL e "Ì" indicam o término do nome da variável.
- para as variáveis tipo Lógico e Data os caracteres NUL e "Î" indicam o término do nome da variável.
- no final do arquivo, tem obrigatoriamente dois caracteres, NUL e SUB (valores em HexaDecimal 00 e 0A)
Sendo assim, dá pra com uma simples rotina de ler o arquivo e verificar os caracteres em suas devidas posições, confirmando se é um arquivo válido.

Código: Selecionar todos

Function cl_checaMEM( cFileName )
   Local mRetorno := .t., cTect

   cText := MemoRead( cFileName )

   If !( SubStr( cText, 12, 1) $ 'ÃÌÎ' )
      mRetorno := .f.
   Endif //

   If !(StrToHex(SubStr( cText, Len(cText), 1)) = '00' )
      mRetorno := .f.
   Endif
   
   If !(StrToHex(SubStr( cText, Len(cText)-1, 1)) = '0A')
      mRetorno := .f.
   Endif
   
   cText := NIL
   
   Return mRetorno
Forte abraço...