7
votes

Comment formater les caractères chinois pour qu'ils s'adaptent aux colonnes?

J'essaye d'imprimer certaines informations d'une manière orientée colonnes. Tout fonctionne bien pour les caractères latins, mais lorsque les caractères chinois sont imprimés, les colonnes cessent d'être alignées. Prenons un exemple:

some text                     | 23
some longer text              | 23
.................................................
一些文字                           | 23
一些較長的文字                       | 23

Sortie:

var latinPresentation1 = "some text".PadRight(30) + "| " + 23;
var latinPresentation2 = "some longer text".PadRight(30) + "| " + 23;

Console.WriteLine(latinPresentation1);
Console.WriteLine(latinPresentation2);

Console.WriteLine("..............................................");

var chinesePresentation1 = "一些文字".PadRight(30) + " | " + 23;
var chinesePresentation2 = "一些較長的文字".PadRight(30) + "| " + 23;

Console.WriteLine(chinesePresentation1);
Console.WriteLine(chinesePresentation2);

Comme on peut le voir, le chinois n'est pas aligné sur les colonnes. Remarque importante: il ne s'agit que d'une présentation du problème; il ne sera pas utilisé dans une application console. Quelqu'un peut-il m'aider?


8 commentaires

Ces caractères chinois ont une largeur de 2. Si l'on pouvait trouver, pour quels caractères exactement cela est vrai, vous pouvez écrire une méthode PadRight personnalisée qui prend cela en compte, si aucune meilleure solution ne se présente.


@CSharpie - J'ai fait des tests à ce sujet, et il semble que les caractères chinois ne sont pas normalisés. On ne peut pas supposer que 1 caractère chinois = 2 caractère latin.


c'est pourquoi j'ai dit que tu devais découvrir, pour quels caractères c'est vrai


@artsch comment le texte sera-t-il utilisé? La prise en charge de la console sous Windows était très mauvaise jusqu'aux dernières versions d'initiés de Windows 10. Jusqu'à récemment, vous deviez configurer explicitement une fenêtre de console pour afficher Unicode. Testez votre code dans la pile de présentation que vous souhaitez utiliser (ASP.NET, WPF, Winforms) et utilisez leurs fonctionnalités pour aligner le texte. Il y a de fortes chances que vous ne rencontriez pas de problèmes


@artsch Check Ligne de commande Windows: Tampon de texte de sortie Unicode et UTF-8 pour voir pourquoi la console est en désordre et ce qui est fait pour résoudre ce problème. L'article a été publié en novembre 2018


@PanagiotisKanavos - il sera envoyé sous forme de texte brut à l'imprimante. Mais pas en standard, ce sera une imprimante de reçus.


@artsch c'est mauvais. Dans ce cas, vous devez faire gérer les limitations - il n'y a pas d'autre couche de présentation. La taille de chaque glyphe dépend de la police utilisée. PadRight ne sait rien sur les polices, seulement les caractères. La taille de chaque glyphe dépendra des polices de l'imprimante . MeasureText peut vous aider si vous pouvez trouver la même police ou une police équivalente sous Windows.


@artsch d'autre part, ce qui manque sur la console Windows, ce sont les commandes d'échappement utilisées pour mettre en page le texte. Les imprimantes PDV prennent généralement en charge les commandes ESC / POS et l'un d'eux est utilisé pour définir des positions de tabulation horizontales , tout comme Word. Au lieu d'un remplissage, vous pouvez définir les positions des tabulations une fois, puis utiliser des tabulations dans chaque ligne de texte pour vous assurer que le texte apparaît là où vous le souhaitez


3 Réponses :


-1
votes

J'ai essayé le code ci-dessous, car je n'ai pas de support chinois, je ne peux pas le tester.

var latinPresentation1 = "some text" ;
var latinPresentation2 = "some longer text";

Console.WriteLine(String.Format("{0,-30} {1,-10} ", latinPresentation1, "| " + 23));
Console.WriteLine(String.Format("{0,-30} {1,-10} ", latinPresentation2, "| " + 23));

Console.WriteLine("..............................................");

var chinesePresentation1 = "一些文字";
var chinesePresentation2 = "一些較長的文字";

Console.WriteLine(String.Format("{0,-30} {1,-10} ", chinesePresentation1, "| " + 23));
Console.WriteLine(String.Format("{0,-30} {1,-10} ", chinesePresentation2, "| " + 23));


1 commentaires

Cela ne fonctionne pas -> C'est fondamentalement le même code. Tout ce que vous avez fait était d'utiliser string.Format à la place, qui fait la même chose sous le capot.



3
votes

Vous pouvez utiliser le TextRenderer.MeasureText de l'assembly System.Windows.Forms pour créer le texte de sortie en fonction de la largeur de la chaîne, au lieu du nombre de caractères.

Voici la méthode util:

var font = new Font("Courier New", 10.0F);
var padding = 340;

var latinPresentation1 = "some text ".FillWithSpaces(padding, font) + "| 23";
var latinPresentation2 = "some longer text".FillWithSpaces(padding, font) + "| 23";

var chinesePresentation1 = "一些文字".FillWithSpaces(padding, font) + "| 23";
var chinesePresentation2 = "一些較長的文字".FillWithSpaces(padding, font) + "| 23";

var result = latinPresentation1 + Environment.NewLine +
             latinPresentation2 + Environment.NewLine +
             ".............................................." + Environment.NewLine +
             chinesePresentation1 + Environment.NewLine +
             chinesePresentation2; 

Et l'utilisation:

public static string FillWithSpaces(this string text, int width, Font font)
{
    while (TextRenderer.MeasureText(text, font).Width < width)
    {
        text += ' ';
    }
    return text;
}

La solution nécessite le paramètre de remplissage (en px) et la police utilisée.


1 commentaires

Ce n'est pas idéal, mais il semble que la solution idéale pour ce cas n'existe pas. Cela fera l'affaire, merci.



0
votes

Je ne peux imaginer qu'une seule solution générique avec remplissage. Vous devez utiliser une police monospace et tous les symboles des deux alphabets doivent être de la même taille. En fait, la fonction PaddingRight ajoute simplement la quantité de symboles fournie à la chaîne. Mais la taille affichée de la chaîne dépend également de la police. Si vous utilisez une police monospace, cela fonctionnera, dans d'autres cas, même pour les symboles latins, cela ne fonctionnera pas. À mon avis, il est préférable de résoudre le problème pour chaque sortie particulière que vous allez utiliser, car la chaîne itsefl ne sait rien de la façon dont elle sera rendue et plus que cela, elle ne devrait pas en être conscient.


0 commentaires