Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 09/01/2008, à 19:54

vincentced

Mysql load infile

Bonjour, j'ai un fichier que je voudrais mettre son contenu en base mais les champs sont séparés par un nombre d'espace différent. Ce fichier est généré par un automate dont je ne peux pas toucher à sa programmation.

Le contenu ressemble à:
2008  8 10 6 5
2008 10  5 7   4
...

J'utilise la commande suivante:
LOAD DATA LOCAL INFILE 'donnees.txt' INTO TABLE table2 FIELDS TERMINATED BY ' ';

Mais dans la base (5 colonnes correspondant aux différents champs), j'obtiens des champs vides, comme par exemple (les 0 correspondent à la valeur par défaut du champs de la table):
2008 0 8 10 6
2008 10 0 7 0

Je sollicite votre aide pour résoudre ce problème.

A noter:
Programmant en C# et Java, je pourrais passer par des objets en faisant une lecture de fichier et utiliser la commande "Split" pour déterminer les séparateurs mais et insérer les valeurs de l'objet par un "Insert". La programmation serait plus longue et je souhaite faire quelque chose d'optimal:
Load est plus rapide que Insert. Selon la doc Mysql:

La commande LOAD DATA INFILE lit les lignes dans un fichier texte et les insère à très grande vitesse

#2 Le 09/01/2008, à 21:27

pef

Re : Mysql load infile

Utiliser sed ou perl pour virer les espaces multiples dans ton fichier de données ?

Par exemple :

sed -s s/\ */\ /g tonficher

devrait faire l'affaire, sauf si tes espaces sont bizarres (autres caractères d'espacement)

Dernière modification par pef (Le 09/01/2008, à 21:31)

Hors ligne

#3 Le 10/01/2008, à 13:10

vincentced

Re : Mysql load infile

Merci de ta réponse mais elle ne me convient pas.

La commande MYSQL (Load) pour charger ce fichier dans la base est réalisée dans le code C# de l'application.

Je rappelle que la difficulté est qu'ntre les champs, le nombre d'espaces est différent.

Si quelqu'un a une solution a ce problème. Merci d'avance!

#4 Le 10/01/2008, à 13:22

pef

Re : Mysql load infile

C# ne permet pas les expression régulières ? Sinon modifie ton titre et indique C# dans le titre wink

Hors ligne

#5 Le 14/01/2008, à 22:12

vincentced

Re : Mysql load infile

Bonjour,

J'ai l'occasion d'apprendre une fonctionalité supplémentaire de MySql et j'ai besoin de votre aide.

Pour une insertion rapide du contenu du fichier (txt) dans la base de données MySQL, j'utilise la commande Load de Mysql dans C# (je n'utilise pas les objets car il faut que çà  soit rapide, et je dois le faire aussi en Java).

Je teste d'abord la commande dans le logiciel MySQL Browser pour visualiser le résultat (Echec ou réussite).

Malheureusement, le fichier texte contient un nombre d'espace différents entre chaque champs car à  l'origine, le fichier était formaté pour une meilleure visualisation pour les opérateurs (généré par des automates):
2007 345  3  3 50 D  3
2007   2 10 30  5 F 20
etc...

Or la commande Load ne permet pas le positionel mais je sais la taille (nombre de caractères de chaque champs).

Séparateur: espace
Longueur de chaque champs: 4 3 2 2 2 1 2

SVP, avez une solution seulement avec le MYSQL (sans aucun autre langage, il faut que la commande soit rapide d'exécution).

Merci de vos réponses!!!

#6 Le 15/01/2008, à 12:37

Aurel34

Re : Mysql load infile

c'est pas très clair ton discours...

t'as essayé FIELDS TERMINATES BY ' '  dans ta requète SQL ?
ou alors FIELDS TERMINATES BY ' ' OPTIONALLY ENCLOSED BY ' ' ?

ce qui me gène c'est qu'en théorie, si tu as les bons type dans ta tables, quand tu lui fait LOAD ... INTO ... il devrait se débrouiller...

sinon il va falloir modifier ton fichier AVANT de l'envoyer à  Mysql. sed (proposé par pef) et une bonne option, rapide (c'est un tout petit utilitaire qui tourne très vite) et ça te permet d'avoir une solution portable (tu le lances depuis le prog que tu veux).
en c#

Process.Start("sed 'machin truc chose'");

en java

Runtime runtime = Runtime.getRuntime();
runtime.exec("sed 'machin truc chose'");

Sinon les expressions régulières ça peut le faire, en C# ou Java.

Sinon un truc du genre:

BinaryReader myRead = File.Open(@"prout.txt");
BinaryWriter  myWrite = new BinaryWriter(@"prout2.txt");
char c = myRead.ReadChar();
while (c != null)
{
if (c != ' ')
{
myWrite.WriteChar(c);
c = myRead.ReadChar();
}
else
{
while (c == '  ') c = myReadChar();
myWrite.WriteChar(' ');
}
}
myRead.Close()
mywrite.Close();

