En este ejemplo vamos a mostrar una manera simple de leer datos desde un fichero de texto e insertarlos en una base de datos mediante PHP.
PHP: ejemplo de lectura desde fichero de texto e inserción en base de datos
Aquí tenéis los ficheros necesarios.
Script de la base de datos
Incluye el script para crear la base de datos. Es muy sencilla, ya que tiene sólo tres campos y no he incluido clave primaria para que podáis probar a insertar los datos más de una vez sin que dé error.
Fichero de texto con los datos a insertar
También incluye el fichero de texto donde están los datos a leer. Como podéis ver, los conjuntos de datos están separados por líneas. Dentro de cada línea, los datos están separados por punto y coma.
1 2 3 4 5 |
FCB;REGAL F.C. BARCELONA;BARCELONA RMA;REAL MADRID;MADRID UNI;UNICAJA;MALAGA UCM;UCAM MURCIA;MURCIA CJL;CAJA LABORAL;VITORIA |
El código en sí consta de dos ficheros, por simplificar. Se podría hacer en uno solo si el formulario hace un autoenvío a sí mismo, pero el código resultante es algo más complejo.
Formulario de subida de fichero
En el primer fichero tenemos un formulario desde el que subimos el fichero de texto y lo enviamos al fichero tramitar_acta.php mediante POST. Los ficheros se deben enviar mediante este método, entre otras cosas, por razones de tamaño.
1 2 3 4 5 6 7 8 9 |
<form action="tramitar_acta.php" method="POST" enctype="multipart/form-data"> <label for="ficheroActa">Fichero con el acta a subir:</label> <input type="file" name="ficheroActa" id="ficheroActa"><br> <input type="submit" value="Enviar acta"> </form> |
La única particularidad de este formulario está en que debemos especificar mediante el atributo enctype que vamos a subir un fichero, dando el valor «multipart/form-data».
En el fichero restante, tramitar_acta.php, es donde está la lógica de programación.
Lógica del programa
Vamos a ver el fichero al completo.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
<?php if ($_FILES["ficheroActa"]["error"] > 0) { echo "Error: " . $_FILES["ficheroActa"]["error"] . "<br>"; } else { echo "Fichero subido correctamente<br>"; echo "Fichero subido: '" . $_FILES["ficheroActa"]["name"] . "'<br>"; // echo "Tamaño: " . ($_FILES["ficheroActa"]["size"] / 1024) . " kB<br>"; // echo "Almacenado en: " . $_FILES["ficheroActa"]["tmp_name"]; // abrimos el fichero con su nombre temporal (el que está en el servidor) // y sólo para lectura $archivo = fopen($_FILES["ficheroActa"]["tmp_name"], "r"); // creamos la conexion a la BD $conexion = new mysqli("localhost", "root", "root", "01_ejercicio_ficheros"); // como vamos a hacer una transaccion, eliminamos el autocommit $conexion->autocommit(false); // creamos una variable booleana que nos controle si ha existido un error en la transacción $errorEnTransaccion = false; // y empezamos la transacción antes de empezar a leer las líneas // mientras haya lineas, las metemos en la variable $lineaActa while( ($linea = fgets($archivo)) !== false ){ // estructura de los datos: codigo_equipo_acb, nombre_equipo, ciudad $arrayDatos = explode(";", $linea); // var_dump($arrayDatos); $codigo_equipo_acb = $arrayDatos[0]; $nombre_equipo = $arrayDatos[1]; $ciudad = $arrayDatos[2]; // ahora inserto los datos en la BD $sql = "INSERT INTO equipos_acb (codigo_equipo_acb, nombre_equipo, ciudad)" . " VALUES ('$codigo_equipo_acb', '$nombre_equipo', '$ciudad');"; // echo $sql; // si hay un error en la operación de inserción, marco la variable // de error como true if (!$conexion->query($sql)){ $errorEnTransaccion = true; } } // fin del while de leer lineas // comprobamos si ha existido error, para hacer la transacción o volver atrás if ($errorEnTransaccion){ $conexion->rollback(); printf("Error durante la operación. No se han actualizado los datos."); } else { $conexion->commit(); printf("Operación de actualización correcta. Se han actualizado los datos."); } // cerramos la conexión con la BD $conexion->close(); // cerrar el fichero fclose($archivo); } ?> |
Primero nos encontramos un if que comprueba en la línea 2 si se ha producido un error al subir el fichero. Para ello hace uso del array asociativo bidimensional que se crea al subir el fichero. Más adelante utilizamos dicho array para acceder a otros datos del fichero.
Información sobre el fichero subido
En caso de que la subida haya sido correcta, informamos mediante dos mensajes. He dejado comentados otros datos que pueden ser interesantes.
1 2 3 4 |
echo "Fichero subido correctamente<br>"; echo "Fichero subido: '" . $_FILES["ficheroActa"]["name"] . "'<br>"; // echo "Tamaño: " . ($_FILES["ficheroActa"]["size"] / 1024) . " kB<br>"; // echo "Almacenado en: " . $_FILES["ficheroActa"]["tmp_name"]; |
Como se puede ver, mediante el acceso a las posiciones del array asociativo bidimensional creado por PHP ($_FILES), se puede acceder a:
- [«name»] -> El nombre del fichero que hemos subido.
- [«size»] -> El tamaño en bytes. Como véis habría que dividir entre 1024 para calcular los kilobytes.
- [«tmp_name»] -> El nombre del fichero en el servidor, es decir, el nombre temporal del mismo, que no coincide con el nombre del fichero original.
- [«type»] -> El tipo de fichero que hemos subido.
- [«error»] -> El código de error que se haya producido durante la subida del mismo (si procede).
Apertura del fichero
Abrimos el fichero mediante el uso de la función fopen(), usando su nombre temporal y pasando el parámetro «r», ya que en este caso sólo vamos a hacer una lectura del mismo.
1 2 3 |
// abrimos el fichero con su nombre temporal (el que está en el servidor) // y sólo para lectura $archivo = fopen($_FILES["ficheroActa"]["tmp_name"], "r"); |
Creación de la conexión a la base de datos
Creamos la conexión a la base de datos. Vamos a utilizar la nomenclatura relativa a objetos.
1 2 |
// creamos la conexion a la BD $conexion = new mysqli("localhost", "root", "root", "01_ejercicio_ficheros"); |
Inicio de la transacción
En este caso vamos a utilizar una transacción. Es decir, o se insertan todos los registros que se han leído, o no se inserta ninguno en caso de que haya un solo error en alguna de las operaciones con cada registro. Esta característica de las transacciones se llama atomicidad.
El ejemplo más claro de esta característica de un sistema de gestión de bases de datos lo tenemos en los cajeros automáticos cuando sacamos dinero. La transacción completa contemplaría al menos los siguientes pasos:
- Se identifica la cuenta desde la que se saca dinero
- Se marca una cantidad a sacar
- Se resta la cantidad de la cuenta
- Se entrega el dinero al usuario
En caso de que alguno de ellos falle, como que no se pueda restar la cantidad de la cuenta o no se pueda entregar el dinero al usuario, la transacción se anula y la base de datos vuelve al estado original. No se entrega el dinero pero tampoco se resta ninguna cantidad de la cuenta.
En nuestro ejemplo indicamos que iniciamos la transacción mediante la función autocommit().
1 2 3 4 5 6 |
// como vamos a hacer una transaccion, eliminamos el autocommit $conexion->autocommit(false); // creamos una variable booleana que nos controle si ha existido un error en la transacción $errorEnTransaccion = false; // y empezamos la transacción antes de empezar a leer las líneas |
Con esta función estamos diciendo al sistema que no ejecute cada instrucción de MySQL por separado y de forma inmediata, sino que sólo lo haga al llamar a la función commit(), como veremos más adelante.
Además creamos una variable booleana para comprobar si ha habido algún error durante las transacciones. La inicializamos a false. En caso de que haya al menos un error quedaría con el valor true.
Bucle de lectura de líneas
Mediante un bucle while() leemos todas las líneas del fichero.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
// mientras haya lineas, las metemos en la variable $linea while( ($linea = fgets($archivo)) !== false ){ // estructura de los datos: codigo_equipo_acb, nombre_equipo, ciudad $arrayDatos = explode(";", $linea); // var_dump($arrayDatos); $codigo_equipo_acb = $arrayDatos[0]; $nombre_equipo = $arrayDatos[1]; $ciudad = $arrayDatos[2]; // ahora inserto los datos en la BD $sql = "INSERT INTO equipos_acb (codigo_equipo_acb, nombre_equipo, ciudad)" . " VALUES ('$codigo_equipo_acb', '$nombre_equipo', '$ciudad');"; // echo $sql; // si hay un error en la operación de inserción, marco la variable // de error como true if (!$conexion->query($sql)){ $errorEnTransaccion = true; } } // fin del while de leer lineas |
Con la función fgets() leemos las líneas de manera independiente. Mientras haya líneas, se guardan en la variable $linea y entramos al while().
Extracción de los datos desde las líneas
Para la extracción de los datos dentro de las líneas, utilizamos la función explode(), a la que le pasamos como parámetro el carácter que hace de separador y la cadena donde están los datos a tratar. El resultado lo metemos en la variable $arrayDatos.
Como podéis ver, me parece muy importante utilizar nombres descriptivos para las variables. Recordemos que los programas deben ser hechos para que lo entiendan otras personas.
1 2 3 4 5 6 |
// estructura de los datos: codigo_equipo_acb, nombre_equipo, ciudad $arrayDatos = explode(";", $linea); // var_dump($arrayDatos); $codigo_equipo_acb = $arrayDatos[0]; $nombre_equipo = $arrayDatos[1]; $ciudad = $arrayDatos[2]; |
La instrucción var_dump() muestra el contenido de la variable que le pasamos en forma legible por humanos. Es muy práctica para comprobar si hemos guardado lo que queremos guardar de forma correcta.
La función explode() mete los campos que encuentra en posiciones consecutivas de un array. Sabiendo el orden de los datos originales metemos los datos en variables con nombres descriptivos por claridad del código, aunque se podrían utilizar directamente.
Inserción de los datos en la base de datos
Ahora creamos una cadena para la sentencia SQL de inserción de datos en la base de datos.
1 2 3 4 5 6 7 8 9 10 |
// ahora inserto los datos en la BD $sql = "INSERT INTO equipos_acb (codigo_equipo_acb, nombre_equipo, ciudad)" . " VALUES ('$codigo_equipo_acb', '$nombre_equipo', '$ciudad');"; // echo $sql; // si hay un error en la operación de inserción, marco la variable // de error como true if (!$conexion->query($sql)){ $errorEnTransaccion = true; } |
Un error muy común es olvidar algunas comillas en la consulta SQL, por lo que es muy recomendable sacarla por pantalla mediante un echo y probarla directamente en la base de datos. Nos ahorraremos mucho tiempo.
En la consulta simplemente le decimos a la base de datos que vamos a insertar en la tabla con nombre equipos_acb y en los campos que le indicamos (y en ese orden) los valores que le pasamos.
En este punto es interesante tener en cuenta que la operación de consulta mediante la función query() se ejecuta al mismo tiempo que comprobamos si devuelve true o false.
Si la operación no ha ido como debiera (porque ya existe un registro con esa clave duplicada, por ejemplo), nos devolvería false, con lo que la variable booleana $errorEnTransaccion quedaría con el valor true hasta el final del programa.
Realizar la transacción o volver atrás en caso de error
Ahora comprobamos si ha existido error en alguna de las operaciones de inserción.
1 2 3 4 5 6 7 8 |
// comprobamos si ha existido error, para hacer la transacción o volver atrás if ($errorEnTransaccion){ $conexion->rollback(); printf("Error durante la operación. No se han actualizado los datos."); } else { $conexion->commit(); printf("Operación de actualización correcta. Se han actualizado los datos."); } |
En caso de que haya habido un error, hacemos un rollback mediante su correspondiente función, con lo que la base de datos vuelve a su estado original y no se inserta ninguno de los datos.
Si no ha habido error en ninguna de las operaciones de inserción individuales, invocamos a la función commit(), que da por válidas todas las operaciones realizadas, con lo que los datos quedan insertados.
En ambos casos mostramos un mensaje por pantalla.
Cierre de conexión a base de datos y fichero
Finalmente cerramos la conexión a la base de datos y el fichero.
1 2 3 4 5 |
// cerramos la conexión con la BD $conexion->close(); // cerrar el fichero fclose($archivo); |
¿Felicitaciones o quejas? ¡Comenta y comparte!
Si te ha gustado o has detectado un error, te agradezco tus comentarios, y puedes compartirlo mediante los enlaces habilitados.
¡Gracias por tu visita!
Hola muy buen trabajo, pero yo tengo una particularidad los datos no estan separados por nada pero son datos fijos cada linea es una registro que tiene esta info fecha hora, registro Nro, dia, mes, hora (HH MM SS), legajo nro.
tipo asi:
«Inicio lectura
1203201808000reg0111031501030001111
1203201808000reg0211031121540001134
Fin Lectura»
cada dia el txt suma informacion no borrando las lecturas anteriores. yo tendria que extraer la info diaria y subirla a mysql.
Tenes idea como podria hacer esto
Gracias
Hola, Nahuel.
Tendrás que sustituir las líneas siguientes:
// estructura de los datos: codigo_equipo_acb, nombre_equipo, ciudad
$arrayDatos = explode(";", $linea);
// var_dump($arrayDatos);
$codigo_equipo_acb = $arrayDatos[0];
$nombre_equipo = $arrayDatos[1];
$ciudad = $arrayDatos[2];
Y usar la función substr() para extraer los distintos campos de la siguiente manera:
$campo1 = substr($linea, $posicion_inicio_1, $longitud_1);
$campo2 = substr($linea, $posicion_inicio_2, $longitud_2);
Respecto a usar siempre el mismo fichero, tendrás que usar un sistema que te permita continuar cada día por el siguiente registro. Para ello tienes distintas opciones dependiendo de si los registros son únicos, consecutivos, incluyen fecha, etc…
Pero de manera general te podría servir el crear una tabla auxiliar con dos campos:
De este modo, al inicio del proceso, puede ir buscando registros hasta que encuentre el último que hemos guardado en dicha tabla y empezar a insertar a partir del siguiente.
Espero que te haya servido de ayuda y gracias por tu comentario.
Hola,
Soy nuevo en programación y necesito realizar la llamada a un formulario que abra un archivo txt e importe los datos un registro por cada uno a una tabla en base de datos. tengo php y mysql
nombre de la base = tarjetas
tabla = numeros
idnum, mumeros
archivo txt = XXXX?
datos del txt ejemplo
1236547963254125
1236547963254126
1236547963254127
1236547963254128
1236547963254129
1236547963254130
gracias
Muchas gracias por dejar tu comentario en mi blog, Daniel. Puedes adaptar el código de ejemplo para que te sirva, las modificaciones que tienes que hacer son pocas. Si te han solicitado un ejercicio de este tipo seguro que no eres tan nuevo en programación 😉
Mucho ánimo y espero que nos muestres tu código adaptado.