Formatage des chaînes en Java

Online Coding Courses for Kids

introduction

Il existe plusieurs façons de formater les chaînes en Java. Certains sont de la vieille école et empruntés directement à d’anciens classiques (comme printf de C) tandis que d’autres sont plus dans l’esprit de la programmation orientée objet, comme le MessageFormat classe.

Dans cet article, nous passerons en revue plusieurs de ces approches. Nous allons montrer quelques détails sur la façon dont chacune des techniques peut être utilisée et dans quelles circonstances. En utilisant ces connaissances, vous saurez comment aborder le formatage des chaînes et laquelle des techniques utiliser.

System.out.printf ()

Commençons par l’ancien classique, printf(). Comme indiqué précédemment, printf() vient du langage de programmation C et signifie format imprimé. Sous la capuche, printf() les usages java.util.Formatter, dont nous parlerons plus tard.

Le chemin printf() les travaux peuvent être expliqués par ses arguments. La façon la plus courante d’utiliser printf() est comme suit:

System.out.printf(String format, String... arguments);

Nous pouvons voir que la méthode attend un format et un vararg arguments. le format L’argument définit la façon dont vous souhaitez que la chaîne soit formatée – un modèle pour le résultat final.

Par exemple, vous souhaiterez peut-être imprimer un nombre décimal avec exactement sept décimales ou un nombre en représentation hexadécimale. Ou, vous pouvez avoir un message prédéfini pour saluer les utilisateurs, mais vous souhaitez le formater pour inclure le nom d’utilisateur.

le arguments vararg attend commodément les arguments (c’est-à-dire les valeurs) pour le modèle String. Par exemple, si le modèle a des espaces réservés pour deux nombres, le printf() méthode attendra également deux nombres comme arguments:

System.out.printf("%d %d", 42, 23);

Nous avons mis deux %d symboles dans le modèle String. Ces deux symboles représentent des espaces réservés pour un certain type de valeur. Par exemple, le %d est un espace réservé pour une valeur numérique décimale. Puisque nous en avons deux, nous devons passer deux arguments qui correspondent à des valeurs numériques, telles que 42 et 23.

L’exécution de ce code donnera:

42 23

Spécificateurs de format

Avec printf(), vous pouvez imprimer des valeurs telles que des nombres, des chaînes, des dates, etc. Pour que la méthode sache exactement ce que vous essayez d’imprimer, vous devez fournir un spécificateur de format pour chacune des valeurs. Prenons un exemple:

System.out.printf("Hello, %s!", "reader");

S’il est exécuté, ce code sera imprimé Hello, reader à la console. le %s Le symbole représente un spécificateur de format pour les chaînes, semblable à la façon dont %d représente un spécificateur de format pour les nombres décimaux.

Il existe de nombreux spécificateurs de format que nous pouvons utiliser. Voici quelques exemples courants:

  • % c – Personnage
  • %ré – Nombre décimal (base 10)
  • % e – Nombre à virgule flottante exponentielle
  • %F – Nombre à virgule flottante
  • %je – Entier (base 10)
  • % o – Nombre octal (base 8)
  • % s – Chaîne
  • % u – Nombre décimal (entier) non signé
  • %X – Nombre hexadécimal (base 16)
  • % t – Date / heure
  • % n – Nouvelle ligne

Si nous voulons imprimer, par exemple, un caractère et un nombre octal, nous utiliserions %c et %o spécificateurs, respectivement. Vous remarquerez peut-être quelque chose d’inhabituel: le spécificateur de nouvelle ligne. Si vous n’êtes pas habitué printf()Le comportement de C, cela peut sembler un peu bizarre de devoir spécifier des choses comme ça.

Bien, printf() n’écrit pas de nouvelle ligne par défaut. En fait, il fait presque rien par défaut. Fondamentalement, si vous voulez que quelque chose se produise, vous devez le faire vous-même.

C’est-à-dire – si nous avons plusieurs printf() instructions sans spécificateur de nouvelle ligne:

System.out.printf("Hello, %s!", "Michael Scott");
System.out.printf("Hello, %s!", "Jim");
System.out.printf("Hello, %s!", "Dwight");

Le résultat serait:

Hello, Michael Scott!Hello, Jim!Hello, Dwight!

