elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Security Series.XSS. [Cross Site Scripting]


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación General
| | |-+  .NET (C#, VB.NET, ASP)
| | | |-+  Programación Visual Basic (Moderadores: LeandroA, seba123neo)
| | | | |-+  leer indice del archivo txt
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: leer indice del archivo txt  (Leído 3,155 veces)
corlo

Desconectado Desconectado

Mensajes: 98


Ver Perfil
leer indice del archivo txt
« en: 17 Junio 2020, 12:49 pm »

Hola soy corlo
estoy haciendo un codigo para leer el final del archivo del indice o sea text6.text
text6.text=contador
text1.text=azar
text2.text=azar1
text3.text=azar2
text3.text=azar3
text4.text=azar4

a la hora de grabar la informacion me lo hace bien, pero cuando cierro el programa y lo ejecuto
otra vez me dice el siguiente error en el form load

Error '62' en tiempo de ejecucion:
la entrada de datos se ha sobrepasado el final del archivo
en la linea:
Input #1, azar, azar1, azar2, azar3, azar4


y lo que yo quiero es leer la variable contador al final del archivo


Código:



Dim contador As Integer
Dim azar As Integer
Dim azar1 As Integer
Dim azar2 As Integer
Dim azar3 As Integer
Dim azar4 As Integer

Private Sub Command1_Click()
'Nuevo
Text6.Text = contador + 1
contador = contador + 1
Text1.Text = ""
Text2.Text = ""
Text3.Text = ""
Text4.Text = ""
Text5.Text = ""


End Sub

Private Sub Command2_Click()

'Guardar

    Open App.Path & "\azar" & ".txt" For Append As #1
    Print #1, Text6.Text & vbCrLf
    Print #1, Text1.Text, Text2.Text, Text3.Text, Text4.Text, Text5.Text & vbCrLf
    Close #1


End Sub

Private Sub Command4_Click()
End
End Sub

Private Sub Command5_Click()
' Calcular

Randomize
azar = Int(Rnd * 45) + 1
Text1.Text = azar
azar1 = Int(Rnd * 45) + 1
Text2.Text = azar1
azar2 = Int(Rnd * 45) + 1
Text3.Text = azar2
azar3 = Int(Rnd * 45) + 1
Text4.Text = azar3
azar4 = Int(Rnd * 45) + 1
Text5.Text = azar4
End Sub

Private Sub Form_Load()
If contador = 0 Then
Open App.Path & "\azar" & ".txt" For Append As #1
Close #1
End If
If contador = 0 Then contador = 1
Open App.Path & "\azar" & ".txt" For Input As #1
     While Not EOF(1)
     Input #1, contador
     Input #1, azar, azar1, azar2, azar3, azar4

en el segunda lectura me pone el siguiente error:
Error '62' en tiempo de ejecucion:
la entrada de datos se ha sobrepasado el final del archivo


     Wend
      Close #1
Text6.Text = contador
End Sub








Gracias


En línea

MCKSys Argentina
Moderador Global
***
Desconectado Desconectado

Mensajes: 5.471


Diviértete crackeando, que para eso estamos!


Ver Perfil
Re: leer indice del archivo txt
« Respuesta #1 en: 17 Junio 2020, 18:47 pm »

Hola!

Si tu archivo tiene el formato parecido al de un archivo INI:

Código:
variable1=valor1
variable2=valor2
variable3=valor3

Puedes hacer la conversión al mismo:

Código:
[INFO]
variable1=valor1
variable2=valor2
variable3=valor3

Y luego usar las APIs de Windows GetPrivateProfileString y WritePrivateProfileString para leer los valores de las variables.

Busca sobre dichas APIs en la red (te dejo los declare por las dudas).

Código
  1. Public Declare Function GetPrivateProfileString Lib "KERNEL32" Alias "GetPrivateProfileStringA" (ByVal lpApplicationName As String, ByVal lpKeyName As Any, ByVal lpDefault As String, ByVal lpReturnedString As String, ByVal nSize As Long, ByVal lpFileName As String) As Long
  2. Public Declare Function WritePrivateProfileString Lib "KERNEL32" Alias "WritePrivateProfileStringA" (ByVal lpApplicationName As String, ByVal lpKeyName As Any, ByVal lpString As Any, ByVal lpFileName As String) As Long
  3.  



Por otro lado, si quieres implementar tu propio codigo, te recomiendo leer linea x linea en una matriz y luego porcesar la misma; o bien, procesar al leer.

Saludos!


En línea

MCKSys Argentina

"Si piensas que algo está bien sólo porque todo el mundo lo cree, no estás pensando."

corlo

Desconectado Desconectado

Mensajes: 98


Ver Perfil
Re: leer indice del archivo txt
« Respuesta #2 en: 17 Junio 2020, 22:27 pm »

hola

gracias MCKSys Argentina por contestar
pero lo que yo necesito es trabajar con archivos secuenciales


Error '62' en tiempo de ejecucion:
la entrada de datos se ha sobrepasado el final del archivo
en la linea:
Input #1, azar, azar1, azar2, azar3, azar4


y lo que yo quiero es leer la variable contador al final del archivo
del formload



gracias
En línea

MCKSys Argentina
Moderador Global
***
Desconectado Desconectado

Mensajes: 5.471


Diviértete crackeando, que para eso estamos!


Ver Perfil
Re: leer indice del archivo txt
« Respuesta #3 en: 17 Junio 2020, 23:21 pm »

pero lo que yo necesito es trabajar con archivos secuenciales

y lo que yo quiero es leer la variable contador al final del archivo
del formload

OK, entonces necesitas ver que hay en el archivo antes de hacer el input, ya que es evidente que no hay data suficiente para llenar las variables.

Por ello te escribí:
Por otro lado, si quieres implementar tu propio codigo, te recomiendo leer linea x linea en una matriz y luego porcesar la misma; o bien, procesar al leer.

En tu caso puedes hacer un line input de esa segunda linea y parsear de acuerdo a los valores que encuentres.

Saludos!
En línea

MCKSys Argentina

"Si piensas que algo está bien sólo porque todo el mundo lo cree, no estás pensando."

corlo

Desconectado Desconectado

Mensajes: 98


Ver Perfil
Re: leer indice del archivo txt
« Respuesta #4 en: 18 Junio 2020, 00:22 am »

gracias por responder MCKSys Argentina

he probado con line input y me dice el siguiente error
 no coinciden los tipos en la variable azar
me podrias poner un pequeño ejemplo sobre lo que dices
gracias
En línea

Serapis
Colaborador
***
Desconectado Desconectado

Mensajes: 3.355


Ver Perfil
Re: leer indice del archivo txt
« Respuesta #5 en: 18 Junio 2020, 17:21 pm »

En primer lugar el código, siempre que sea posible y haya en el listado de etiquetas Geshi, el lenguaje para el mismo, procede colocarlo dentro de tales etiquetas... para que resulte cómodo leer y mantenga al menos el formato de la indentación.
O manualmente... (quitando los espacios se convierte en las etiquetas BBcode)
[ code = vb ] tu código aquí [ / code ]

Line input, lee una linea entera es decir hasta que encuentre un salto d elínea, sea la cantidad de bytes que sea. Por lo que solo resulta indicado en ciertas situaciones:
- Se pretende leer texto, por tanto leer cada vez una línes es adecuado, porque a priori, nos e conoce el tamaño de cada línea.
- Los datos están fuertemente formateados. En tal caso, el usuario se supone conocer correctamente la estructura y la forma de 'desguazar' (parse), dicha línea en las variables que proceda.
- Cualquier otra situación, pero solo cuando hay un único dato en cada línea (que no requiere un parsingm ás allá de la asignación).

Luego, Line input, lee 'string', cadenas de texto... de ahí el error que te arroja, puesto que tu (seguramente) intentas volcarlo en un tipo integer.

Antes de eso, con input es más procedente cuando se conoce muy bien el formato que compone el fichero y éste tiene (o puede tener) distintos tipos...
Así algo como:
Código
  1. Dim numVertices as byte
  2. Dim Vertices() as single
  3. dim canal as integer
  4. dim Ruta as string
  5.  
  6.    ' Abrir el fichero...
  7.    ruta = "tu ruta al fichero deseado..."
  8.    canal = Freefile
  9.    open ruta for input as #canal
  10.  
  11.    ' leer datos
  12.    input #canal,,numVertices
  13.    if (numVertices >0)
  14.        redim vertices(0 to numVertices-1)
  15.         input #canal,, vertices
  16.    else
  17.        '... algún mensaje de error si procede...
  18.    end if
  19.  
  20.   close #canal
  21.  
   
Que viene a decir... primero se lee la cantidad de vertices que es un byte (es decir un valor entre 1 y 255) y la siguiente lectura leerá, tantos valores de tipo single como indique...
Esto es porque hay un formato reconocido para el fichero que se conoce, y por tanto se aplicó al escribir y eél mismo es adecuado para leer.

No puedes escribir 10 bytes y luego pretender leer 12.
Las variables Azar, Azar1... y 'contador' están declarados como 'integer', luego por cada uno se leen 2 bytes.
EOF, detectará correctamente el final del fichero, siempre que una lectura cumpla una de estas dos condiciones:
A - se lee 1 único byte cada vez en el bucle.
B - Se leen los bytes que sean, pero congruentes al tamaño. Esto es, si se guardaron 60 bytes, puedo leer en cada ciclo, 2, o en cada ciclo 3, o en cada ciclo, 4 o en cada ciclo, 5, 10, 12, 15, 20, 30, 60... porque todos ellos son submúltiplos de 60
Si el fichero tiene 60 bytes y en cada ciclo se leen 7 bytes, al llegar al 8º ciclo, he leído 56 bytes (7*8), luego en el siguiente ciclo, al intentar leer 7 bytes, puésto que solo restan 60-56 = 4, saltará el error...

En el caso 'A', solo interesa cuando se sepa que es precisamente así como se quiere leer byte a byte, porque el tipo de datos de destino son bytes, o bien cuando es uno mismo quien procederá a componer el tipo que proceda. Ahora leer byte a byte es lento.
En el caso 'B', interesa cuando uno tiene que leer datos de forma más o menos compleja, aunque si hay un 'patrón' sería mejor crear una estrcutura (type), y leer con una sola variable todo el contenido d ela estructura, es decir 'record a record'...

Cierto problema con 'input' es que es 'exigente, es decir requiere que la lista de variables leída estén en el mismo orden y sean del mismo tipo que se escribieron, es decir si fueras a leer un entero donde se escribió una cadena, el entero devolvería 0.

Es más conveniente, para evitar ciertas complejidades para quienes no se leen nada de documentación leer y escribir en 'binary' mode... ya que lee y escribe bytes al tipo que lee, no guarda ninguna info del tipo que se guarda, luego es perfectamente sencillo guardar un tipo long (4 bytes) y luego leerlo como bytes, como integer como byte e integer, como long, incluso como cadena.

Código
  1. '....
  2.    dim k as long, j as integer, i as byte, b as boolean, s as string, ib() as byte  
  3.  
  4.    ' Escribimos un valor de tipo long = 4 bytes.
  5.    Open ruta for binary as #canal
  6.    k = 1145323841
  7.    put #canal,,k
  8.    debug.print "Escrito el tipo long con valor: " & cstr(k)
  9.    close #canal
  10.  
  11.    ' Leemos un tipo long = 4 bytes.
  12.    k= 0
  13.    canal = freefile
  14.    open ruta for binary as #canal
  15.    get #canal,, k
  16.    debug.print "Leido el tipo long con valor: " & cstr(k)
  17.    close #canal
  18.    debug.print
  19.  
  20.    ' Leemos un tipo integer 2 veces (2+2)=4 bytes.
  21.    canal = freefile
  22.    open ruta for binary as #canal
  23.    get #canal,, j
  24.    debug.print "Leido el tipo integer con valor: " & cstr(j)
  25.    get #canal,, j
  26.    debug.print "Leido otrol tipo integer con valor: " & cstr(j)
  27.    close #canal
  28.    debug.print
  29.  
  30.    ' Leemos un tipo integer y byte 2 veces (2+1+1)=4 bytes.
  31.    canal = freefile
  32.    open ruta for binary as #canal
  33.    get #canal,, j
  34.    debug.print "Leido el tipo integer con valor: " & cstr(j)
  35.    get #canal,, i
  36.    debug.print "Leido el tipo byte con valor: " & cstr(i)
  37.    get #canal,, i
  38.    debug.print "Leido otro tipo byte con valor: " & cstr(i)
  39.    close #canal
  40.    debug.print
  41.  
  42.    ' Leemos un tipo integer y byte 2 veces (2+1+1)=4 bytes.
  43.    canal = freefile
  44.    open ruta for binary as #canal
  45.    get #canal,, j
  46.    debug.print "Leido el tipo integer con valor: " & cstr(j)
  47.    get #canal,, i
  48.    debug.print "Leido el tipo byte con valor: " & cstr(i)
  49.    get #canal,, i
  50.    debug.print "Leido otro tipo byte con valor: " & cstr(i)
  51.    close #canal  
  52.    debug.print
  53.  
  54.    ' Leemos un tipo integer y boolean (2+2)=4 bytes.
  55.    canal = freefile
  56.    open ruta for binary as #canal
  57.    get #canal,, j
  58.    debug.print "Leido el tipo integer con valor: " & cstr(j)
  59.    get #canal,, b
  60.    debug.print "Leido el tipo boolean con valor: " & cstr(b)
  61.    close #canal
  62.    debug.print
  63.  
  64.    ' Leemos los mismos, al revés tipo boolean e integer (2+2)=4 bytes.
  65.    canal = freefile
  66.    open ruta for binary as #canal
  67.    get #canal,, b
  68.    debug.print "Leido el tipo boolean con valor: " & cstr(b)
  69.    get #canal,, j
  70.    debug.print "Leido el tipo integer con valor: " & cstr(j)
  71.    close #canal
  72.    debug.print
  73.  
  74.    ' Leemos un tipo byte a byte, 4 veces (1+1+1+1)=4 bytes.
  75.    canal = freefile
  76.    open ruta for binary as #canal
  77.    get #canal,, i
  78.    debug.print "Leido el tipo byte con valor: " & cstr(i)
  79.    get #canal,, i
  80.    debug.print "Leido otro byte con valor: " & cstr(i)
  81.    get #canal,, i
  82.    debug.print "Leido otro byte con valor: " & cstr(i)
  83.    get #canal,, i
  84.    debug.print "Leido otro byte con valor: " & cstr(i)
  85.    close #canal
  86.    debug.print
  87.  
  88.    ' Leemos un tipo byte y 3 más en un array (1+1+1+1)=4 bytes.
  89.    canal = freefile
  90.    open ruta for binary as #canal
  91.    get #canal,, i
  92.    debug.print "Leido el tipo byte con valor: " & cstr(i)
  93.    redim ib(0 to 2) ' dimensionar el array a un tamaño igual o menor a lo que reste en el fichero.
  94.    get #canal,, ib
  95.    debug.print "Leido un array de 3 bytes con valores: ",  cstr(ib(0)),  cstr(ib(1)),  cstr(ib(2))
  96.    close #canal
  97.    debug.print
  98.  
  99.    ' Leemos un tipo string de 3 caracteres (1+1+1+1)=4 bytes.
  100.    canal = freefile
  101.    open ruta for binary as #canal
  102.    s= space$(4)  ' dimensionar el string... si no es un string nulo ""
  103.    get #canal,, i
  104.    debug.print "Leido el tipo byte con valor: " & cstr(i)
  105.    redim ib(0 to 2)
  106.    get #canal,, ib
  107.    debug.print "Leido un array de 3 bytes con valores: ",  cstr(ib(0)),  cstr(ib(1)),  cstr(ib(2))
  108.    close #canal
  109.    debug.print
  110.  
Nota que cada vez hemos abierto y cerrado el fichero... no es estrictamente necesario, bastaría con reposicionar el curso de lectura al comienzo:

el acceso aleatorio a un fichero en modo binario, es reposicionando el cursor donde convenga
Código
  1.    Seek(canal), 1  ' reposiciona el curso al comienzo del fichero.
  2.  
  3.   Seek(canal),( lof(canal) -20) ' reposiciona el curso al final del fichero, -20 bytes, dará error si esa posición sale negativa (el fichero tiene menos de 20 bytes)
  4.  


También se puede preguntar por la posición actual... por ejemplo para guardarla, leer datos y volver a ese mismo punto por segunda vez.
Código
  1.    k = Seek(canal)
  2.  

Es posible tener más de un cursor apuntando al mismo fichero... uno podría estar leyendo de una cabecera de datos, mientras el otro canal apunta a los datos que el registor leído en la cebecera indicare (probablemente previo cálculo)
Código
  1.   canal1 = freefile
  2.   open ruta for binary as #canal1
  3.   canal2 = freefile
  4.   open ruta for binary as #canal2
  5.  

Nota también que es preferible usar la sentencia 'freefile' para obtener un canal libre, que usar una constante directamente... cuando peres con proyectos de cierta complejidad, no puedes tener control de 'números', Freefile devuelve siempre un canal no usado que se asigna a una variable, que identifica únivocamente al fichero concreto... si además la variable tiene un nombre más específico, mejor: canalPrecios (por ejemplo, para un fichero cuyo contenido son precios), canalClientes (por ejemplo para un fichero cuyo contenido son registros con los datos de clientes)

Nota que en modo binario, se lee un solo dato (variable) cada vez... input, permite leer una lista, es parte de lo que determina si usar un modo u otro, pero es muy dependiente del modo en que se escribió.

... en cualquier caso, acude a la documentación de VB6, que es muy completa, lleva el cursor al keyword del lenguaje de tu interés y pulsa 'F1', la ayuda aparece siempre pulsando la tecla de función: 'F1', pero si está encima de un keyword, busca el mismo... y la propia documentación suele contener ejemplos.

Hay que practicar, pero lo correcto es aprender documentándose. Practicar sin documentación, supone emplear 20 veces más de tiempo para aprender, algo que leyendo unos párrafos, se aprende en 15 minutos y se practca en 1 hora... con solo práctica puedes dedicarle días, y todavía surgirán errores y dudas que uno no termina de comprender y es seguro, que quedarán lagunas...(detalles que jamás se llega a conocer).
« Última modificación: 18 Junio 2020, 17:36 pm por NEBIRE » En línea

corlo

Desconectado Desconectado

Mensajes: 98


Ver Perfil
Re: leer indice del archivo txt
« Respuesta #6 en: 18 Junio 2020, 23:20 pm »

hola nebire gracias por contestar

al final lo he conseguido


dejo el codigo por si alguien le interesa

Código:


Private Sub Command1_Click()
Open App.Path & "\Base1.txt" For Input As #1
Do While Not EOF(1)
  Input #1, identificacion, azar, azar1, azar2, azar3, azar4
 
Loop
Close #1

Text1 = identificacion + 1
identificacion = identificacion + 1
Text2 = Empty
Text3 = Empty
Text4 = Empty
Text5 = Empty
Text6 = Empty
End Sub

Private Sub Command2_Click()
Open App.Path & "\Base1.txt" For Append As #1
Write #1, Text1, Text2, Text3, Text4, Text5, Text6
Close #1

End Sub

Private Sub Command3_Click()
Open App.Path & "\Base1.txt" For Input As #1
Do While Not EOF(1)
  Input #1, identificacion, azar, azar1, azar2, azar3, azar4
   If Text1 = identificacion Then

  Text2 = azar
  Text3 = azar1
  Text4 = azar2
  Text5 = azar3
  Text6 = azar4
  End If
Loop
Close #1
End Sub

Private Sub Command4_Click()
End
End Sub

Private Sub Command5_Click()

Randomize
azar = Int(Rnd * 45) + 1
Text2 = azar
azar1 = Int(Rnd * 45) + 1
Text3 = azar1
azar2 = Int(Rnd * 45) + 1
Text4 = azar2
azar3 = Int(Rnd * 45) + 1
Text5 = azar3
azar4 = Int(Rnd * 45) + 1
Text6 = azar4
End Sub

Private Sub Form_Load()
If identificacion = 0 Then
Open App.Path & "\Base1.txt" For Append As #1
Close #1
End If
If identificacion = 0 Then identificacion = 0
Open App.Path & "\Base1.txt" For Input As #1
Do While Not EOF(1)
  Input #1, identificacion, azar, azar1, azar2, azar3, azar4
 
Loop
Text1 = identificacion + 1
Close #1





End Sub









gracias
En línea

Serapis
Colaborador
***
Desconectado Desconectado

Mensajes: 3.355


Ver Perfil
Re: leer indice del archivo txt
« Respuesta #7 en: 19 Junio 2020, 01:21 am »


Código
  1. Private Sub Command3_Click()
  2.    Open App.Path & "\Base1.txt" For Input As #1
  3.    Do While Not EOF(1)
  4.        Input #1, identificacion, azar, azar1, azar2, azar3, azar4
  5.        If Text1 = identificacion Then
  6.            Text2 = azar
  7.            Text3 = azar1
  8.            Text4 = azar2
  9.            Text5 = azar3
  10.            Text6 = azar4
  11.        End If
  12.    Loop
  13.    Close #1
  14. End Sub
  15.  
Esto es muy ineficiente...
Estás leyendo secuencialmente un fichero para localizar un valor...
Cuando es posible, es más óptimo el acceso aleatorio a la posición deseada del fichero.

Si el valor está ordenado, y por tanto 'identificación' es el enésimo registro, puedes calcular la posición y saltar directamente a ella.
Viendo que 'identificador' aumenta 1 a 1, es deducible que el contenido en el fichero está ordenado...

Si no está ordenado, todavía puedes ir saltando... y leer en cada ciclo, solo 'identificación' hasta que lo encuentras, y acto seguido lees lo que se precisa.




Código
  1. Private Sub Form_Load()
  2.    ' 1
  3.    If identificacion = 0 Then
  4.        Open App.Path & "\Base1.txt" For Append As #1
  5.        Close #1
  6.    End If
  7.  
  8.    ' 2
  9.    If identificacion = 0 Then identificacion = 0
  10.  
  11.    Open App.Path & "\Base1.txt" For Input As #1
  12.    Do While Not EOF(1)
  13.        Input #1, identificacion, azar, azar1, azar2, azar3, azar4
  14.    Loop
  15.  
  16.    ' 3
  17.    Text1 = identificacion + 1
  18.    Close #1
  19. End Sub
  20.  

1 - Abrir, para luego cerrar, qué sentido tiene????.
2 - Esa línea es redundante... sobra.
3 - Nuevamente es muy ineficiente... estás accediendo al último registro.... calcula: del tamaño del fichero, resta el tamaño de 1 regsto, posicionas el cursor ahí.. Basta leer solo el último registro.
En ficheros pequeños la ineficiencia no se aprecia, cuando operes con ficheros de muchos Mb... (pongamos 1Gb.... se hará intolerable la espera).


Y por favor, ya llevas tiempo en el foro, acostumbra a usar la etiquetas del 'código GESHI', ...las encuentras cuando editas el mensaje entre las opciones de edición de dicha ventana...
En línea

corlo

Desconectado Desconectado

Mensajes: 98


Ver Perfil
Re: leer indice del archivo txt
« Respuesta #8 en: 19 Junio 2020, 12:50 pm »

hola nebire

ya lo se que se puede mejorar la estructua del programa , pero por lo que
necesito yo de momento ya vale , pero si lo quieres mejorar , lo puedes mejorar.

trabajo con archivos secuenciales por  poca informacion

gracias por responder
En línea

Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
leer un archivo txt « 1 2 3 »
Programación Visual Basic
RED_HORSE 22 8,219 Último mensaje 14 Abril 2006, 22:06 pm
por RED_HORSE
Leer archivo .civ « 1 2 »
Programación Visual Basic
Tyrz 13 5,002 Último mensaje 9 Septiembre 2007, 12:54 pm
por Tyrz
leer archivo con api's « 1 2 »
Programación Visual Basic
krackwar 12 4,500 Último mensaje 14 Julio 2008, 17:00 pm
por krackwar
Leer archivo xml....
.NET (C#, VB.NET, ASP)
Zeroql 7 6,314 Último mensaje 3 Julio 2010, 00:16 am
por Zeroql
Abrir archivo, leer datos y modificarlos en otro archivo.
Java
Tonyskater 6 5,884 Último mensaje 24 Mayo 2017, 20:25 pm
por Tonyskater
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines