concatenacion de string y se queda pillado

Iniciado por lessionone, 13 Abril 2012, 10:57 AM

0 Miembros y 2 Visitantes están viendo este tema.

lessionone

Hola buenas, tengo un trozo de codigo fuente que se me queda pillado en el visual studio, al parecer el procesador se pone a trabajar a tope y nada.(es un core 2 duo p8600 y 4 gb de memoria)

Private Function encriptararchivo(ByVal archivooriginal As String) As String
       Dim c As String = ""
       Dim z As String = ""
       Dim y As Integer=0
       For b = 1 To Len(archivooriginal)
           c = Mid(archivooriginal, b, 1)
           y = Asc(c)
           z = z & y & "tallin"
       Next
       Return z

me he inclinado por escribir en el subforo de criptografia ya que vosotros entendeis perfectamente algoritmos rc4, xor y estos funcionan a la perfeccion a la hora de ejecutarlos en un ordenador sin necesitad de un gran procesador ni memoria.
He de decir que la variable archivooriginal es un archivo leido en binario y por eso lo paso a ascci, y que el numero de veces que debe de pasar por el bucle es de 697373.
Si yo le pongo 100000 lo realiza pero le cuesta aunque sin duda lo que mas le cuesta es ir concatenando en la variable z ya que si quito esta concatenacion pues hace el bucle y todas las instrucciones muy rapidas.
¿En rc4 no concatena el texto del archivo que le pasa? si es asi como que con rc4 no se queda pillado y con esto que es una tonteria si?
¿como podria hacerlo sin usar concatenacion?
Si creeis que esto pertenece mas a programacion decirmelo y lo muevo.
Gracias.

Yoghurt

#1
Amigo creo que aun no conoces las Arrays, cuando concatenas las variables en Visual Basic pasa justamente eso, el computador se vuelve lento y más si le pasas archivos pesados. Intenta Aprendiendo que son los Arrays y como funcionan, luego sustituye la concatenación con un array.

(te sugiero deshacerte de "tallin" no sirve!!)

primero hay que inicializar la array para reservarle memoria, en este caso será la longitud del archivo.

Dim z[] As String 'crea un array de String
ReDim z[0 to (len(archivooriginal))


luego sustituye la concatenación por:
z[b] = y & "tallin"

y para pasarlo de Array a String usa:
archivofinal = join(z, "")

O pasalo directamente a un archivo en el disco duro:
Open "archivo final" for Binary Access Write Lock Write As #2
put #2, 0, z
Close #2


Y no olvides de liberar la memoria de z: ReDim z[0]

Notaste que la concatenacion al igual que el array pesa 6 veces más por ese estupido TALLIN!!??? Espero hayas aprendido que la memoria es inversamente proporcional a la velocidad (en la informatica).

Yoghurt

En RC4 y otros algoritmos de codificación lo que hacen para que al contrario de ti no se queden sin memoria, es no ocupar el puto "tallin"! (perdón pero me saca dequicio)  :D jajajajaja...

Bueno, lo que hacen ellos es dividir el texto a cifrar en pedazos más pequeños para de esta forma ocupar menos espacio en memoria y ser más eficientes puesto que consigen más velocidad haciendo eso.

Con tu algoritmo pasa lo siguiente: Codificas un archivo en el disco de 3MB por ejemplo, pero para codificarlo lo tubiste que poner en una variable (archivooriginal) que pesa lo mismo que el archivo en disco 3MB, luego lo pasas ya cifrado a la variable z que ocupará 3MB más, pero como le pones "tallin" a cada caracter pesa 6 veces más por lo que z pesa en realidad 21MB, entonces tienes:

archivooriginal = 3MB
z = 21MB
Resultado = 24MB ocupados por tu programa en RAM

Increible verdad. Bueno te recomiendo leer solo pedazos directamente del archivo en disco utilizando una variable String como buffer que lea solo X caracteres (X es un numero dependiendo de tus necesidades Ej: 24) y los codifique y luego los ponga directamente en un archivo en el disco... Asi solo ocupas 24bits + (24bits * 6bits) = 168bits!  Claro, como el Disco Duro es mas lento que la RAM se demora un poco más pero es solo un poco más.

79137913

HOLA!!!

No le hagas caso a AbrahamAraon, el desentiende este lenguaje parece , te esta explicando poniendo corchetes en vez de parentesis, eso denota una total ignorancia de la sintaxis del lenguaje.

Siguiendo:

El problema esta en estas lineas:
Código (vb) [Seleccionar]
Dim c As String = ""
       Dim z As String = ""
       Dim y As Integer=0

Por que al declarar esas variables no se les puede dar un valor. (aunque todas de inicializan con el valor que igualas ahi)
Tenes que poner asi para que funcione:
Código (vb) [Seleccionar]
Dim c As String
       Dim z As String
       Dim y As Integer
       c = ""
       z = ""
       y = 0

Como veras ahi separo la declaracion de la asignacion de valor de la variable.

Luego tambien estas mal con esta linea:
Código (vb) [Seleccionar]
Return z
En VB6 no se usa Return, para que la funcion devuelva esa variable que indicas ahi deberias reemplazar esa linea por:
Código (vb) [Seleccionar]
encriptararchivo = z

Por ultimo nunca cerras la funcion.
Deberias agregar un End Function al final.

El codigo te quedaria asi:
Código (vb) [Seleccionar]
Private Function encriptararchivo(ByVal archivooriginal As String) As String
       Dim c As String
       Dim z As String
       Dim y As Integer
       c = ""
       z = ""
       y = 0
       For b = 1 To Len(archivooriginal)
           c = Mid(archivooriginal, b, 1)
           y = Asc(c)
           z = z & y & "tallin"
       Next
       encriptararchivo = z
End Function


P.D: @lessionone solo arregle tus problemas con la sintaxis no cambie el funcionamiento de tu funcion.
P.D2: @AbrahamAraon Si respondes por favor responde bien o aunque sea en el lenguaje del subforo correspondiente, No hagas doble post, modifica el ultimo post y agrega lo que tengas que agregar, arriba ya te dije que no se usan corchetes en vb6, se usan parentesis.

GRACIAS POR LEER!!!
"Como no se puede igualar a Dios, ya he decidido que hacer, ¡SUPERARLO!"
"La peor de las ignorancias es no saber corregirlas"

79137913                          *Shadow Scouts Team*

seba123neo

por el codigo que pone lessionone, parece que esta programando en visual basic .net

igual es verdad, la concatenacion de strings en visual basic es super lenta en bucles de miles, hay un post que hice con una clase que usa CopyMemory que puede llegar a concatenar millones de strings en muy poco tiempo. el equivalente de esto en .NET es la clase StringBuilder.
La característica extraordinaria de las leyes de la física es que se aplican en todos lados, sea que tú elijas o no creer en ellas. Lo bueno de las ciencias es que siempre tienen la verdad, quieras creerla o no.

Neil deGrasse Tyson

Yoghurt

Lo siento por el descuido, aprate de los corchetes (esq se me cruzan los lenguajes) no noté otros errores en el código de lessionone, espero le ayude de todas formas ;)