(je sors ça comme ça, ya 1% de chance que ça compile direct, mais ça ne doit pas être loin de la vérité... et puis c'est transposable dans n'importe quel langage du moment qu'il y a une fonction pour lire caractère/écrire par caractère)
au niveau du C# il faut utiliser les stream binaires pour aller "vite". Mais tout ce fatra je ne suis pas sûr que ça aille plus vite que sed...

#7 Le 15/01/2008, à 13:19

Aurel34

Re : Mysql load infile

(ou plutà´t à  la fin:

while ((c == ' ')&&(c!=null)) c = myReadChar();

mais c'et un détail...)

enfin, on peut imaginer le même code en C (testé lui):

/* gcc -O2 no_space no_space.c
 * no_space int.txt out.txt
 * by ushu <noce@pcrob156.lirmm.fr>
 * 
 * Created:       mardi 15 janvier 2008, 13:11:58 (UTC+0100)
 */
#include <stdio.h>

int main(int argc, char *argv[])
{
	FILE *in, *out;
	int next_char;

	if (argc != 3) return 1;
	if (!(in=fopen(argv[1],"r"))) return 2;
	if (!(out=fopen(argv[2],"w"))) return 2;
	next_char = fgetc(in);
	while (next_char != EOF)
	{
		if ((char)next_char!=' ')
		{
			fputc(next_char,out);
			next_char = fgetc(in);
		}
		else
		{
			while (((char)next_char==' ')&&(next_char!=EOF))
				next_char = fgetc(in);
			fputc(' ',out);
		}
	}
	fclose(in);
	fclose(out);
	return 0;
}

sur un petit fichier de 20Mo généré avec

perl -e '$n=2000000;print do {"1"." "x(int(rand(5)+1))."2"." "x(int(rand(5)+1))."3\n"} while($n--)' > in.txt

j'obtiens

time ./no_space in.txt out.txt 

real    0m0.746s
user    0m0.688s
sys     0m0.056s

donc après faut voir ce que tu appelle "rapide". En comparaion avec sed

time sed -s s/\ */\ /g in.txt >> out2.txt

real    0m9.940s
user    0m9.821s
sys     0m0.088s

c'est mieux. Après faudrait voir ce que ça donne en C#, mais là  j'ai la flemme d'installer mono...

#8 Le 15/01/2008, à 14:07

vincentced

Re : Mysql load infile

Merci de ton aide, je vais tester.

J'ai aussi:
Load data local infile 'fichier.txt' into table table FIELDS TERMINATES BY ' ' OPTIONALLY ENCLOSED BY ' ';

mais arriver au caractère (VARCHAR(1)), il me met
Data Truncated.

Du coup, la colonne avec le caractère n'est pas rempli et la suite du tableau MySql est vide.

J'ai aussi essayer avec:
Load data local infile 'fichier.txt' into table table FIELDS TERMINATES BY '' OPTIONALLY ENCLOSED BY '';
ou il faut définir la taille de chaque champs dans la base mais il se bloque au moment du caractère (colonne de la table en VARCHAR(1))


Je continue à  chercher et je vais tester avec sed (que je ne connais pas).


J'espère trouver avec Load Data Infile.

#9 Le 15/01/2008, à 21:36

vincentced

Re : Mysql load infile

Problème résolu partiellement.

En fait, le problème provient de la version de MySql sous Windows 5.1 ou la commande Load Infile doit sans doute bugger.:mad:

En faisant le test sous Ubuntu (MySql 5.0 : Server version: 5.0.45-Debian_1ubuntu3.1-log Debian etch distribution), les deux tests réalisés donnent:
fichier test.txt :
2007 23 b 2

mysql> create table test (V1 int(4),V2 int(3),V3 char(2),V4 int(2));Query OK, 0 rows affected (0.53 sec)



mysql> load data local infile "test.txt" into TABLE test fields terminated by "" optionally enclosed by "";

Query OK, 1 row affected (0.00 sec)

Records: 1  Deleted: 0  Skipped: 0  Warnings: 0



mysql> select * from test;

+------+------+------+------+

| V1   | V2   | V3   | V4   |

+------+------+------+------+

| 2007 |   23 |  b   |    2 |

+------+------+------+------+

1 row in set (0.00 sec)


Oà¹:
mysql> create table test (V1 int(4),V2 int(2),V3 char(1),V4 int(1));Query OK, 0 rows affected (0.31 sec)



mysql> load data local infile "test.txt" into TABLE test fields terminated by " ";

Query OK, 1 row affected (0.00 sec)

Records: 1  Deleted: 0  Skipped: 0  Warnings: 0



mysql> select * from test;

+------+------+------+------+

| V1   | V2   | V3   | V4   |

+------+------+------+------+

| 2007 |   23 | b    |    2 |

+------+------+------+------+

1 row in set (0.00 sec)


Le résultat montre que les champs sont bien mis.

Excusez-moi du dérangement!!!