extraire les informations d'un fichier

othmani
extraire les informations d'un fichier

Salut tout le monde,
J’ai un fichier .txt standard: toutes les lignes sont structurées de la même manière la date suivie par l'heure suivie par une information..... tant qu'on n'a pas retour à la ligne c'est que la ligne n'est pas terminée, les champs sont séparés par des espaces.
Comment je peux ouvrir ce fichier et le parcourir afin d'extraire ces champs puisque j'ai besoins d'eux ailleurs;
S’il y a une personne qui peut m'aider qu'il n'hésite pas car c'est très urgent.
Merci

angelo

Je t'envoie la classe JAVA qui permet de faire ca :

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class TestFileParse {

	public static void main(String[] args) {
		File dataFile = new File("src/data.txt");
		try {
			InputStream ips = new FileInputStream(dataFile);
			InputStreamReader ipsr = new InputStreamReader(ips);
			BufferedReader br = new BufferedReader(ipsr);
			String ligne;
			while ((ligne = br.readLine()) != null) {
				// recuperation de la ligne courante
				System.out.println("Contenu de la ligne:" + ligne);
				// separation de la ligne avec le toke " " (espace)
				// 
				String token = " ";
				StringTokenizer stringTokenizer = new StringTokenizer(ligne, token);
				// Parcours des tokens de la ligne
				while (stringTokenizer.hasMoreElements()) {
					String element = (String) stringTokenizer.nextElement();
					System.out.println("Element : " + element);					
				}				
			}
			br.close();
		} catch (Exception e) {
			System.out.println(e.toString());
		}
	}
}

Creer un fichier data.txt dans le répertoire src avec ce contenu

29/05/07 18:30
28/05/07 06:00

Ce code est base sur l'exemple http://www.developpez.org/club/bkostrzewa/td-fichiers/texte.html

En gros tu lis chaque ligne du fichier avec BufferedReader
et tu utilises StringTokenizer pour coupe ta ligne avec le caractère " ".

Cette exemple de code n'est pas du tout optimise, donc si ton fichier est gros, il faudrait parser le fichier caractère par caractère.

De plus il n'y aucune gestion d'erreur si ton fichier n'est pas formatté correctment, mais je pense que ca te donnera deja une base.

Angelo

melie

Bonjour, je me permet d'utiliser ce post car j'ai un probleme similaire.
Je veux pouvoir parcourir un fichier et en extraitres des informations que j'enregistrait par la suite dans des variables.

Donc en fait il y a une classe spécifique qui fait ca? C'est bien ca?
Là l'exemple donné est pour un fichier texte avec date, heure, etc

Moi il s'agirait d'un fichier sql avec des requetes. le principe reste le meme??

Merci beaucoup.

angelo

Bonsoir,
si j'ai bien compris tu veux recuperer les informations d'une requetes provenant d'un fichier. Si tes reqêtes sont simples et si tu es sur qu'elles ont toujours la même structure tu peux utiliser l'exemple que j'ai utilise, par contre si tu veux gerer des requetes plus compliques comme
par exemple :

SELECT * FROM WHERE ID IN (SELECT ID FROM MYTABLE WHERE COL0='WHERE')

is il y a des requetes imbriques et WHERE est utilisé dans la condition SELECT mais aussi avec COL0='WHERE'. Il faut distinguer les 2 WHERE :

* le WHERE de la condition SQL
* le 'WHERE' dans COL0

En d'autres termes il faut definir une grammaire qui permettent de detecter les tokens. Pour cela tu peux utiliser ANTLR http://www.antlr.org/ par exemple qui te permet de definir une grammaire et ensuite de generer le parser/lexer JAVA.

Beaucoup de projet Open Source sont basés sur antlr. Je croies (mais pas sur a 100%) que Hibernate est base sur antlr pour definir la grammaire les requetes HBM.

Le liens http://www.antlr.org/grammar/list te donne des exmples de grammaires que tu peux ecrire.

Dans cette liste il y a la grammaire ORACLE http://www.antlr.org/grammar/ORACLE-7-SQL/sql.g dont tu pourrais t'e inspirer.

