一. 前言:
小熙刚才输出打印快捷键的时候,看到有一个 printf 输出,好奇的试了下,发现和 print 输出结果是一样的,都是不换行。但是小熙知道肯定不会有两个完全一样的输出打印,所以又查了下,记录下。
二. printf介绍:
printf() 原本是 C 语言标准库函数,用于将格式化后的字符串输出到标准输出。
在java中 printf 还是打印, 但是继承了c语言的一些特性(格式化)
-
注意以下是对 printf 在 java 中使用的简化,如需查看更详细的信息,请查看c语言相关介绍。printf("需要格式化的字符串", 输出表列):
- 需要格式化的字符串的表达式为:
:%[flags][.precision]type
%[标志][.精度]类型
- 标识:
字符 名称 说明 - 减号 结果左对齐,右边填空格。默认是右对齐,左边填空格。 + 加号 输出符号(正号或负号) space 空格 输出值为正时加上空格,为负时加上负号 数字零 将输出的前面补上0,直到占满指定列宽为止(不可以搭配使用“-”) - 精度(.precision): 举例:
.precision 描述 .数值 十进制整数。
(1)对于整型precision不能表示,只能用标识中的0表示,不足补前导零,超过不截断。
(2)对于浮点型,precision表示小数点后数值位数,默认为六位,不足补后置0,超过则截断。
(3)对于类型说明符g或G,表示可输出的最大有效数字。
(4)对于字符串,precision表示最大可输出字符数,不足正常输出,超过则截断。
precision不显示指定,则默认为0
. 以星号代替数值,类似于width中的,在输出参数列表中指定精度。
结果:System.out.printf("%07d \n",1000); //不足指定宽度补前导0 System.out.printf("%.7f \n",1000.123456789);//超过精度,截断 System.out.printf("%.7f \n",1000.123456); //不足精度,补后置0 System.out.printf("%.7g \n",1000.123456); //一共的最大有效数字为8位 System.out.printf("%.7s \n","abcdefghij"); //超过指定长度截断
关于String(本篇的 printf 在 String 的 format方法中同样适用):0001000 1000.1234568 1000.1234560 1000.123 abcdefg
在 String 中的 format 方法中也是可以使用这里的精度的,如:String st = String.format("%.2f", 3.141592653); 因为这里是直接截取,所以不会四舍五入的,如需要请使用DecimalFormat等格式化。
- 类型(基本的):
"%d"是一个int值的占位符, "%f"是一个double 或float值的点位符(默认展示小数点后6位,你也可以通过[width](最小宽度)控制他的占位数,如%.2f是小数点后两位), "%s"是一个字符串值的点位符的意思, "%c"是一个字符值的点位符的意思
三. 代码:
- 例子:
/**
* print 和 printf的区别
* printf("需要格式化的字符串", 输出表列)
* 需要格式化的字符串的表达式为: %[flags][.precision]type
* %[标志][.精度]类型
*
* 此处在pringtf中的使用,在String.format中同样适用
*/
@Test
public void testPrint(){
int i = 6;
double j = 7;
char c = 'c';
String s = "小熙";
// 单纯的格式化输出,只是不换行而已
System.out.print("print输出,i:" + i);
System.out.println();
// printf继承了c语言的一些特性(格式化)
// 类型:
// "%d"是一个int值的占位符,
// "%f"是一个double 或float值的点位符(默认展示小数点后6位,你也可以通过[width](最小宽度)控制他的占位数,如%.2f是小数点后两位),
// "%s"是一个字符串值的点位符的意思,
// "%c"是一个字符值的点位符的意思。
System.out.printf("printf输出,i:%d, j: %.2f, x: %c, s: %s \r\n", i, j, c, s);
System.out.println(String.format("printf输出,i:%d, j: %.2f, x: %c, s: %s \r\n", i, j, c, s));
System.out.printf("i:%-10d \r\n", i);
System.out.printf("i:%#f", 1.00);
System.out.println("----------------------");
System.out.printf("%07d \n",1000); //不足指定宽度补前导0
System.out.printf("%.7f \n",1000.123456789);//超过精度,截断
System.out.printf("%.7f \n",1000.123456); //不足精度,补后置0
System.out.printf("%.7g \n",1000.123456); //最大有效数字为8位
System.out.printf("%.7s \n","abcdefghij"); //超过指定长度截断
}
- 结果
print输出,i:6
printf输出,i:6, j: 7.00, x: c, s: 小熙
printf输出,i:6, j: 7.00, x: c, s: 小熙
i:6
i:1.000000----------------------
0001000
1000.1234568
1000.1234560
1000.123
abcdefg
四. 关于 printf 缓冲:
在 printf 的实现中,在调用 write 之前先写入 IO 缓冲区,这是一个用户空间的缓冲。系统调用是软中断,频繁调用,需要频繁陷入内核态,这样的效率不是很高,而 printf 实际是向用户空间的 IO 缓冲写,在满足条件的情况下才会调用 write 系统调用,减少 IO 次数,提高效率。
printf(…) 在 glibc 中默认为行缓冲,遇到以下几种情况会刷新缓冲区,输出内容:
(1)缓冲区填满;
(2)写入的字符中有换行符\n或回车符\r;
(3)调用 fflush(…) 手动刷新缓冲区;
(4)调用 scanf(…) 从输入缓冲区中读取数据时,也会将输出缓冲区内的数据刷新。
可使用setbuf(stdout,NULL)关闭行缓冲,或者setbuf(stdout,uBuff)设置新的缓冲区,uBuff 为自己指定的缓冲区。也可以使用setvbuf(stdout,NULL,_IOFBF,0);来改变标准输出为全缓冲。全缓冲与行缓冲的区别在于遇到换行符不刷新缓冲区。
printf(…) 在 VC++ 中默认关闭缓冲区,输出时会及时输到屏幕 。如果显示开启缓冲区,只能设置全缓冲。因为微软闭源,所以无法研究 printf(…) 的实现源码。
五. 后语:
关于缓冲的部分是借鉴一些在C的描述,以上是小熙在 java 处的简单实践,如有更好的建议,也请您提出来。