天天看点

java中的print和printf的区别

一. 前言:

小熙刚才输出打印快捷键的时候,看到有一个 printf 输出,好奇的试了下,发现和 print 输出结果是一样的,都是不换行。但是小熙知道肯定不会有两个完全一样的输出打印,所以又查了下,记录下。

二. printf介绍:

printf() 原本是 C 语言标准库函数,用于将格式化后的字符串输出到标准输出。

在java中 printf 还是打印, 但是继承了c语言的一些特性(格式化)

  1. printf("需要格式化的字符串", 输出表列):

    注意以下是对 printf 在 java 中使用的简化,如需查看更详细的信息,请查看c语言相关介绍。
  2. 需要格式化的字符串的表达式为:

    %[flags][.precision]type

    :

    %[标志][.精度]类型

  3. 标识:
    字符 名称 说明
    - 减号 结果左对齐,右边填空格。默认是右对齐,左边填空格。
    + 加号 输出符号(正号或负号)
    space 空格 输出值为正时加上空格,为负时加上负号
    数字零 将输出的前面补上0,直到占满指定列宽为止(不可以搭配使用“-”)
  4. 精度(.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");	//超过指定长度截断
               
    结果:
    0001000 
         1000.1234568 
         1000.1234560 
         1000.123 
          abcdefg 
               
    关于String(本篇的 printf 在 String 的 format方法中同样适用):
    在 String 中的 format 方法中也是可以使用这里的精度的,如:String st = String.format("%.2f", 3.141592653);
        因为这里是直接截取,所以不会四舍五入的,如需要请使用DecimalFormat等格式化。
               
  5. 类型(基本的):
    "%d"是一个int值的占位符,
       "%f"是一个double 或float值的点位符(默认展示小数点后6位,你也可以通过[width](最小宽度)控制他的占位数,如%.2f是小数点后两位),
       "%s"是一个字符串值的点位符的意思,
       "%c"是一个字符值的点位符的意思
               

三. 代码:

  1. 例子:
/**
     * 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");	//超过指定长度截断

    }
           
  1. 结果
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 处的简单实践,如有更好的建议,也请您提出来。