Mais je ne te cache pas que ca demande un investissement. Je suis en train d'etudier ANTLR pour mon projet de generation de code Akrogen http://akrogen.sourceforge.net/index.html et j'en bave pas mal meme si ANTLR est très puissant.

Bon courage

Angelo

othmani

Bonjour, merci pour vos remarques,
mais je voulais éclaircir quels points; le fichier que je vais l'étudier c'est un fichiers .evt transformé en .txt (c'est moi que je l'avais écrit) puis en étudiant bien ce fichier j'ai remarqué que les champs ne sont pas séparés par des espaces, je pense deux champs sont séparés par une tabulation (j'en suis pas sur car en voyant le fichier les champs ne sont pas séparés par des espaces égales mais c’est sûr qu’ils ne sont pas des espaces), le problème aussi c'est que le champ lui même peut contenir des espaces puisque un champ peut être une phrase.

angelo

Bonjour,
si les séparation sont des tabulations, il suffit just de changer le token de séparation par la tabulation, autrement dir :

String token = "\t";

Maintenant si le token a des espaces et que ton fichier a des espaces, ca me parait difficile de decouper correctement ta ligne. En effet comment veut tu faire une différence entre un espace qui detecte un nouveau champs et un espace d'une phrase? Si c'est le cas, tu dois modifier la structure de ton fichier.

Angelo

melie

Bonjour, merci pour ta réponse détaillée.
Par contre je m'excuse, je me suis mal exprimée et en fait ce ne sont pas des requetes, je me suis emmelée dans les mots désolée.

C'est un fichier du type :

-- phpMyAdmin SQL Dump
-- version 2.6.2-Debian-3sarge3
-- http://www.phpmyadmin.net
-- 
-- Serveur: server
-- Généré le : Jeudi 17 Mai 2007 à 21:12
-- Version du serveur: 4.0.24
-- Version de PHP: 4.3.10-19
-- 
-- Base de données: `base`
-- 
CREATE DATABASE `base`;
USE base;

-- --------------------------------------------------------

-- 
-- Structure de la table `Enseignant`
-- 

CREATE TABLE `Enseignant` (
  `num` int(11) NOT NULL auto_increment,
  `nom` varchar(20) NOT NULL default '',
  `prenom` varchar(20) NOT NULL default '',
  `mail` varchar(30) default NULL,
  `codeCat` varchar(5) NOT NULL default '0',
  PRIMARY KEY  (`num`)
) TYPE=MyISAM AUTO_INCREMENT=48 ;

-- 
-- Contenu de la table `Enseignant`
-- 

INSERT INTO `Enseignant` (`num`, `nom`, `prenom`, `mail`, `codeCat`) VALUES (1, 'Machin', 'Machin', 'machin@machin.com', 'vac');

C'est un fichier sql.
Ce qui m'interesse dedans en fait c'est le nom de la table (donc derriere le create table) ainsi que les attributs et leurs "options".

Je me fiche du reste. je vais donc devoir supprimer des lignes.

Est ce que pour la lecture du fichier et la suppression ca ressemble à ce qui a été dit plus haut pour la personne qui avait à la base créé ce post? (avec des modifications evidemment)

Voilà merci beaucoup et encore désolé de m'etre mal exprimée.

angelo

Y a pas de souci.

