C# 字符串格式化大全
本文为译文,原文地址http://blog.stevex.net/string-formatting-in-csharp/,转载请注明来自本博客。
关于在.NET中字符串格式化的方法String.Format(),本人一直找不到一本合适的快速参考,故作此文。
自打本人学习.NET Framework起,心头一直纠结一件事。我找不到类似于C语言中的sprintf()的函数,它有一个输出缓冲,一个字符串的格式描述和一串参数,并且跟据这一切创建一串你需要的字符串。
例如:
char szError[256]; sprintf(szError, "Error %d occurred.\n", nError);
此句将生成一串“Error 12 occurred.” 到szError这个缓冲中(当然,前提是nError为12)。这是C语言编程的基础,甚至很多C++的程序员依然在使用这种方式,虽然在STL库中提供了更好的功能,但sprintf相对更加清晰而易于使用。
STL中同样的做法会是:
str << "Error " << nError << " occurred." << endl;
或者其它类似的方式。它虽然是类型安全的,而且比sprintf更面向对象,但比较难于阅读和本地化。
.NET framework很好地处理了字符串--但这需要适应,在.NET中与sprintf最相近的就是静态方法String.Format(),它需要一个格式字符串和一些参数,然后生成一个输出的字符串。(相对于sprintf最大的闪光点在于你再也不用担心覆盖了输出缓冲。)
例如:
string errorString = String.Format("Error {0} occurred.", nError);
由于元数据机制的存在,.NET环境不需要格式字符串中指明要格式化的类型,你只要指明位置就行。(最常见的sprintf的Bug就是提供了错误的数据类型,在你误把%s当%d使用的时候,一但sprintf被调用,你的程序就会挂掉,没有任何保护。)
在上面这个示例中,{0}将会被nError的值替换掉,但如果你想用指定的数值,或指定的进制(例如十六进制),.NET 都支持,但貌似这不是String.Format的功能,而是类型自己的功能。
任何对象都有一个叫ToString()的方法来返回对象的字符串表述形式。ToString()方法可以接收一个告诉对象怎么来格式化自己的字符串参数,而在String.Format()中,这个格式字符串是在占位符后面传递,例如:"{0:##}"。
花括号中的格式是这样的,{index[,alignment][:formatString]}。如果alignment是正数,文本在指定文本数的空间内右对齐;如果它是负数,则是左对齐。
字符串
抱歉的是,对字符串真的没什么可格式化的,只有对齐,而且对齐对所有调用String.Format()中的内容都有效。
示例 |
输出 |
String.Format("->{0,10}<-", "Hello"); | -> Hello<- |
String.Format("->{0,-10}<-", "Hello"); | ->Hello <- |
数值
内置的数值格式化主要包括如下内容:
识别符 |
类型 | 格式 | 输出(传值 Double 1.42) | 输出(传值 Int -12400) |
c |
Currency | {0:c} | $1.42 | -$12,400 |
d |
Decimal | {0:d} | System.FormatException | -12400 |
e |
Scientific | {0:e} | 1.420000e+000 | -1.240000e+004 |
f |
Fixed point | {0:f} | 1.42 | -12400.00 |
g |
General | {0:g} | 1.42 | -12400 |
n |
带千分号的Number | {0:n} | 1.42 | -12,400 |
r |
四舍五入 | {0:r} | 1.42 | System.FormatException |
x |
Hexadecimal | {0:x4} | System.FormatException | cf90 |
自定义数值格式化包括如下内容:
识别符 |
类型 |
格式 |
输出(传值 Double 1500.42) |
注意 |
0 |
0占位符 |
{0:00.0000} |
1500.4200 |
用0填充位置. |
# |
数字占位符 |
{0:(#).##} |
(1500).42 |
|
. |
小数点占位符 |
{0:0.0} |
1500.4 |
|
, |
千分号 |
{0:0,0} |
1,500 |
必须在两个0中间 |
,. |
数值缩放 |
{0:0,.} |
2 |
缩小1000倍(整除) |
% |
百分号 |
{0:0%} |
150042% |
乘上100再加个% |
e |
指数占位符 |
{0:00e+0} |
15e+2 |
允许多种指数格式 |
; |
分组占位符 |
见文末示例 |
分组占位符在处理货币型数据的时候非常有用,它可以用不同的格式显示负值或0,具体示例请看文末。
日期
请注意日期的格式化依赖于计算机的地区设置;示例为本人的地区设置下的结果
识别符 |
类型 |
输出(传值 10/12/2002 10:11:29) |
d | 短日期 | 10/12/2002 |
D | 长日期 | December 10, 2002 |
t | 短时间 | 10:11 PM |
T | 长时间 | 10:11:29 PM |
f | 完整日期和时间 | December 10, 2002 10:11 PM |
F | 完整日期和时间(长) | December 10, 2002 10:11:29 PM |
g | 默认日期和时间 | 10/12/2002 10:11 PM |
G | 默认日期和时间(长) | 10/12/2002 10:11:29 PM |
M | 月和日 | December 10 |
r | RFC1123 日期时间 | Tue, 10 Dec 2002 22:11:29 GMT |
s | 可排序的日期时间 | 2002-12-10T22:11:29 |
u | 通用可排序本地日期时间 | 2002-12-10 22:11:29Z |
U | 通用可排序格林威治标准时间 | December 10, 2002 10:11:29 PM |
Y | 年和月 | December, 2002 |
U 识别符貌似有问题,输出的字符串没有排序的意义。
自定义日期时间格式化(以2002-12-10 10:11:29.932 PM为示例):
识别符 |
类型 |
示例 |
输出 |
dd | 天 | {0:dd} | 10 |
ddd | 周 | {0:ddd} | Tue |
dddd | 完整周名 | {0:dddd} | Tuesday |
f, ff, … | 秒的小数部分 | {0:fff} | 932 |
gg, … | 纪元 | {0:gg} | A.D. |
hh | 2位数小时 | {0:hh} | 10 |
HH | 2位数小时,24小时格式 | {0:HH} | 22 |
mm | 分 | {0:mm} | 11 |
MM | 月 | {0:MM} | 12 |
MMM | 短月名 | {0:MMM} | Dec |
MMMM | 长月名 | {0:MMMM} | December |
ss | 秒 | {0:ss} | 29 |
tt | 上下午 | {0:tt} | PM |
yy | 年,2位数 | {0:yy} | 02 |
yyyy | 年 | {0:yyyy} | 2002 |
zz | 时区 | {0:zz} | -05:00 |
zzz | 完整时区 | {0:zzz} | -05:00 |
: | 分隔符 | {0:hh:mm:ss} | 10:11:29 |
/ | 分隔符 | {0:dd/MM/yyyy} | 10/12/2002 |
枚举
识别符 |
类型 |
g |
可以的话就显示名称,否则显示数值 |
f |
显示名称 |
d |
显示数值 |
x |
八位十六进制 |
一些有用示例
String.Format("{0:$#,###.00;¥#,###.00;零蛋}", value);
当传值1234.50的时候,输出是$1,234.50,当传值-1234.50的时候,输出是¥1,234.50,当传值0或-0的时候,输出是“零蛋” ,很显然,这很像C#中的三元表达式。
String.Format(“{0:(###) ###-####}”, 8005551212);
输出是 “(800) 555-1212″。