Cependant, si nous incluons le caractère de nouvelle ligne:

System.out.printf("Hello, %s!%n", "Michael Scott");
System.out.printf("Hello, %s!%n", "Jim");
System.out.printf("Hello, %s!%n", "Dwight");

Le résultat serait alors:

Hello, Michael Scott!
Hello, Jim!
Hello, Dwight!

Remarque: %n est un format spécial qui peut être rn ou juste n. n est le véritable symbole de nouvelle ligne, tandis que le r est le symbole de retour chariot. En règle générale, il est conseillé d’utiliser n car il fonctionne comme prévu sur tous les systèmes, contrairement à %n qui peut être compris comme l’un des deux. Plus d’informations à ce sujet plus tard.

Caractères d’échappement

En plus des spécificateurs de format décrits ci-dessus, il existe un autre type de symboles de formatage: Échapper aux personnages.

Imaginons que nous voulons imprimer un " symbole en utilisant printf(). Nous pouvons essayer quelque chose comme:

System.out.printf(""");

Si vous essayez d’exécuter ceci, votre compilateur lèvera certainement une exception. Si vous regardez attentivement, même le code qui met en évidence le code sur cette page mettra en évidence ); comme étant une chaîne et non le crochet fermé de la méthode.

Ce qui s’est passé, c’est que nous avons essayé d’imprimer un symbole qui a une signification particulière et réservée. Le guillemet est utilisé pour indiquer le début et la fin d’une chaîne.

Nous avons commencé et terminé une chaîne "", après quoi nous en avons ouvert un autre " mais je ne l’ai pas fermé. Cela rend l’impression de caractères réservés comme celui-ci impossible, en utilisant cette approche.

La façon de contourner cela est en s’échapper. Pour imprimer des caractères spéciaux (tels que "), nous devons d’abord échapper à ses effets, et en Java, cela signifie le préfixer avec une barre oblique inverse (). Pour imprimer légalement un guillemet en Java, nous procédons comme suit:

System.out.printf(""");

La combinaison de et " indique spécifiquement au compilateur que nous aimerions insérer le " caractère à cet endroit et qu’il devrait traiter la " comme une valeur concrète, pas un symbole réservé.

Appliquer le caractère d’échappement peut invoquer différents effets basés sur le suivant. Passer un caractère normal (non réservé) ne fera rien et sera traité comme une valeur.

Cependant, certaines combinaisons (également appelées commandes) ont une signification différente du compilateur:

  • b – Insérer un retour arrière
  • F – Le premier caractère de la ligne suivante commence à droite du dernier caractère de la ligne actuelle
  • n – Insérer une nouvelle ligne
  • r – Insérer le retour chariot
  • t – Onglet Insérer
  • \ – Insérer une barre oblique inverse
  • %% – Insérer un signe de pourcentage

Ainsi, vous utiliseriez n pour imprimer un séparateur de ligne sur la console, en commençant efficacement tout nouveau contenu depuis le début de la ligne suivante. De même, pour ajouter des onglets, vous utiliseriez le t spécificateur.

Vous avez peut-être remarqué %% comme dernière combinaison.

Pourquoi est-ce? Pourquoi % simplement utilisé?

le % le personnage est déjà un personnage d’échappement spécialement pour le printf() méthode. Suivi par des personnages comme d, i, f, etc., le formateur à l’exécution sait comment traiter ces valeurs.

le cependant, le caractère est destiné au compilateur. Il lui indique où et quoi insérer. le % la commande n’est tout simplement pas définie et nous utilisons la % caractère d’échappement pour échapper à l’effet de la suite % caractère – si cela a du sens.

Pour le compilateur, le % n’est pas un caractère spécial, mais est. De plus, il est courant que les caractères spéciaux s’échappent d’eux-mêmes. s’échappe et % s’échappe %.

Utilisation de base

Formater une chaîne avec plusieurs arguments de différents types:

System.out.printf("The quick brown %s jumps %d times over the lazy %s.n", "fox", 2, "dog");

La sortie sera:

The quick brown fox jumps 2 times over the lazy dog.

Flotteur et double précision

Avec printf(), nous pouvons définir une précision personnalisée pour les nombres à virgule flottante:

double a = 35.55845;
double b = 40.1245414;

