web-dev-qa-db-fra.com

quel est Java équivalent de sscanf pour analyser les valeurs d'une chaîne en utilisant un modèle connu?

Je viens donc d'un arrière-plan C (à l'origine à l'origine, même si je n'ai pas utilisé ce langage depuis près de 5 ans) et j'essaie d'analyser certaines valeurs d'une chaîne en Java. En C, j'utiliserais sscanf. Dans Java les gens m'ont dit "utilisez Scanner ou StringTokenizer", mais je ne vois pas comment les utiliser pour atteindre mon objectif.

Ma chaîne d'entrée ressemble à "17-MAR-11 15.52.25.000000000". En C, je ferais quelque chose comme:

sscanf(thestring, "%d-%s-%d %d.%d.%d.%d", day, month, year, hour, min, sec, fracpart);

Mais en Java, tout ce que je peux faire, c'est des choses comme:

scanner.nextInt();

Cela ne me permet pas de vérifier le modèle, et pour "MAR", je dois faire des choses comme:

str.substring(3,6);

Horrible! Il y a sûrement une meilleure façon?

29
Kidburla

Le problème est Java n'a pas de paramètres (ou passe par référence) en C ou C #.

Mais il existe un meilleur moyen (et plus solide). Utilisez des expressions régulières:

Pattern p = Pattern.compile("(\\d+)-(\\p{Alpha}+)-(\\d+) (\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)")
Matcher m = p.matcher("17-MAR-11 15.52.25.000000000");
day = m.group(1);
month= m.group(2);
....

Bien sûr, le code C est plus concis, mais cette technique a un avantage: Patterns spécifie un format plus précis que '% s' et '% d'. Vous pouvez donc utiliser\d {2} pour spécifier que le jour DOIT être composé d'exactement 2 chiffres.

39
korifey

Voici une solution utilisant des scanners:

Scanner scanner = new Scanner("17-MAR-11 15.52.25.000000000");

Scanner dayScanner = new Scanner(scanner.next());
Scanner timeScanner = new Scanner(scanner.next());

dayScanner.useDelimiter("-");
System.out.println("day=" + dayScanner.nextInt());
System.out.println("month=" + dayScanner.next());
System.out.println("year=" + dayScanner.nextInt());

timeScanner.useDelimiter("\\.");
System.out.println("hour=" + timeScanner.nextInt());
System.out.println("min=" + timeScanner.nextInt());
System.out.println("sec=" + timeScanner.nextInt());
System.out.println("fracpart=" + timeScanner.nextInt());
22
dsboger

Aucun de ces exemples ne m'a vraiment satisfait, j'ai donc créé mon propre Java utilitaire sscanf:

https://github.com/driedler/Java-sscanf/tree/master/src/util/sscanf

Voici un exemple d'analyse d'une chaîne hexadécimale:

String buffer = "my hex string: DEADBEEF\n"
Object output[] = Sscanf.scan(buffer, "my hex string: %X\n", 1);

System.out.println("parse count: " + output.length);
System.out.println("hex str1: " + (Long)output[0]);

// Output:
// parse count: 1
// hex str1: 3735928559
11
user1495323

Pour "17-MAR-11 15.52.25.000000000":

SimpleDateFormat format = new SimpleDateFormat("dd-MMM-yy HH.mm.ss.SSS");

try 
{
    Date parsed = format.parse(dateString);
    System.out.println(parsed.toString());
}
catch (ParseException pe)
{
    System.out.println("ERROR: Cannot parse \"" + dateString + "\"");
}
3
DefenestrationDay

C'est loin d'être une solution aussi élégante que l'on obtiendrait avec l'utilisation de regex, mais cela devrait fonctionner.

public static void stringStuffThing(){
String x = "17-MAR-11 15.52.25.000000000";
String y[] = x.split(" ");

for(String s : y){
    System.out.println(s);
}
String date[] = y[0].split("-");
String values[] = y[1].split("\\.");

for(String s : date){
    System.out.println(s);
}
for(String s : values){
    System.out.println(s);
}
2
Zavior

Connaissez-vous le concept des expressions régulières? Java vous offre la possibilité d'utiliser l'expression régulière en utilisant la classe Pattern. Consultez celle-ci: http://docs.Oracle.com/javase/8/docs/api /Java/util/regex/Pattern.html

Vous pouvez tester votre chaîne comme ça:

Matcher matcher = Pattern.match(yourString);
matcher.find();

puis utilisez les méthodes fournies par Matcher pour manipuler la chaîne que vous avez trouvée ou NON.

0
Nikola Yovchev