C# .NET 6.0如何实现字符串左/右/居中对齐写入文本文件
.NET 6.0 定长文本字段对齐实现
问题说明
- 基于.NET 6.0开发文本文件导出功能,要求所有字段为固定长度,需支持左对齐、右对齐、居中对齐三种格式化规则,格式化完成后将字符串流写入文本文件
- 原实现通过手动给字符串尾部补空格凑长度的方式处理,无法实现
amountTag右对齐、interfaceTag居中对齐的效果,输出列错位
原问题代码如下:
public static void JustifyTxt() { try { string batchIdHeader = "BatchId "; string interfaceHeader = "Interface "; string voucherTypeHeader = "VoucherType "; string amountHeader = "Amount "; string voucherNoHeader = "VoucherNo "; string batchIdTag = "AIMGL07_220428 "; string interfaceTag = "XA "; string voucherTypeTag = "GL "; string amountTag = "1000 "; string voucherNoTag = "123238 "; Console.WriteLine("-------------------------------------------------------------------------------------------------------------"); Console.WriteLine($"{batchIdHeader}|{interfaceHeader}|{voucherTypeHeader}|{amountHeader}|{voucherNoHeader}"); Console.WriteLine("-------------------------------------------------------------------------------------------------------------"); var formatedTag = String.Format("{0,0}{1,0}{2,0}{3,3}{4,0} ", batchIdTag, interfaceTag,voucherTypeTag,amountTag,voucherNoHeader); Console.WriteLine(formatedTag); } catch (Exception ex) { Console.WriteLine(ex); } }
参考居中实现逻辑如下:
public static void JustifyTxtCentre() { string tag = "AIMGL07_220428"; int tagLen = tag.Length; int tagMaxWidth = 25; int tagLenDifference = tagMaxWidth - tag.Length; int totalPaddingToAdd = tagLenDifference > 0? tagLenDifference : checked(-tagLenDifference); int distributePaddings = totalPaddingToAdd / 2; int leftPaddings = distributePaddings; int rightPaddings = distributePaddings; var processedTag = new string(' ', leftPaddings) + tag + new string(' ', rightPaddings); if(processedTag.Length == (tagMaxWidth - 1)) { processedTag = processedTag + new string(' ', 1); } }
问题根因
- 传入格式化方法的所有字符串本身已经提前拼接了多余尾部空格,导致对齐计算的基准长度完全错误
- 对
String.Format对齐语法使用错误:{索引, 对齐值}语法中,正数值代表右对齐、负数值代表左对齐,数值为字段总长度,该方法原生不支持居中对齐,需要单独实现 - 原居中对齐参考实现未处理字符串长度超过固定宽度的截断场景,边界逻辑不完善
修复方案
第一步:实现通用定长对齐辅助方法
封装统一的对齐处理逻辑,支持三种对齐方式,自动处理补空格、超长截断逻辑,固定输出长度严格符合要求:
/// <summary> /// 定长字符串对齐处理 /// </summary> /// <param name="source">原始字符串</param> /// <param name="totalWidth">字段固定总长度</param> /// <param name="alignment">对齐方式:Left左对齐/Right右对齐/Center居中</param> /// <returns>固定长度的格式化字符串</returns> public static string FormatFixedWidth(string source, int totalWidth, StringAlignment alignment) { // 空值处理 source = source?.Trim() ?? string.Empty; // 超长时直接截断,保证总长度符合要求 if (source.Length >= totalWidth) return source.Substring(0, totalWidth); int paddingTotal = totalWidth - source.Length; return alignment switch { StringAlignment.Left => source + new string(' ', paddingTotal), StringAlignment.Right => new string(' ', paddingTotal) + source, StringAlignment.Center => new string(' ', paddingTotal / 2) + source + new string(' ', paddingTotal - paddingTotal / 2), _ => source + new string(' ', paddingTotal) }; }
注:
StringAlignment是System.Drawing命名空间下的枚举,若不想引用该命名空间,可以自定义枚举或者用整数/字符串参数指定对齐方式。
第二步:修正业务格式化逻辑
移除原代码中手动给字符串补的空格,传入原始业务值调用统一方法格式化,保证每个字段长度和表头完全匹配:
public static void JustifyTxt() { try { // 表头直接通过格式化方法生成,保证长度统一 string batchIdHeader = FormatFixedWidth("BatchId", 25, StringAlignment.Left); string interfaceHeader = FormatFixedWidth("Interface", 25, StringAlignment.Left); string voucherTypeHeader = FormatFixedWidth("VoucherType", 25, StringAlignment.Left); string amountHeader = FormatFixedWidth("Amount", 18, StringAlignment.Left); string voucherNoHeader = FormatFixedWidth("VoucherNo", 15, StringAlignment.Left); // 业务值按要求对齐:BatchId左对齐、Interface居中、VoucherType左对齐、Amount右对齐、VoucherNo左对齐 string batchIdTag = FormatFixedWidth("AIMGL07_220428", 25, StringAlignment.Left); string interfaceTag = FormatFixedWidth("XA", 25, StringAlignment.Center); string voucherTypeTag = FormatFixedWidth("GL", 25, StringAlignment.Left); string amountTag = FormatFixedWidth("1000", 18, StringAlignment.Right); string voucherNoTag = FormatFixedWidth("123238", 15, StringAlignment.Left); // 输出分隔线长度和表头总长度匹配 int splitLength = 25 + 25 + 25 + 18 + 15 + 4; // 加4是分隔符|的总长度 Console.WriteLine(new string('-', splitLength)); Console.WriteLine($"{batchIdHeader}|{interfaceHeader}|{voucherTypeHeader}|{amountHeader}|{voucherNoHeader}"); Console.WriteLine(new string('-', splitLength)); var formatedTag = $"{batchIdTag}|{interfaceTag}|{voucherTypeTag}|{amountTag}|{voucherNoTag}"; Console.WriteLine(formatedTag); // 后续直接将formatedTag写入文本文件即可,所有字段长度固定、对齐符合要求 } catch (Exception ex) { Console.WriteLine(ex); } }
效果说明
- 所有字段严格保持预设固定长度,不会出现列错位问题
- 对齐规则完全符合需求:金额类字段
amountTag自动补前导空格实现右对齐,interfaceTag自动在两侧补空格实现居中,其余字段左对齐 - 自动处理空值、超长值场景,输出文本完全符合定长文件的格式要求,可直接传入StreamWriter生成目标文本文件。
内容的提问来源于stack exchange,提问作者K.Z
相关产品推荐
相关产品推荐