BlackZeroX

#6
[quote author=lessionone link=topic=359048.msg1737017#msg1737017 date=1334307451]
...
[code]
Private Function encriptararchivo(ByVal archivooriginal As String) As String
        Dim c As String = ""
        Dim z As String = ""
        Dim y As Integer=0
        For b = 1 To Len(archivooriginal)
            c = Mid(archivooriginal, b, 1)
            y = Asc(c)
            z = z & y & "tallin"
        Next
        Return z

...
[/quote]

para ese algoritmo sencillo se puede calcular facilmente el buffer que utilizara.

bufferSize = (SizeOfFile * lenWord) + (SizeOfFile / NumberOfChars)
es decir:
bufferSize = (len(archivooriginal) * len("tallin")) + (len(archivooriginal) / 1)

Aun que a mi sinceramente no me agrada usar los strings para trabajar con archivos...

Código (vbnet) [Seleccionar]


...
        z = space((len(archivooriginal) * len("tallin")) + (len(archivooriginal) / 1))

        For b = 1 To Len(archivooriginal)
            mid(z, c, 1) = mid(archivooriginal, i, 1) // no recuerdo si en .Net puedo seguir usando el mid() del lado izuierdo del igual...
            mid(z, c + 1, len("tallin")) = "tallin"
            c = c + 1 + len("tallin")
        Next

        Return z
...


Me tendré que instalar otra vez el vb6...

Dulces Lunas!¡.[/code]
The Dark Shadow is my passion.

BlackZeroX

#7
Asi es como yo lo haria... los algoritmos funcionan tan rapido que procesa un archivo de 17 megabytes en unos segundos... con un archivo de salida de casi 190 megabytes...

Código (vb) [Seleccionar]


Option Explicit

Private Declare Sub RtlMoveMemory Lib "kernel32" (ByVal pDst As Long, ByVal pSrc As Long, ByVal ByteLen As Long)

Private Sub Form_Load()
Dim ff          As Long
Dim mapFile()   As Byte

   ff = FreeFile
   Open "c:\hola.txt" For Binary As ff
       If Not EOF(ff) Then
           ReDim mapFile(0 To LOF(ff) - 1)
           Seek ff, 1  '  nos posicionamos al inicio del archivo
           Get ff, , mapFile
'                Debug.Print StrConv(mapFile, vbUnicode)
           Seek ff, 1  '  nos posicionamos al inicio del archivo
               mapFile = fisuras(mapFile, StrConv("BlackZeroX", vbFromUnicode))
'                Debug.Print StrConv(mapFile, vbUnicode)
           Put ff, , mapFile
       End If
   Close ff
End Sub


Private Function fisuras(ByRef arr() As Byte, ByRef words() As Byte) As Byte()
Dim size    As Long
Dim newSize As Long
Dim sizeW   As Long
Dim ret()   As Byte
Dim i       As Long, j  As Long ', k  As Long
   
   size = (UBound(arr) + 1)
   sizeW = (UBound(words) + 1)
   newSize = (size * sizeW + size / 1)
   
   ReDim ret(0 To (newSize - 1))
   
   For i = 0 To (size - 1)
       ret(j) = arr(i): j = (j + 1)
       RtlMoveMemory VarPtr(ret(j)), VarPtr(words(0)), sizeW   '   For k = 0 To (sizeW - 1): ret(j + k) = words(k): Next
       j = (j + sizeW)
   Next
   
   fisuras = ret
   
End Function



o tambien asi:

Código (vb) [Seleccionar]


Option Explicit

Private Sub Form_Load()
Dim ff          As Long
Dim mapFile()   As Byte

   ff = FreeFile
   Open "c:\hola.txt" For Binary As ff
       If Not EOF(ff) Then
           ReDim mapFile(0 To LOF(ff) - 1)
           Seek ff, 1  '  nos posicionamos al inicio del archivo
           Get ff, , mapFile
'                Debug.Print StrConv(mapFile, vbUnicode)
           Seek ff, 1  '  nos posicionamos al inicio del archivo
               mapFile = fisuras(mapFile)
'                Debug.Print StrConv(mapFile, vbUnicode)
           Put ff, , mapFile
       End If
   Close ff
End Sub


Private Function fisuras(ByRef arr() As Byte, Optional ByRef text As String = "BlackZeroX") As Byte()
Dim size    As Long
Dim newSize As Long
Dim lenText As Long
Dim ret()   As Byte
Dim i       As Long, j  As Long, k  As Long
   
   size = (UBound(arr) + 1)
   lenText = Len(text)
   newSize = (size * lenText + size / 1)
   
   ReDim ret(0 To (newSize - 1))
   
   For i = 0 To (size - 1)
       ret(j) = arr(i)
       For k = 1 To lenText
           ret(j + k) = Asc(Mid(text, k, 1))
       Next
       j = (j + 1 + lenText)
   Next
   
   fisuras= ret
   
End Function



Dulces Lunas!¡.
The Dark Shadow is my passion.

BlackZeroX

#8
Cita de: AbrahamAraon en 11 Julio 2012, 10:49 AM

Y no olvides de liberar la memoria de z: ReDim z[0]


para liberar se usa erase...

erase z

Aun que si las variables estan declaradas en un proceso estas son automáticas y la llamada a erase se obvia... caso omiso cuando pides memoria...

OJO Mientras mas grande sea el buffer te quedaras sin memoria... tambien ten en consideracion que si lees trozos desde tu HD como dice @AbrahamAraon solo es en cuestión a que sea un archivo PESADO (DEFINICIÓN mas de 100 megas e inclusive hasta 4 Gigas o mas...), mientras no sean archivos super pesados, es mejor CARGAR TODO el archivo en memoria y crear memoria que actué como buffer de esta manera se evita estar leyendo el archivo constantemente y evitamos la latencia que esta representa a su vez aumentamos la velocidad de procesamiento...

* No uses String para leer archivos si es que los vas a procesar,
* Usa array de bytes par procesar archivos un caracter de una string es equivalente a 2 bytes... y en si aun que tu veas 10 caracteres pesaras que pesa en memoria 10 bytes pero la realidad es que pesa 20 bytes...

Dulces Lunas!¡.
The Dark Shadow is my passion.

Yoghurt

Me ha pasado casos en los que me da error al usar ERASE por lo que uso ReDim para las array, a nadie más le ha dado error?. Y... si que se esfuerzan en el código ustedes cosa que yo no hago en el foro, pero tengan fé de que lo haré ;)  Solo que no se formen una idea equivocada pues siempre busco la manera más eficiente para mi codigo. y BlackZeroX (Astaroth) difiero de ti en lo del Disco Duro, tal vez tengas una Computadora Genial, pero no todos tienes grandes recursos, no me digas que no recuerdas al marivilloso Pentium III, yo aun tengo un computador de 700MHz con 64Mb de RAM (antes tenia 128 pero las rams se queman)... Y no le veo la debilidad de usar un buffer de lectura, divide y vencerás!