/*
 * Created on 30 mai 2007
 * 
 * To change the template for this generated file go to
 * Window>Preferences>Java>Code Generation>Code and Comments
 */

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class ParseTable {

	public static void main(String[] args) {
		File dataFile = new File("src/sql.txt");
		try {
			InputStream ips = new FileInputStream(dataFile);
			InputStreamReader ipsr = new InputStreamReader(ips);
			BufferedReader br = new BufferedReader(ipsr);
			String ligne;
			while ((ligne = br.readLine()) != null) {
				// recuperation de la ligne courante
				//System.out.println("Contenu de la ligne:" + ligne);
				String tokenCreateTable = "CREATE TABLE";
				if (ligne.startsWith(tokenCreateTable)) {
					// La ligne commence par "CREATE TABLE", c'est une table
					System.out.println("Ligne table trouvé");
					// Recuperation du nom de la table
					// Qui est compris entre CREATE TABLE et (
					int indexStartOption = ligne.indexOf("(");
					String tableName = ligne.substring(tokenCreateTable.length(), indexStartOption);
					// ici tableName = " `Enseignant` "
					// suppression des espaces gauche/droite
					tableName = tableName.trim();
					// Suppression des simples quotes `
					tableName = tableName.replaceAll("`", "");
					System.out.println("Nom de la table : " + tableName);
					
				}
			}
			br.close();
		} catch (Exception e) {
			System.out.println(e.toString());
		}
	}

}

Voici le code qui permet de retrouver le nom de la table (mais pareil c pas du tout optimise). pour les options je pense que tu peux te debrouiller.
Les commenatires t'explique l'algorythme.

Pour faire marcher cette classe, tu copie ton fichier sql dans le repoertoire src et en le nommant sql.txt

Angelo

melie

Merci beaucoup!!!!

Oui une fois que j'aurais bien compris le principe pour la recuperation du nom de la table, ca devrait aller pour les attributs.

C'est tres gentil merci.

melie

J'ai une petite question, pourquoi faut il renommer le fichier machin.sql en sql.txt?

La classe n'accepte que les txt?

angelo

Non la classe accepte n'importe quel fichier texte
Dans mon code j'ai fais

File dataFile = new File("src/sql.txt");

Toi tu peux faire

File dataFile = new File("src/machin.sql");

Angelo

melie

En tout cas merci beaucoup, j'ai testé dans mon programme, ca marche nickel! Et en plus j'ai compris :D

Merci.
J'ai plus qu'à faire pareil avec mes attributs!

melie

Bonjour!

J'ai une petite question.
Je veux toujours extraires mes infos concernant les attributs maintenant.
Et en fait je veux recuperer le type de l'attribut, donc pour cela je fais de la meme maniere que pour le nom de la table. Je dis entre quoi et quoi un type d'attribut est compris. Sauf que voilà ca depend du type.

Si j'ai un int, j'aurais int(11) et si j'ai une date, j'aurais juste date.
Donc au debut j'avais mis

String repereType ="  '"+nomAttribut+"' ";
int motifType = ligne.indexOf("(");
String typeAttribut = ligne.substring(repereType.length(), motifType);

Mais je voudrais aussi

int motifType = ligne.indexOf(" ");

Est ce que je peux donner ces deux valeurs à ma variable motifType?

fredericmazue

Quote:
Je veux toujours extraires mes infos concernant les attributs maintenant.

Je dois dire que je ne comprends rien (mais alors rien) à ce que tu fais et j'aimerais bien en capter un minimum.
Si j'ai bien lu ce qui précède, tu analyses un fichier de requête SQL, c'est ça ? Par exemple tu cherches CREATE TABLE pour voir où la création d'une table commence.

Bon mais après c'est quoi cette histoire d'attributs ? Il y a des "attributs" dans une requête SQL INSERT (je suppose que derrière CREATE TABLE il y a des INSERT) ?

Quote:
Si j'ai un int, j'aurais int(11)

Qu'est-ce que cela :?:
Quote:
si j'ai une date, j'aurais juste date

Et la valeur de la date elle passe à la trappe ?

Moi j'aimerais bien voir un petit extrait du fichier SQL sur lequel tu travailles, on dirait qu'il vaut le coup d'oeil. :D

Quote:
Est ce que je peux donner ces deux valeurs à ma variable motifType

Comme je ne comprends rien, je ne sais pas :)
Mais une même variable pour deux usages différent, c'est n'est jamais très bon signe dans du code.
Et puis la recherche de tes différents types "d'attributs" (mais que diable est-ce ?) ne semble pas clairement différenciée.
Je veux dire, on ne dirait pas que tu cherches d'abord tous les int(11) puis toutes les dates successivement.
Ou bien que tu prends les lignes une à une pour en analyser méthodiquement les tokens (i.e int, date, tec)

On pourrait pas des fois voir un bout de ce fichier SQL et un peu de ton code, histoire de parler de choses concrètres ?

melie

Bah les deux extraits sont présents.
J'ai posté plus haut un extrait du fichier sql. Et aussi de mon code.

Mais en fait j'ai trouvé une alternative, seulement j'ai des soucis avec ligne.indexOf().

Peut on lui passer un espace c'est à dire ligne.indexOf(" ")? Ou y a t'il un caractere special pour l'espace. Car quand j'ecrit ca, ca donne une erreur...

melie

Pour etre plus precise j'ai

String repereType ="  `"+nomAttribut+"` ";
int motifType = ligne.indexOf(" ");
String typeAttribut = ligne.substring(repereType.length(), motifType);

Ainsi si on regarde l'extrait du fichier sql que j'ai posté plus haut, je souhaite avec ce code recuperer soit int(11), soit date ou autre selon le type de l'attribut.

Mais ca ne marche pas et j'obtiens comme erreur :

java.lang.StringIndexOutOfBoundsException: String index out of range: -8

Je pense que ca viens du ligne.indexOf mais je n'en suis pas sure.
C'est pour ca que je me demande si ce que j'ai ecrit est bon et où serait l'erreur.

Merci.

fredericmazue

Quote:
Ainsi si on regarde l'extrait du fichier sql que j'ai posté plus haut, je souhaite avec ce code recuperer soit int(11), soit date ou autre selon le type de l'attribut.

Autant pour moi :oops:
J'avais oublié qu'il était plus haut.
Mais c'est bien fait pour toi aussi ;) A l'avenir, quand tu voudras poser une question tu sauras que ce n'est pas pertinent de l'intercaler dans la discussion relative à une autre question, même si cette autre est semblable. Bref tu m'as enduit d'erreur. :D

Bon je comprends qu'on est toujours à analyser la requête CREATE TABLE donc. C'est déjà plus clair :)
Mais j'ai beau écarquiller les yeux, :shock: je ne vois pas de date dans cet exemple. (Et j'ignorais que les types étaient des attributs ;) ) Enfin bref.

Quote:
int motifType = ligne.indexOf(" ")

Je suppose qu'avec ça, tu veux te placer sur le premier caractère non blanc de la ligne, c'est ça ?
Bon et si la ligne commence par deux espaces :D ?

Bon pour commencer faut pas bricoler comme ça. Il est beaucoup plus rationnel de dégager de ta ligne les espaces de début et de fin. Comme ceci (en supposant que ligne est une String bien sûr):

ligne = ligne.trim();

Quant à ton erreur OutOfBound, je parierais assez volontiers que la valeur repereType.Length() est plus grande que motifType et que du coup tu cherches à reculons dans la chaîne :lol: et évidemment....
Si j'en crois ce que je vois de ton code, motifType vaut 0 et repèreType sans doute 8, d'où le -8 dans l'erreur.

melie

Oui en fait dans l'extrait du fichier sql que j'ai mis on ne voit pas d'exemple avec "date".

Bon là je comprend pas! :evil:

Voici mon code :

ligne = br.readLine();
ligne = ligne.trim(); 
int j=0;
String repereAttribut= "`";
while (ligne.startsWith(repereAttribut)) {

    // La ligne commence par "`" : c'est un attribut
    System.out.println("Un attribut a été trouvé");
		        		    
    // On recupere le nom de l'attribut qui est compris entre "`" et "` "
    int motifAtt = ligne.indexOf("` ");
    String nomAttribut = ligne.substring(repereAttribut.length(), motifAtt);
		                
     // On recupere le type de l'attribut compris entre le nom de l'attribut et " "
    String repereType ="`"+nomAttribut+"` ";
	                		
    int motifType = ligne.indexOf(" ");
	                			                		
             		
    String typeAttribut = ligne.substring(repereType.length(), motifType);

	               		 
    System.out.println("Nom de l'attribut : " + nomAttribut); 
    System.out.println("Type de l'attribut : " + typeAttribut); 

    j++;

Donc en fait je suis ton conseil, j'enleve les espaces de debut et de fin de la ligne.
Ensuite je regarde si la ligne commence par "`" et dans ce cas je recupere le nom de l'attribut qui est donc compris entre "`" et "` ".

Ensuite je veux son type (int(22) ou date ou autre...).

Le type est compris entre le nom et " " (espace) d'apres la configuration de la ligne.

C'est donc ce que je fais dans mon code.
Et là comme on a enlevé les espaces de debut et de fi, ca ne devrait pas poser de probleme. (mon probleme de tout à l'heure etait qu'il prenait le premier espace qu'il trouvait et non pas celui dont j'avais besoin :) ).

