IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Entrée/Sortie Java Discussion :

Remplir une Arraylist à partir d'un fichier csv


Sujet :

Entrée/Sortie Java

  1. #81
    Candidat au Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Décembre 2016
    Messages
    52
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 28
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2016
    Messages : 52
    Points : 3
    Points
    3

  2. #82
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Le problème est que le fichier POP.csv est partiellement pourri : il y a des lignes à la fin qui ne sont pas cohérentes (pas les mêmes datas). En plus la regexp de parsing ne fonctionne pas s'il n'y a aucune donnée dans une ligne (que des virgules).
    Par ailleurs, les index que tu utilisais n'étaient pas tous correct et donc ça ne prenait pas les données correspondantes. En particulier, les fichiers 2 et 3 référence les pays en anglais, donc on ne pouvait pas utiliser le nom du pays en français comme clef. Au vu de ton code de recherche d'ailleurs, ce sont les noms en anglais qu'il faut prendre comme nom de pays à priori. On peut changer ça facilement en modifiant le dataIndex pour le collect du premier fichier, mais il faudra recherche "France (La)" pour trouver le pays "France" ! Ou alors il faudrait traiter le nom pour virer ce qui se trouve entre parenthèse (par regexp).
    Il y a aussi beaucoup de données non utilisable (dans le fichier de surface, il y a des pays non présent dans le premier fichier)
    Le code suivant fonctionne globalement (on extrait certains pays, avec leur population et surface), mais il faudrait éventuellement envisager de lire le premier fichier à part (il contient différentes données, nom de pays en 2 langues, code iso639) qui pourraient servir à matcher dans d'autres fichiers, selon les cas.

    J'ai aussi modifié le code pour que la population et la surface soit sous forme numérique ce qui est quand même plus logique.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    public class CountryManager implements Iterable<Country>{
     
    	private static final String PROPERTY_SURFACE = "surface";
    	private static final String PROPERTY_POPULATION = "population";
    	private static final String PROPERTY_NAME = "name";
    	final List<Country> countries;
     
    	public CountryManager() throws IOException {
    		countries = Collections.unmodifiableList(readCountries());
     
    	}
     
    	public Country searchByCountryName(String countryName) throws NoSuchElementException { 
     
    		Country result = null;
    		for (Country country: countries) {
    			if (country.getName().equalsIgnoreCase(countryName)) {
    				result = country;
    				break;
    			}
    		}
    		if (result == null) {
    			throw new NoSuchElementException("Country " + countryName + " does not exists.");
    		} else {
    			return result; 
     
    		}
    	}
     
    	public List<Country> getCountries() {
    		return countries;
    	}
     
    	public Iterator<Country> iterator() {
    		return countries.iterator();
    	}
     
    	public static void main(String[] args) {
     
    		try {
    			CountryManager countryManager = new CountryManager();
    			for(Country country : countryManager) {
    				System.out.println(country);
    			}
     
    			System.out.println("Search France: " + countryManager.searchByCountryName("France"));
     
    		} catch (IOException e) {
     
    			e.printStackTrace();
    		}
     
    	}
     
    	/**
             * 
             * @param file
             *            nom de fichier
             * @param lineToSkip
             *            nombre de ligne à ignorer au début du fichier
             * @param splitString
             *            expression régulière pour découpage de lignes en tableau
             * @param dataIndex
             *            numéro de la cellule dans le tableau
             * @param name
             *            nom de la propriété à lire
             * @param countryIndex
             *            numéro de la cellule qui contient le nom du pays, ou -1 si on
             *            lit les noms de pays
             * @param map
             *            une map pour stocker le résultat
             * @throws IOException
             */
    	public static void collect(String file, Charset charset, int lineToSkip, String splitString, int dataIndex, String propertyName,
    			int countryIndex, boolean keyDef, Map<String, Map<String, String>> map) throws IOException {
     
    		try (BufferedReader reader = Files.newBufferedReader(Paths.get(file), charset)) {
    			for (String line = reader.readLine(); line != null; line = reader.readLine()) {
    				if (lineToSkip > 0) { // on saute les lignes au début
    					lineToSkip--;
    					continue;
    				}
    				if ( !line.trim().isEmpty() ) {
    					final String[] data = line.split(splitString);
    					//System.out.println(Arrays.toString(data));
    					if (dataIndex >= data.length) {
    						/*System.err.println(file+ ": Ligne ignorée (pas assez de données): " + data.length + "<=" + dataIndex + " "
    								+ Arrays.toString(data) + " "+line);*/
    					} else {
    						if (countryIndex >= data.length) {
    							/*System.err.println(file+ ": Ligne ignorée (pas assez de données pour le pays): " + data.length
    									+ "<=" + countryIndex + " " + Arrays.toString(data)+ " "+line);*/
    						} else {
    							String value = data[dataIndex].trim();
    							String countryKey = data[countryIndex].trim().toLowerCase();
    							if (keyDef) {
    								final Map<String, String> dataMap = new HashMap<>();
    								dataMap.put(propertyName, value);
    								map.put(countryKey, dataMap);
    							} else {
    								final Map<String, String> dataMap = map.get(countryKey);
    								if (dataMap != null) {
    									dataMap.put(propertyName, value);
    								}
    								/*else {
    									System.err.println("Country not found: " + data[countryIndex]);
    								}*/
    							}
    						}
    					}
    				}
    			}
    		}
     
    	}
     
    	public static List<Country> readCountries() throws IOException {
     
    		final Map<String, Map<String, String>> map = new HashMap<>();
     
    		collect("country_codes_iso.csv", StandardCharsets.UTF_8, 1, ",", 0, CountryManager.PROPERTY_NAME, 0, true, map); // nom du pays
    		collect("POP.csv", StandardCharsets.ISO_8859_1, 6, ",(?=([^\"]*\"[^\"]*\")*[^\"]*$)", 4, CountryManager.PROPERTY_POPULATION, 3, false, map); // population
    		collect("rawdata_2147.txt", StandardCharsets.UTF_8, 0, "\t", 2, CountryManager.PROPERTY_SURFACE, 1, false, map); // surface
     
    		return map.values().stream().map(m -> new Country(m.get(CountryManager.PROPERTY_NAME),
    				convertPopulation(m.get(CountryManager.PROPERTY_NAME), m.get(CountryManager.PROPERTY_POPULATION)), convertSurface(m.get(CountryManager.PROPERTY_NAME), m.get(CountryManager.PROPERTY_SURFACE))))
    				.collect(Collectors.toList());
     
    	}
     
    	private final static DecimalFormat POPULATION_FORMAT = new DecimalFormat("#,##0",
    			DecimalFormatSymbols.getInstance(Locale.US));
     
    	private static long convertPopulation(String country, String string) {
    		if ( string!=null ) {
    			string = string.trim().replaceAll("\"","");
    			if ( !string.isEmpty() ) {
    				try {
    					return (long) POPULATION_FORMAT.parse(string);
    				} catch (ParseException | ClassCastException e) {
    					System.err.println("Erreur dans la population de " + country + ": " + string + " n'est pas un nombre entier.");
    				}
    			}
    		}
    		return 0;
    	}
     
    	private final static DecimalFormat SURFACE_FORMAT = new DecimalFormat("#,##0",
    			DecimalFormatSymbols.getInstance(Locale.US));
     
    	private static long convertSurface(String country, String string) {
     
    		if ( string!=null ) {
    			string = string.trim().replaceAll("\"","");
    			if ( !string.isEmpty() ) {
    				try {
    					return (long) SURFACE_FORMAT.parse(string);
    				} catch (ParseException | ClassCastException e) {
    					System.err.println("Erreur dans la surface de " + country + ": " + string + " n'est pas un nombre entier.");
    				}
    			}
    		}
    		return 0;
     
    	}
     
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    public class Country {
     
    	private final String name;
    	private final long population;
    	private final long surface;
     
    	private final static DecimalFormat DECIMAL_FORMAT = new DecimalFormat("#,##0",DecimalFormatSymbols.getInstance(Locale.US));
     
    	public Country(String name, long population, long surface) {
    		this.name=name;
    		this.population=population;
    		this.surface=surface;
    	}
     
    	public String getName() {
    		return name;
    	}
     
    	public long getPopulation() {
    		return population;
    	}
     
    	public long getSurface() {
    		return surface;
    	}
     
    	@Override
    	public String toString() {
    		return "["+name+";pop="+DECIMAL_FORMAT.format(population)+";surface"+DECIMAL_FORMAT.format(surface)+"]";
    	}
     
    }
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  3. #83
    Candidat au Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Décembre 2016
    Messages
    52
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 28
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2016
    Messages : 52
    Points : 3
    Points
    3
    Par défaut
    Je te remercie vraiment pour ton aide ! Et ta patience surtout !
    J'ai dernière question, lorsque tu recherches par nom le pays tu utilises la méthode "country.getName().equalsIgnoreCase(countryName))"
    Mais ca ne fonctionne que pour les String si je ne me trompe pas.., si je veux faire la meme chose avec un long que serait la population par exemple, je devrai utiliser quoi ?

  4. #84
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par Sara_hda Voir le message
    Mais ca ne fonctionne que pour les String si je ne me trompe pas.., si je veux faire la meme chose avec un long que serait la population par exemple, je devrai utiliser quoi ?
    Forcément, equalsIgnoreCase servant à tester l'égalité sans prise en compte de la casse, une notion concernant des caractères, on ne peut pas l'appliquer à les long.
    Le problème avec les longs, c'est que si on fait une égalité pure, on risque d'avoir du mal à trouver des résultats. Genre si j'ai trois pays avec 12521245, 8454, 4589212 habitants et que je cherche 303215 habitants j'aurais 0 pays. Il faudrait vraiment avoir du bol ou connaître d'avance la population d'un pays pour avoir une réponse.
    Je dirais que pour gérer ce cas, il vaut mieux procéder par intervalle.

    Soit intervalle pur, je cherche entre telle et telle valeur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     
    public Country searchByPopulation(long min, long max) throws NoSuchElementException { 
     
    		Country result = null;
    		for (Country country: countries) {
    			if (min<=country.getPopulation() && country.getPopulation()<=max) {
    				result = country;
    				break;
    			}
    		}
    		if (result == null) {
    			throw new NoSuchElementException("No country found with population between " + min + " and " + max );
    		} else {
    			return result; 
     
    		}
    	}
    Toutefois cela pose un problème : on peut avoir plusieurs pays avec la même population, à fortiori, plusieurs pays dans le même intervalle. On peut modifier pour récupérer plusieurs pays :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     
    public Set<Country> searchByPopulation(long min, long max) throws NoSuchElementException { 
     
    		Set<Country> result = new HashSet<>();
     
    		for (Country country: countries) {
    			if (min<=country.getPopulation() && country.getPopulation()<=max) {
    				result.add(country);
    			}
    		}
    		if (result.isEmpty() {
    			throw new NoSuchElementException("No country found with population between " + min + " and " + max );
    		} else {
    			return Collections.unmodifiableSet(result); 
     
    		}
    	}


    Soit par tranche, soit fixes, genre intervalles de 10000, ou progressives, <10000, entre 10000 et 50000, entre 50000 et 250000, entre 250000 et 500000, etc.
    Pour le premier cas, il suffit de faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
    public Set<Country> searchByPopulation(long population) throws NoSuchElementException { 
     
                    int min = 10000*(population/10000);
                    int max = min+10000;
     
                    Set<Country> result = new HashSet<>();
     
    		for (Country country: countries) {
    			if (min<=country.getPopulation() && country.getPopulation()<max) {
    				result.add(country);
    			}
    		}
    		if (result.isEmpty() {
    			throw new NoSuchElementException("No country found with population in bracket [" + min + ", " + max+"[" );
    		} else {
    			return Collections.unmodifiableSet(result); 
     
    		}
    	}
    Ainsi quand on cherche un pays pour une tranche

    On peut même rendre la tranche paramétrable :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     
    public Set<Country> searchByPopulation(long population, int rangeWidth) throws NoSuchElementException { 
     
                    if ( rangeWidth<=0 ) throw new IllegalArgumentException("Incorrect value for range width");
     
                    int min = rangeWidth*(population/rangeWidth);
                    int max = min+rangeWidth;
     
                    Set<Country> result = new HashSet<>();
     
    		for (Country country: countries) {
    			if (min<=country.getPopulation() && country.getPopulation()<max) {
    				result.add(country);
    			}
    		}
    		if (result.isEmpty() {
    			throw new NoSuchElementException("No country found with population in range [" + min + ", " + max+"[" );
    		} else {
    			return Collections.unmodifiableSet(result); 
     
    		}
    	}
    pour des tranches de tailles progressives, il faudra faire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
    public Set<Country> searchByPopulation(long population) throws NoSuchElementException { 
     
                    Set<Country> result = new HashSet<>();
     
                    int min;
                    int max;
                    if ( population<10000 ) {
                        min=0;
                        max=10000;
                    }
                    else if ( population<50000 ) {
                        min=10000;
                        max=50000;
                    }
                    else if ( population < 250000 ) {
                        min=50000;
                        max=250000;
                    }
                    else {
                        min=250000;
                        max=Integer.MAX_VALUE;
                    }
     
    		for (Country country: countries) {
    			if (min<=country.getPopulation() && country.getPopulation()<max) {
    				result.add(country);
    			}
    		}
    		if (result.isEmpty() {
    			throw new NoSuchElementException("No country found with population in range [" + min + ", " + max+"[" );
    		} else {
    			return Collections.unmodifiableSet(result); 
     
    		}
    	}
    ou par boucle, ce qui permet de rendre paramétrable les tranches :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
    public Set<Country> searchByPopulation(long population, int...ranges) throws NoSuchElementException { 
     
                   // on vérifie que les tranches sont bien ordonnées
                   int[] sorted = Arrays.copyOf(ranges, ranges.length);
        Arrays.sort(sorted);
        if ( !Arrays.equals(sorted,ranges)) {
                throw new IllegalArgumentException();
        }
     
     
     
                    int min=0;
                    int max=Integer.MAX_VALUE; 
                    for(int i : ranges) {
                        if ( population < i ) { 
                             max=i;
                             break;
                        }
                        min=i;
                    }
     
                  Set<Country> result = new HashSet<>();
     
    		for (Country country: countries) {
    			if (min<=country.getPopulation() && country.getPopulation()<max) {
    				result.add(country);
    			}
    		}
    		if (result.isEmpty() {
    			throw new NoSuchElementException("No country found with population in range [" + min + ", " + max+"[" );
    		} else {
    			return Collections.unmodifiableSet(result); 
     
    		}
    	}
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

Discussions similaires

  1. [AC-2003] Requête pour remplir une table à partir d'un fichier Excel
    Par olivier777 dans le forum Requêtes et SQL.
    Réponses: 8
    Dernier message: 07/09/2009, 10h52
  2. remplir une combobox à partir d'un fichier .csv
    Par wolverine1987 dans le forum MFC
    Réponses: 24
    Dernier message: 28/04/2009, 11h00
  3. Tracer une courbe à partir d'un fichier .csv
    Par dzonaser dans le forum MATLAB
    Réponses: 2
    Dernier message: 25/10/2008, 14h48
  4. Réponses: 0
    Dernier message: 07/02/2008, 16h09
  5. Remplir une liste à partir d'un fichier texte
    Par leroidje dans le forum Langage
    Réponses: 1
    Dernier message: 01/07/2007, 08h41

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo