2
votes

Convertir un fichier .txt avec des doubles en ArrayList

J'ai un fichier .txt avec ce contenu: "17.23;12.1;20.34;88.23523;" . Je veux lire ce fichier en double dans une ArrayList . Et finalement imprimer la ArrayList (et finalement imprimer le min.et le max., Mais je ne pense pas que ce sera un problème après avoir résolu cela).

Mais je n'obtiens que la sortie "[]".

Qu'est-ce que je fais mal? Je me débat avec cela depuis plus de 15 heures embarrassantes, parcouru ici, youtube, des livres de cours ...

Mon code:

public static void main(String[] args) throws IOException {
      File myFile = new File("text.txt");
      Scanner scan = new Scanner(myFile);

      ArrayList<Double> aList = new ArrayList<>();
      
      while (scan.hasNextDouble()) {  
          double nextInput = scan.nextDouble();
          if (nextInput != 0) {
              break;  
          }  
        
          aList.add(nextInput);
      }

      System.out.println(alist);
}


3 commentaires

if (nextInput != 0) break; pourquoi avez-vous besoin de cette ligne? À cause d'eux, votre code n'est jamais censé ajouter quelque chose à une arrayList compte tenu de votre entrée


Puisque votre fichier a des nombres séparés par un point-virgule, vous ne pourrez pas les lire en utilisant scan.hasNextDouble() par défaut. Cependant, il y a tellement de façons de le faire, par exemple en lisant une ligne sous forme de chaîne et en traitant chaque nombre à partir de celle-ci après l'avoir divisée sur le point-virgule. Une autre façon est de remplacer le délimiteur par défaut, etc.


Vous avez raison nkrivenko. Oui @Arvind Kumar Avinash, je vais vérifier toutes les suggestions.


4 Réponses :


0
votes

Puisque votre fichier a des nombres séparés par un point-virgule, vous ne pourrez pas les lire en utilisant scan.hasNextDouble() par défaut. Cependant, il y a tellement de façons de le faire, par exemple

  1. Remplacez le délimiteur par défaut.
  2. Lire une ligne sous forme de chaîne et traiter chaque nombre à partir de celle-ci après l'avoir fractionnée sur le point-virgule.

Option 1:

import java.io.File;
import java.io.FileNotFoundException;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) throws FileNotFoundException, ParseException {
        File myFile = new File("file.txt");
        Scanner scan = new Scanner(myFile);
        NumberFormat format = NumberFormat.getInstance(Locale.FRANCE);
        List<Double> aList = new ArrayList<>();
        while (scan.hasNextLine()) {
            String nextInput = scan.nextLine();
            String[] arr = nextInput.split(";");
            for (String s : arr) {
                aList.add(format.parse(s).doubleValue());
            }
        }
        System.out.println(aList);
    }
}

Notez que puisque votre fichier a la virgule au lieu du point comme symbole décimal, vous pouvez utiliser un Locale dans lequel il s'agit de la valeur par défaut.

[17.23, 12.1, 20.34, 88.23523]

En outre, le bloc de code suivant dans votre code entraînera la fin de la boucle après la lecture du premier nombre lui-même car le premier nombre de votre fichier n'est pas égal à zéro. Supprimez simplement ces lignes pour obtenir le résultat souhaité:

import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) throws FileNotFoundException {
        File myFile = new File("file.txt");
        Scanner scan = new Scanner(myFile);

        List<Double> aList = new ArrayList<>();
        while (scan.hasNextLine()) {
            String nextInput = scan.nextLine();
            String[] arr = nextInput.split(";");
            for (String s : arr) {
                aList.add(Double.valueOf(s.replace(",", ".")));
            }
        }
        System.out.println(aList);
    }
}

Option 2:

Lisez une ligne, divisez-la sur un point-virgule, remplacez la virgule par un point, analysez chaque élément du tableau résultant en Double et stockez-le dans aList .

Démo:

if (nextInput != 0) {
    break;  
}

Production:

scan.useLocale(Locale.FRANCE);

Une alternative pour remplacer la virgule par un point consiste à utiliser NumberFormat comme indiqué ci-dessous:

scan.useDelimiter(";")


1 commentaires

Tant de réponses utiles, j'ai essayé les premières démos et modifié les données pour que je comprenne. Grand merci!



2
votes

Vous devez configurer votre scanner pour qu'il accepte:

  1. ; comme délimiteur
  2. , comme séparateur décimal

Le code de travail est:

File myFile = new File("input.txt");

// Swedish locale uses ',' as a decimal separator
Scanner scan = new Scanner(myFile).useDelimiter(";").useLocale(Locale.forLanguageTag("sv-SE"));

ArrayList<Double> aList = new ArrayList<>();

while (scan.hasNextDouble()) {
    double nextInput = scan.nextDouble();
    aList.add(nextInput);
}

System.out.println(aList);

Avec sortie [17.23, 12.1, 20.34, 88.23523]


3 commentaires

Grande réponse, +1 de moi, même si je crois que le « Uppgift » mot dans le nom de fichier est le suédois et la Suède utilise - t , ainsi, changeant ainsi Locale.FRENCH à Locale.forLanguageTag("sv-SE") serait probablement plus précis pour la question. Même résultat, bien sûr.


Oui, bien sûr, le français n'est qu'un exemple (la locale "ru-RU" fonctionne aussi)


Un grand merci pour la réponse. Je vais vérifier cela aussi !!



0
votes

Vous pouvez le faire simplement en changeant le délimiteur. Cela fonctionne en lisant à partir d'une chaîne, mais vous pouvez également le faire à partir d'un fichier. C'est à vous de mettre les valeurs dans une structure de données. Cela suppose que vos paramètres régionaux par défaut utilisent «,» comme point décimal.

17.23
12.1
20.34
88.23523

impressions

String str = "17,23;12,1;20,34;88,23523;";

Scanner scan = new Scanner(str);
scan.useDelimiter("[;]+");
while(scan.hasNextDouble()) {
    System.out.println(scan.nextDouble());
}


4 commentaires

La virgule est un séparateur décimal dans la question de OP, pas un séparateur de nombres


Il est peu probable que les deux , et ; sont des séparateurs de valeurs. Il est beaucoup plus probable que ; est le séparateur de valeur et que , est un point décimal spécifique aux paramètres régionaux, d'autant plus que le mot "Uppgift" dans le nom de fichier est suédois et que la Suède utilise , comme point décimal.


Eh bien, le PO n'a pas précisé cela dans la question (mais cela a du sens), alors je l'ai mis en garde dans ma réponse. Merci à vous deux!


Salut, Andreas a raison. J'ai maintenant changé cela pour la norme plus internationale! Un grand merci pour les réponses!



1
votes

Scanner fonctionne en divisant l'entrée en jetons, où les jetons sont séparés par des espaces (par défaut). Puisqu'il n'y a pas d'espaces blancs dans le texte, le premier / seul jeton est le texte entier, et puisque ce texte n'est pas une valeur double valide, hasNextDouble() renvoie false .

Deux façons de résoudre ce problème:

  • Remplacez le séparateur de jetons par ; :

    String filename = "text.txt";
    try (BufferedReader in = Files.newBufferedReader(Paths.get(filename))) {
        NumberFormat format = NumberFormat.getInstance(Locale.forLanguageTag("sv-SE"));
        
        for (String line; (line = in.readLine()) != null; ) {
            List<Double> aList = new ArrayList<>();
            
            for (String token : line.split(";")) {
                double value = format.parse(token).doubleValue();
                aList.add(value);
            }
            
            System.out.println(aList); // Prints: [17.23, 12.1, 20.34, 88.23523]
        }
    }
    
  • Lisez le fichier avec BufferedReader et utilisez split() :

    String filename = "text.txt";
    try (BufferedReader in = Files.newBufferedReader(Paths.get(filename))) {
        for (String line; (line = in.readLine()) != null; ) {
            String[] tokens = line.split(";");
            // code here
        }
    }
    

Cela donnera désormais les jetons suivants: 17,23 , 12,1 , 20,34 , 88,23523 .

Malheureusement, aucun de ceux qui sont valides double valeurs, car ils utilisent le formatage spécifique locale, à savoir le point décimal est un , et non un . .

Ce qui signifie que si vous continuez à utiliser Scanner , vous ne pouvez pas utiliser hasNextDouble() et nextDouble() , et si vous avez changé pour utiliser split() , vous ne pouvez pas utiliser Double.parseDouble() .

Vous devez utiliser un NumberFormat pour analyser les formats numériques spécifiques aux paramètres régionaux. Puisque "Uppgift" a l'air suédois, nous pouvons utiliser NumberFormat.getInstance(Locale.forLanguageTag("sv-SE")) , ou simplement NumberFormat.getInstance() si votre locale par défaut est la Suède.

scan.useDelimiter(";");


1 commentaires

Un grand merci (tacle :)) Andreas! J'essaierai également votre suggestion.