Je pensais donc que ca allait marcher, mais non et je vois pas pourquoi là.

fredericmazue

Quote:
Je pensais donc que ca allait marcher, mais non et je vois pas pourquoi là.

T'es tu amusée è regarder ce que vaut motifType-repereType.length() par curiosité ? :D

Et au fait int(22) ça a du sens ? Un int c'est 11 caractère maxi en MySQL je crois

Bon, comme je le disais faut pas bricoler. Je te propose d'aller lire la Javadoc de java.util.StringTokenizer. Je suis sûr que ça va te plaire :)

melie

J'ai reussi à faire fonctionner mais c'est vrai que c'est peut etre un peu du bricolage.

J'ai regardé la Javadoc de java.util.StringTokenizer mais est ce que ca risque pas de poser un probleme. par exemple j'ai ce type de ligne :

  `id` int(11) NOT NULL auto_increment,

NOT NULL forme un "tout" et avec cette méthode ne va t'il pas me le couper?

fredericmazue

Quote:
NOT NULL forme un "tout" et avec cette méthode ne va t'il pas me le couper?

Si, et alors ?
melie

Bah en fait sur la ligne que j'ai mis au dessus de mon fichier sql, je dois recuperer chacune des informations c'est à dire le type de l'attribut (date, int...), s'il est NULL ou NOT NULL, autoincrement ou pas.

Et apres j'enregistre chacune de ces informations dans des variables spécifiques.

Et donc j'ai besoin de mon "NOT NULL" en entier.

fredericmazue

Oui. Et alors :?:

Niroken
Une aide:)

import java.io.*;
import java.util.regex.*;

public class ParserSql
{
	public static void main(String[] args)
	{
		ParserSql parserSql = new ParserSql();
		parserSql.ParserSqlForRecupTableName("toto.txt");
		parserSql.ParserSqlForRecupTableFields("toto.txt");		
	}
	
	public void ParserSqlForRecupTableName(String inputFile)
	{
		try
		{
			BufferedReader lecteurAvecBuffer = null;
			lecteurAvecBuffer = new BufferedReader(new FileReader(inputFile));
			
			String ligneLue;
											
			while((ligneLue = lecteurAvecBuffer.readLine()) != null)
			{
				if (ligneLue.matches(".*CREATE TABLE.*"))
				{
					boolean TableNameBegin = false;
					String TableName = "";
					
					for (int i = 0; i < ligneLue.length(); i++)
					{
						if (ligneLue.charAt(i) == '`' && TableNameBegin == true)
						{
							System.out.println("TableName : " + TableName);
							return;
						}
						if (TableNameBegin == true)
						{
							TableName += ligneLue.charAt(i);
						}
						if (ligneLue.charAt(i) == '`' && TableNameBegin == false)
						{
							TableNameBegin = true;
						}
					}
				}
			}
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
	}
	
	public void ParserSqlForRecupTableFields(String inputFile)
	{
		try
		{
			BufferedReader lecteurAvecBuffer = null;
			lecteurAvecBuffer = new BufferedReader(new FileReader(inputFile));
			
			String ligneLue;
											
			System.out.println("TableFields : ");
			
			while((ligneLue = lecteurAvecBuffer.readLine()) != null)
			{
				if (ligneLue.trim().matches("`.*"))
				{
					String[] ligneLueTab = ligneLue.split(" ");
					
					for (int i = 0; i < ligneLueTab.length; i++)
					{
						if (ligneLueTab[i].trim().equals("NOT"))
							System.out.print(ligneLueTab[i] + " " + ligneLueTab[i + 1] + "#");
						else
							System.out.print(ligneLueTab[i] + "#");	
					}
				
					System.out.println("");
				}
			}
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
	}
}

Bon voila ceci résoud ton problème en ce qui concerne
l' extraction du nom de la table et des champs.

J'ai fait ce code assez rapidement, si cela n 'est pas assez
clair je le détaillerais...

Pour en faire bon usage, il suffit de remplacer les "toto.txt"
par le nom de ton fichier, ce code fonctionne pour le format
de fichier que tu as fourni sur le post ci avant.

Bonne chance

fredericmazue
Avant

Bel effort :)
Les expressions régulières maintenant :) Mélie est gâtée :)
Je trouve quand même plus simple d'utiliser le StringTokenizer sur ce coup.

