Я пытаюсь напечатать некоторую информацию по столбцам. Все работает с латинскими символами, но когда печатаются китайские символы, столбцы перестают выравниваться. Рассмотрим пример:
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);
Вывод:
some text | 23
some longer text | 23
.................................................
一些文字 | 23
一些較長的文字 | 23
Как видно, китайский не выровнен по столбцам. Важное примечание: это просто представление проблемы; он не будет использоваться в консольном приложении. Кто-нибудь может мне с этим помочь?
@CSharpie - Я проверил это, и похоже, что китайские иероглифы не нормализованы. Нельзя предположить, что 1 китайский символ = 2 латинских символа.
вот почему я сказал, что вам нужно выяснить, для каких символов это правда
@artsch как будет использоваться текст? Консольная поддержка в Windows была очень плохой до релизов последний для инсайдеров Windows 10. До недавнего времени вам приходилось явно настраивать окно консоли для отображения Unicode. Протестируйте свой код в стеке презентаций, который вы собираетесь использовать (ASP.NET, WPF, Winforms), и используйте функции их для выравнивания текста. Скорее всего, у вас не возникнет проблем
@artsch Проверьте Командная строка Windows: текстовый буфер вывода Unicode и UTF-8, чтобы узнать, почему в консоли такой беспорядок, и что делается, чтобы это исправить. Статья опубликована в ноябре 2018 г.
@PanagiotisKanavos - он будет отправлен на принтер в виде обычного текста. Но не стандартный, это будет принтер чеков.
@artsch это плохо. В этом случае вы делать должны иметь дело с ограничениями - другого уровня представления нет. Размер каждого глифа зависит от используемого шрифта. PadRight ничего не знает о шрифтах, только о символах. Размер каждого глифа будет зависеть от шрифтов принтер. MeasureText может помочь, если вы найдете такой же или эквивалентный шрифт в Windows.
@artsch, с другой стороны, в консоли Windows отсутствуют управляющие команды, используемые для разметки текста. POS-принтеры обычно поддерживают команды ESC / POS, и одна из них используется установить горизонтальные позиции табуляции, как и Word. Вместо заполнения вы можете установить позиции табуляции один раз, а затем использовать табуляции в каждой текстовой строке, чтобы текст отображался там, где вы хотите.





Я попробовал приведенный ниже код, так как у меня нет поддержки китайского языка, я не могу его протестировать.
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));
Это не работает -> Это в основном тот же код. Все, что вы сделали, это вместо этого использовали string.Format, которая делает то же самое внутри.
Вы можете использовать метод TextRenderer.MeasureText из сборки System.Windows.Forms для построения выходного текста на основе ширины строки, а не количества символов.
Вот метод утилиты:
public static string FillWithSpaces(this string text, int width, Font font)
{
while (TextRenderer.MeasureText(text, font).Width < width)
{
text += ' ';
}
return text;
}
И использование:
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;
Решение требует использования параметра заполнения (в пикселях) и шрифта.
Это не идеально, но похоже, что идеального решения для этого случая не существует. Подойдет, спасибо.
Я могу представить только одно общее решение с заполнением. Вы должны использовать моноширинный шрифт, и все символы обоих алфавитов должны быть одного размера. Фактически функция PaddingRight просто добавляет заданное количество символов в строку. Но отображаемый размер строки также зависит от шрифта. Если вы используете моноширинный шрифт, он будет работать, в других случаях даже для латинских символов - нет. На мой взгляд, лучше решать проблему для каждого конкретного вывода, который вы собираетесь использовать, потому что строка itsefl ничего не знает о том, как она будет отображаться, и более того, она не должна знать об этом.
Эти китайские символы имеют ширину 2. Если бы можно было выяснить, для каких именно символов это верно, вы могли бы написать собственный PadRight-Method, который учитывает это, если не будет лучшего решения.