System.out.printf("a = %.2f b = %.4f", a, b);

Depuis %f est utilisé pour les flotteurs, nous pouvons l’utiliser pour imprimer doubles. Cependant, en ajoutant un .n, où n est le nombre de décimales, nous pouvons définir une précision personnalisée.

L’exécution de ce code donne:

a = 35.56
b = 40.1245

Rembourrage de format

Nous pouvons également ajouter un remplissage, y compris la chaîne passée:

System.out.printf("%10sn", "stack");

Ici, après le % caractère, nous avons passé un nombre et un spécificateur de format. Plus précisément, nous voulons une chaîne avec 10 caractères, suivi d’une nouvelle ligne. Depuis stack ne contient que 5 caractères, 5 autres sont ajoutés en tant que remplissage pour “remplir” la chaîne vers la cible du personnage:

     stack

Vous pouvez également ajouter un remplissage à droite à la place:

System.out.printf("%-10sn", "stack");

Lieu

On peut aussi passer un Locale comme premier argument, formatant la chaîne en conséquence:

System.out.printf(Locale.US, "%,dn", 5000);
System.out.printf(Locale.ITALY, "%,dn", 5000);

Cela produirait deux entiers de format différent:

5,000
5.000

Index des arguments

Si aucun index d’argument n’est fourni, les arguments suivront simplement l’ordre de présence dans l’appel de méthode:

System.out.printf("First argument is %d, second argument is %d", 2, 1);

Il en résulterait:

First argument is 2, argument number is 1

Cependant, après % caractère d’échappement et avant le spécificateur de format, nous pouvons ajouter une autre commande. $n spécifiera l’index d’argument:

System.out.printf("First argument is %2$d, second argument is %1$d", 2, 1);

Ici, 2$ est situé entre % et d. 2$ précise que nous aimerions joindre le seconde argument de la liste des arguments cette spécificateur. De même, le 1$ spécifie que nous aimerions attacher le premier argument de la liste à l’autre spécificateur.

L’exécution de ce code entraîne:

First argument is 1, second argument is 2

Vous pouvez pointer les deux spécificateurs vers le même argument. Dans notre cas, cela signifierait que nous n’utilisons qu’un seul argument fourni dans la liste. C’est parfaitement bien – même si nous devons encore fournir tous les arguments présents dans le modèle String:

System.out.printf("First argument is %2$d, second argument is %2$d", 2, 1);

Cela se traduira par:

First argument is 1, second argument is 1

System.out.format ()

Avant de parler System.out.format(), concentrons-nous brièvement sur System.out.

Tous les systèmes UNIX ont trois tuyaux principaux – tuyau d’entrée standard (stdin), tuyau de sortie standard (stdout) et tube d’erreur standard (stderr). le out correspond au champ stdout tuyau et est de PrintStream type.

Cette classe possède de nombreuses méthodes différentes pour imprimer des représentations textuelles formatées dans un flux, dont certaines sont format() et printf().

Selon la documentation, ils se comportent tous deux exactement de la même manière. Cela signifie qu’il n’y a pas de différence entre les deux et peut être utilisé pour les mêmes résultats. Tout ce que nous avons dit jusqu’à présent printf() travaille aussi pour format().

Tous les deux printf() et System.out.format() imprimer sur le stdout pipe, qui vise généralement la console / le terminal.

String.format ()

Une autre façon de formater les chaînes est de String.format() méthode qui utilise également en interne java.util.Formatter, que nous explorerons dans la section suivante.

Le principal avantage de String.format() plus de printf() est son type de retour – il renvoie un String. Au lieu d’imprimer simplement le contenu sur le tuyau de sortie standard et de n’avoir aucun type de retour (void) comme printf() Est-ce que, String.format() est utilisé pour formater une chaîne pouvant être utilisée ou réutilisée à l’avenir:

String formattedString = String.format("Local time: %tT", Calendar.getInstance());

Vous pouvez maintenant faire tout ce que vous formattedString. Vous pouvez l’imprimer, vous pouvez l’enregistrer dans un fichier, vous pouvez le modifier ou le conserver dans une base de données. L’imprimer entraînerait:

Local time: 16:01:42

le String.format() utilise exactement le même principe sous-jacent que le printf() méthode. Les deux utilisent en interne le Formatter pour formater réellement les chaînes. Ainsi, tout a été dit pour printf() s’applique également au String.format() méthode.

En utilisant printf(), String.format() ou Formatter c’est essentiellement la même chose. La seule chose qui diffère est le type de retour – printf() imprime sur le flux de sortie standard (généralement votre console) et String.format() renvoie un formaté String.

Cela étant dit, String.format() est plus polyvalent car vous pouvez réellement utiliser le résultat de plusieurs manières.

La classe Formatter

Étant donné que toutes les méthodes ci-dessus appellent intrinsèquement la méthode Formatter, connaître un seul signifie que vous les connaissez tous.

L’utilisation de Formatter est assez similaire aux autres techniques présentées précédemment. La plus grande différence est que pour l’utiliser, il faut instancier un Formatter objet:

Formatter f = new Formatter();
f.format("There are %d planets in the Solar System. Sorry, Pluto", 8);
System.out.println(f);

Cela soulève la question:

Pourquoi n’utiliserais-je pas toujours les méthodes précédentes, car elles sont plus concises?

Il existe une autre distinction importante qui fait Formatter classe assez flexible:

StringBuilder sb = new StringBuilder();
Formatter formatter = new Formatter(sb);

formatter.format("%d, %d, %d...n", 1, 2, 3);

Au lieu de travailler uniquement avec Strings, Formatter peut également fonctionner avec StringBuilder ce qui permet de (ré) utiliser efficacement les deux classes.

En réalité, Formatter est capable de travailler avec n’importe quelle classe qui implémente le Appendable interface. Un tel exemple est le susmentionné StringBuilder, mais d’autres exemples incluent des classes telles que BufferedWriter, FileWriter, PrintStream, PrintWriter, StringBuffer, etc. La liste complète se trouve dans le Documentation.

Enfin, tous les spécificateurs de format, caractères d’échappement, etc. sont également valides pour le Formatter car il s’agit de la logique principale de formatage des chaînes dans les trois cas: String.format(), printf(), et Formatter.

MessageFormat

Enfin, montrons une technique de formatage finale qui n’utilise pas Formatter sous la capuche.

MessageFormat a été conçu pour produire et fournir des messages concaténés d’une manière indépendante de la langue. Cela signifie que le formatage sera le même, que vous utilisiez Java, Python ou un autre langage prenant en charge MessageFormat.

MessageFormat étend l’abstrait Format classe, juste comment DateFormat et NumberFormat faire. le Format La classe est destinée à formater des objets sensibles aux paramètres régionaux en chaînes.

Voyons un bel exemple, gracieuseté de MessageFormatc’est Documentation.

int planet = 7;
String event = "a disturbance in the Force";

String result = MessageFormat.format(
	"At {1, time} on {1, date}, there was {2} on planet {0, number, integer}.",
	planet, new Date(), event
);

Crédit de code: Oracle Docs

La sortie est:

At 11:52 PM on May 4, 2174, there was a disturbance in the Force on planet 7.

Au lieu des spécificateurs de pourcentage que nous avons vus jusqu’à présent, nous utilisons ici des accolades pour chacun des arguments. Prenons le premier argument, {1, time}. Le nombre 1 représente l’index de l’argument qui doit être utilisé à sa place. Dans notre cas, les arguments sont planet, new Date(), et event.

La seconde partie, time, fait référence au type de la valeur. Les types de format de niveau supérieur sont number, date, time, et choice. Pour chacune des valeurs, une sélection plus spécifique peut être effectuée, comme avec{0, number, integer} ce qui signifie que la valeur doit être traitée non seulement comme un nombre, mais aussi comme un entier.

L’ensemble complet des types et sous-types de format se trouve dans le Documentation.

Conclusion

Dans cet article, nous avons passé en revue un bon nombre de façons de formater les chaînes dans le noyau Java.

Chacune des techniques que nous avons montrées a sa propre raison d’être. printf(), par exemple, rappelle la méthode C du même nom à l’ancienne.

D’autres approches, telles que Formatter ou MessageFormat offrent une approche plus moderne qui exploite certains avantages de la programmation orientée objet.

Chaque technique a des cas d’utilisation spécifiques, alors j’espère que vous pourrez savoir quand les utiliser à l’avenir.

Close Menu