Regarde Mélie:

Quote:
if (ligneLueTab[i].trim().equals("NOT"))
System.out.print(ligneLueTab[i] + " " + ligneLueTab[i + 1]

Avant aussi il a "coupé" le NOT NULL en deux, et là quand il trouve NOT il concatène avec l'élément suivant. Ce que tu pouvais très bien faire aussi avec les token obtenus par le StringTokenizer, tout simplement.
melie

Merci pour tout ce code, mais c'est normal que j'ai pas tout compris... :?

Ce que j'ai reussi à faire moi, c'est recuperer le nom de ma table, recuperer les noms de mes attributs pour chacune des tables. Pour chaque attribut je recupere également son type (int, char, varchar. Dans mon code chaque type correspond à un Id (necessaire pour le reste du programme).
J'ai egalement recuperer la taille pour certains types d'attributs.

Je vous montre mon code, je me doute que c'est pas tres propre, et j'espere que vous comrpendrez toutes les etapes de ma... reflexion :wink:

	                
	                ligne = br.readLine();

	                int j=0;

	                String repereAttribut= "  `";
	                while (ligne.startsWith(repereAttribut)) {

	                		// La ligne commence par "  `" : c'est un attribut
	                		System.out.println("Un attribut a été trouvé");
	                		
	                		// On enlève les espaces de debut et de fin de ligne
	    	                ligne = ligne.trim();
	    	                
	                		// On recupere le nom de l'attribut qui est compris entre "`" et "` "
	    	                repereAttribut="`";
	                		int motifAtt = ligne.indexOf("` ");
	                		String nomAttribut = ligne.substring(repereAttribut.length(), motifAtt);
		                
	                		String repereType ="`"+nomAttribut+"` ";
	                		
	                		
	                		// On modifie la ligne
	                		ligne = ligne.substring(repereType.length());
	                		int motifType = ligne.indexOf(" ");

	                		
	                		// On extrait le type de l'attribut complet
	                		String typeComplet = ligne.substring(0, motifType);
	                		String typeAttribut = typeComplet;
	                		String tailleAttributString = null;
	                		int tailleAttribut = 0;
	                		
	                		// On extrait le type de l'attribut
	                		if (typeComplet.endsWith(")")) { 
	                			typeAttribut = typeComplet.substring(0, typeComplet.indexOf("("));
	                			String repere = typeAttribut+"(";
	                		    tailleAttributString = typeComplet.substring(repere.length(), typeComplet.indexOf(")"));
	                		    tailleAttribut = Integer.parseInt(tailleAttributString);
	                		}

	                		// On teste le type de l'attribut pour lui attribuer le numero correspondant
	                		int numeroAttribut= 0;
	                		
	                		if (typeAttribut.compareTo("varchar")==0) {
	                			numeroAttribut = 0;
	                		}
	                		if (typeAttribut.compareTo("tinyint")==0) {
	                			numeroAttribut = 1;
	                		}
	                		if (typeAttribut.compareTo("text")==0) {
	                			numeroAttribut = 2;
	                		}
	                		if (typeAttribut.compareTo("date")==0) {
	                			numeroAttribut = 3;
	                		}
	                		if (typeAttribut.compareTo("smallint")==0) {
	                			numeroAttribut = 4;
	                		}
	                		if (typeAttribut.compareTo("mediumint")==0) {
	                			numeroAttribut = 5;
	                		}
	                		if (typeAttribut.compareTo("int")==0) {
	                			numeroAttribut = 6;
	                		}
	                		if (typeAttribut.compareTo("bigint")==0) {
	                			numeroAttribut = 7;
	                		}
	                		if (typeAttribut.compareTo("float")==0) {
	                			numeroAttribut = 8;
	                		}
	                		if (typeAttribut.compareTo("double")==0) {
	                			numeroAttribut = 9;
	                		}
	                		if (typeAttribut.compareTo("decimal")==0) {
	                			numeroAttribut = 10;
	                		}
	                		if (typeAttribut.compareTo("datetime")==0) {
	                			numeroAttribut = 11;
	                		}
	                		if (typeAttribut.compareTo("timestamp")==0) {
	                			numeroAttribut = 12;
	                		}
	                		if (typeAttribut.compareTo("time")==0) {
	                			numeroAttribut = 13;
	                		}
	                		if (typeAttribut.compareTo("year")==0) {
	                			numeroAttribut = 14;
	                		}
	                		if (typeAttribut.compareTo("char")==0) {
	                			numeroAttribut = 15;
	                		}
	                		if (typeAttribut.compareTo("tinyblob")==0) {
	                			numeroAttribut = 16;
	                		}
	                		if (typeAttribut.compareTo("tinytext")==0) {
	                			numeroAttribut = 17;
	                		}
	                		if (typeAttribut.compareTo("blob")==0) {
	                			numeroAttribut = 18;
	                		}
	                		if (typeAttribut.compareTo("mediumblob")==0) {
	                			numeroAttribut = 19;
	                		}
	                		if (typeAttribut.compareTo("mediumtext")==0) {
	                			numeroAttribut = 20;
	                		}
	                		if (typeAttribut.compareTo("longblob")==0) {
	                			numeroAttribut = 21;
	                		}
	                		if (typeAttribut.compareTo("longtext")==0) {
	                			numeroAttribut = 22;
	                		}
	                		
	                		System.out.println("Nom de l'attribut : " + nomAttribut); 
	                		//System.out.println("Type complet de l'attribut : " + typeComplet); 
	                		System.out.println("Type de l'attribut : " + typeAttribut);
							System.out.println("Numero de l'attribut : " + numeroAttribut);
							System.out.println("Taille de l'attribut : " + tailleAttribut);
	                		j++;
		                

Voilà :oops:

Maintenant j'arrive au probleme d'extraire le NULL ou NOT NULL.
Et c'est là que je comprend pas tout.

melie

Je crois que je viens de comprendre cette partie du code :

while((ligneLue = lecteurAvecBuffer.readLine()) != null)
         {
            if (ligneLue.trim().matches("`.*"))
            {
               String[] ligneLueTab = ligneLue.split(" ");
               
               for (int i = 0; i < ligneLueTab.length; i++)
               {
                  if (ligneLueTab[i].trim().equals("NOT"))
                     System.out.print(ligneLueTab[i] + " " + ligneLueTab[i + 1] + "#");
                  else
                     System.out.print(ligneLueTab[i] + "#");   
               }
            
               System.out.println("");
            }
         } 

Ca a l'air de simplifier grandement ma recuperation des champs d'attribut.

Niroken

Bon je m'explique brièvement :

if (ligneLue.trim().matches("`.*"))
Ce morceau -> on récupère ttes les lignes qui
commencent par un `

String[] ligneLueTab = ligneLue.split(" ");
Celui ci : je découpe ma chaine avec comme délimiteur
le caractère espace., le tout stocké dans le tableau
"ligneLueTab"

Ensuite je parcours mon tableau j affiche tt les élements un par un
sauf dans le cas ou je détecte un "NOT" et la je l ajoute avec
le "NULL" qui logiquement est contenu dans le case suivante.

Voila voila

Bonne chance

melie

Merci, en effet ca parait plus simple et plus propre que ce que j'ai fais.

fredericmazue

Quote:
NOT" et la je l ajoute avec
le "NULL" qui logiquement est contenu dans le case suivante.

[...]
Merci, en effet ca parait plus simple et plus propre que ce que j'ai fais.

Et si tu veux bien faire, tu dois améliorer le code de Niroken. Niroken t'as bien dit que son code marche avec le fichier d'exemple que tu as donné.
Mais si le code doit être amené à analyser d'autres fichiers SQL, alors tu dois éliminer un bug potentiel, qui se produira si un NOT n'est pas suivi de NULL (ca existe en SQL). Tout ce que tu as à faire est de vérifier que dans la "case suivante d'un NOT" tu as bien un NULL. :)

fredericmazue

Salut,

Ayant eu 5 minutes, j'ai repris le code de Niroken avec une approche un peu différente pour varier les plaisirs. Au lieu de splitter NOT NULL et de le reconstituer après, on le cherche dans la chaîne en amont. S'il y est on splite la chaîne avec NOT NULL comme critère de séparation puis on splitte les deux parties obtenues avec " " comme critère de séparation puis on regroupe le tout. S'il n'y a pas NOT NULL on splitte avec " " normalement.
J'ai aussi ajouté la suppression de la virgule finale dans les lignes d'attributs et je parcoure le fichier une seule fois au lieu de deux. En outre mon code a une caractéristique qui peut être vue comme un avantage ou un inconvénient (Ca c'est un test pour voir s'il y en a qui suivent)
Voici le code donc:

(defun parse-sql-file (file)
  (with-open-file (stream file)
    (loop for line = (read-line stream nil 'eof)
	  until (eq line 'eof)
	  append (parse-sql-line (string-trim " " line)))))
    
(defun parse-sql-line (line)
  (let ((header-table "CREATE TABLE ")
	(pos-header nil)
	(is-attribute nil)
	(result))
    (setf pos-header (search header-table line))
    (if ( > (length line) 0)
	(setf is-attribute (eq (char line 0) #\`)))
    (if (not (eq pos-header nil))
	(push (build-table-name line header-table) result))
    (if (not (eq is-attribute nil))
	(push (parse-attribute line) result))
  (reverse result)))

(defun build-table-name (line header-table)
   (format nil "Nom de la table: ~A"
 	  (car (cl-utilities:split-sequence #\space (remove #\` (subseq line (length header-table)))))))

(defun parse-attribute (line)
    (let* ((double-token " NOT NULL")
	   (before (search double-token line))
	 (after)
	 (result))
      (if (numberp before)
	  (progn
	    (setf after (length double-token))
	    (setf result (cl-utilities:split-sequence #\space line :start 0 :end before))
	    (setf result (append result (list double-token)))
	    (setf result (append result (cl-utilities:split-sequence #\space (remove #\, line) :start after))))
	  (setf result (append result (cl-utilities:split-sequence #\space (remove #\, line)))))  
    result))

(dolist (x (parse-sql-file "fichier.sql")) (format t "~A~%" x))

et la sortie produite est:


Nom de la table: Enseignant
(`num` int(11)  NOT NULL (11) NOT NULL auto_increment)
(`nom` varchar(20)  NOT NULL char(20) NOT NULL default '')
(`prenom` varchar(20)  NOT NULL varchar(20) NOT NULL default '')
(`mail` varchar(30) default NULL)
(`codeCat` varchar(5)  NOT NULL  varchar(5) NOT NULL default '0')

Oui je sais... j'ai un peu changé la syntaxe générale aussi. Je n'ai pas pu m'en empêcher. :lol:

melie

Bonjour, je voulais vous remercier pour les diverses propositions concernant mon probleme.
Je me suis surtout servi de la toute premiere idée, elle etait plus à ma portée je pense.

Mais merci d'en avoir proposé d'autres

:wink: