##################################################
目录
标准输出流 System.out.printf() 与格式输出
read ( byte[] b, int off, int len )
##################################################
调用 Java Scanner API 输入接口
——————————
什么是 Java API
API/Application Programming Interface/应用程序编程接口
是一些预先定义的接口
目的是提供应用程序与开发人员基于某软件或硬件的以访问一组例程的能力
而又无需访问源码或理解内部工作机制的细节
实际上 API 就是别人写好的代码
这些代码能实现一定的功能
你如果想用别人的代码去实现你想要实现的功能
不需要自己再写代码,只需要去调用就可以了
这个 API 可以是 某个函数、某个类、某个对象
运行 Java 程序时,虚拟机装载程序的 class 文件所使用的 Java API class 文件
所有被装载的 class文件
包括从应用程序中和从 Java API 中提取的
和所有已经装载的动态库
包含本地方法
共同组成了在 Java 虚拟机上运行的整个程序
在一个平台能够支持 Java 程序以前,必须在这个特定平台上明确地实现 API 的功能
为访问主机上的本地资源 Java API 调用了本地方法
由于 Java API class 文件调用了本地方法 Java 程序就不需要再调用她们了
通过这种方法 Java API class 文件为底层主机提供了具有
平台无关性
标准接口
的 Java 程序
对 Java 程序而言,无论平台内部如何 Java API 都会有同样的表现和可预测的行为
正是由于在每个特定的主机平台上明确地实现了 Java 虚拟机和 Java API
因此 Java 程序自身就能够成为具有平台无关性的程序
Java API 在 Java 安全性模型方面也有贡献
当 Java API 的方法进行任何有潜在危险的操作
比如进行本地磁盘写操作
之前都会通过查询访问控制器来检验是否得到了授权!
访问控制器是一个类,该类用来执行栈检验,以决定是否允许某种操作
使用 API 前,我们都需要去导包
一般我们不需要自己手动导包
因为你如果使用开发工具比如 IDEA 或者 eclipse 开发工具会自动帮我们导包
——————————
导入 Scanner 依赖包/依赖类
在 Java 中可以实现从控制台进行输入的方法有很多种
在开发中 最常用的却是 Scanner 类
java.util.Scanner 是 Java 5 的新特征
首先 我们需要导入 java.util 包:
import java.util.*;
或者仅仅导入 Scanner 类:
import java.util.Scanner;
当使用的类不是定义在基本 java.lang 包中时
一定要使用 import 关键字将相应的包加载进来
Scanner 类定义在 java.util 包中
——————————
Scanner 控制台输入原理
导包语法:
import 包名.类名;
JDK 1.5 后就引入了类
java.util.Scanner
使用她可以处理控制台不同数据类型的输入
之后就可以使用该类的构造方法,创建一个该类的对象:
数据类型 变量名 = new 数据类型(参数列表);
System.in 是标准的输入
我们在创建 Scanner 对象时 需要与 标准输入流 关联 就构造一个 System.in 对象:
Scanner in = new Scanner(System.in);
使用她获取用户输入
关于对象的概念 以后就会明白了
接着我们就可以调用该类的成员方法,完成指定的功能:
对象名.方法名();
——————————
Scanner 常用 API
java.util.Scanner 类可以处理控制台输入的不同数据类型的数据!
这些都是非静态方法
只能通过类对象访问 如果尝试使用类名称访问该方法会报错
字符串有关的方法:
next() 读取输入的字符 遇到 空白符/空格/回车 结束输入 接收类型为 String 字符串型
nextLine() 读取输入的字符串 遇到回车结束输入 接收类型为 String 字符串型
hasNext() 读取并判断你是否有输入字符 有输入返回 true 没有输入例如只输入空格则返回 false 接收类型为 boolean 布尔值类型
整数有关的函数:
nextInt() 读取并转换整数的字符序列 遇到空白符结束输入 接收类型为 int 整型
hasNextInt() 读取并判断你是否有输入整数 有输入返回 true 没有输入返回 false 接收类型为 boolean 布尔值
nextLong() 读取并转换长整型的字符序列 遇到空白符结束输入 接收类型为 long 长整型
hasNextLong() 只有输入的数是长整型是才返回真值 其她情况返回假 接收类型为 long
布尔值有关的方法:
nextBoolean() 读取并转换布尔型的数据 遇到空白符结束输入 接收类型为 boolean 布尔值
hasNextBoolean() 读取并判断你输入的是否是 true 或 false 有输入返回 true 没有输入返回 false 接收类型为布尔值
浮点数有关的方法:
nextFloat() 读取并转换浮点数的字符序列 遇到空白符结束输入 接收类型为 float 浮点数类型
hasNextfloat() 读取并判断你输入的是否为单精度浮点数 有输入返回 true 没有输入返回 false 接收类型为 boolean 布尔值
nextDouble() 读取并转换成双精度浮点数的字符序列 遇到空白符结束输入 接收类型为 double 双精度浮点型
hasNextDouble() 读取并判断你是否有输入双浮点数 有输入返回 true 没有输入返回 false 接收类型为 boolean 布尔值
——————————
一段代码测试常用 Scanner 接口中的函数
如下测试了可能用到的 10 个方法:
next() 输入单词
hasNext() 测试输入是否是单词
nextLine() 输入行
hasNextLine() 测试输入是否为行
nextInt() 接收转换整型
hasNextInt() 测试输入是否为整型
nextDouble() 接收转换双浮点型
hasNextDouble() 测试输入是否为双浮点型
nextBoolean() 接收转换布尔型
hasNextDouble() 测试输入是否为布尔型
Print.java code:
package ip;
import java.util.Scanner;
public class Print {
public static void main(String[] args) {
Scanner sc = new Scanner ( System.in );
System.out.println( "##### 注意事项 #####" );
System.out.println( "<<< 表示录入" );
System.out.println( ">>> 表示输出" );
System.out.println( "录入数据按回车" );
System.out.println( "退格键可用" );
/* String next() */
System.out.println ( "\n—————————— String next() ——————————" );
System.out.print ( "1.请输入字符串 遇到空格结束录入\n<<< " );
String str_1 = sc.next();
System.out.println ( ">>> " + str_1 );
/* 接收流中的剩余内容但是不赋值 本代码仅解释这一次 不然流中剩余的数据会自动填充下一次 Scanner 接收 */
sc.nextLine();
System.out.print ( "2.输入一个字符串 <<< " );
if ( sc.hasNext() )
System.out.println ( ">>> true" );
else
System.out.println ( ">>> false" );
sc.nextLine();
System.out.print ( "3.输入一个字符串也会报假 <<< " );
if ( ! sc.hasNext() )
/* 实在不知道怎么才能返回 false 干脆取反 */
System.out.println ( ">>> true" );
else
System.out.println ( ">>> false" );
sc.nextLine();
/* String nextLine() */
System.out.println ( "\n—————————— String nextLine() ——————————" );
System.out.print ( "1.请输入字符串 遇到空格不会结束录入\n<<< " );
String str_2 = sc.nextLine();
System.out.println ( ">>> " + str_2 );
System.out.print ( "2.输入一个字符串 <<< " );
if ( sc.hasNextLine() )
System.out.println ( ">>> true" );
else
System.out.println ( ">>> false" );
sc.nextLine();
System.out.print ( "3.输入什么都会 false <<< " );
if ( ! sc.hasNextLine() )
System.out.println ( ">>> true" );
else
System.out.println ( ">>> false" );
sc.nextLine();
/* int nextInt() */
System.out.println ( "\n—————————— int nextInt() ——————————" );
System.out.print ( "1.请输入 数字 输入字母会崩溃\n<<< " );
int int_1 = sc.nextInt();
sc.nextLine();
System.out.println ( ">>> " + int_1 );
System.out.print ( "2.输入一个数字 <<< " );
if ( sc.hasNextInt() )
System.out.println ( ">>> true" );
else
System.out.println ( ">>> false" );
sc.nextLine();
System.out.print ( "3.输入一个字母 <<< " );
if ( sc.hasNextInt() )
System.out.println ( ">>> true" );
else
System.out.println ( ">>> false" );
sc.nextLine();
/* Double nextDouble() */
System.out.println ( "\n—————————— Double nextDouble() ——————————" );
System.out.print ( "1.请输入 一个小数\n<<< " );
double double_1 = sc.nextDouble();
sc.nextLine();
System.out.println ( ">>> " + double_1 );
System.out.print ( "2.输入一个小数 <<< " );
if ( sc.hasNextDouble() )
System.out.println ( ">>> true" );
else
System.out.println ( ">>> false" );
sc.nextLine();
System.out.print ( "3.输入一个整数 <<< " );
if ( sc.hasNextDouble() )
System.out.println ( ">>> true" );
else
System.out.println ( ">>> false" );
sc.nextLine();
/* boolean nextBoolean() */
System.out.println ( "\n—————————— boolean nextBoolean() ——————————" );
System.out.print ( "1.请输入布尔值\n<<< " );
boolean bool_1 = sc.nextBoolean();
System.out.println ( ">>> " + bool_1 );
System.out.print ( "2.请输入布尔值\n<<< " );
bool_1 = sc.nextBoolean();
System.out.println ( ">>> " + bool_1 );
System.out.print ( "3.输入真值 <<< " );
if ( sc.hasNextBoolean() )
System.out.println ( ">>> true" );
else
System.out.println ( ">>> false" );
sc.nextBoolean();
System.out.print ( "4.输入假值 <<< " );
if ( sc.hasNextBoolean() )
System.out.println ( ">>> true" );
else
System.out.println ( ">>> false" );
sc.nextBoolean();
System.out.print ( "5.输入数字 <<< " );
if ( sc.hasNextBoolean() )
System.out.println ( ">>> true" );
else
System.out.println ( ">>> false" );
sc.nextInt();
System.out.print ( "6.输入小数 <<< " );
if ( sc.hasNextBoolean() )
System.out.println ( ">>> true" );
else
System.out.println ( ">>> false" );
sc.nextDouble();
System.out.print ( "7.输入字母 <<< " );
if ( sc.hasNextBoolean() )
System.out.println ( ">>> true" );
else
System.out.println ( ">>> false" );
}
}
MyEclipase Demo:
##### 注意事项 #####
<<< 表示录入
>>> 表示输出
录入数据按回车
退格键可用
—————————— String next() ——————————
1.请输入字符串 遇到空格结束录入
<<< a b c 1 2 3
>>> a
2.输入一个字符串 <<< 123 345
>>> true
3.输入一个字符串也会报假 <<< 123 345
>>> false
—————————— String nextLine() ——————————
1.请输入字符串 遇到空格不会结束录入
<<< qwe 123 ,./
>>> qwe 123 ,./
2.输入一个字符串 <<< 123 123
>>> true
3.输入什么都会 false <<< 123 awe
>>> false
—————————— int nextInt() ——————————
1.请输入 数字 输入字母会崩溃
<<< 5211314
>>> 5211314
2.输入一个数字 <<< 5211314
>>> true
3.输入一个字母 <<< a
>>> false
—————————— Double nextDouble() ——————————
1.请输入 一个小数
<<< 3.1415926
>>> 3.1415926
2.输入一个小数 <<< 3.1415926
>>> true
3.输入一个整数 <<< 3\n
>>> false
—————————— boolean nextBoolean() ——————————
1.请输入布尔值
<<< true
>>> true
2.请输入布尔值
<<< false
>>> false
3.输入真值 <<< true
>>> true
4.输入假值 <<< false
>>> true
5.输入数字 <<< 1
>>> false
6.输入小数 <<< 5.2
>>> false
7.输入字母 <<< A
>>> false
##################################################
Scanner 输入类方法的搭配使用
——————————
缓冲区问题
%%%%%
如何清除上一次剩余的缓冲区后再读取下一次输入
nextInt() 在缓冲区中遇到空格或回车符等空白字符时
会将空白字符前的数据读取走 但空白符不会被处理掉 依然留在缓冲区中!
nextLine 方法在缓冲区中读取一行数据 这行数据以回车符为结束标志
nextLine 会把包括回车符在内的数据全部提走 缓冲区不会有回车符残留
因此使用时要注意 尽量不要在 nextInt() 后接 nextLine()
因为 nextLine() 会读取到回车符 而不是用户输入的内容
正确的使用方式:
nextInt();
nextLine() /* 在使用 nextLine 方法之前先将缓冲区中的回车符读取掉 */
nextLine();
其她方法也或多或少会有一些这方面的问题
只需要在前面再来一次相应的读取读走缓冲区中剩余的内容即可!
%%%%%
输入与判断输入的交叉搭配使用
hasNextLine() 和 nextLine() 搭配使用:
import java.util.*;
public class test {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int num = 0;
System.out.print ( "<<< " );
while ( sc.hasNextLine() ) {
System.out.println ( ">>> [" + sc.next() + "]" );
num ++;
if ( num >= 5 )
break;
}
}
}
因为设置了条件 所以只循环读取 5 次:
C:\Users\byme\javaTest>javac test.java
C:\Users\byme\javaTest>java test
<<< qwer123 456re wq1
>>> [qwer123]
>>> [456re]
>>> [wq1]
123 345 567
>>> [123]
>>> [345]
C:\Users\byme\javaTest>
如果输出一行的字符串用空格隔开 则空格后的内容会被换行
持续循环 hasNextLine() 返回 true
读取缓存中的内容 直到读完
hasNext() 和 nextLine() 搭配使用
import java.util.*;
public class test {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int num = 0;
System.out.print ( "<<< " );
while ( sc.hasNext() ) {
System.out.println ( ">>> [" + sc.nextLine() + "]" );
num ++;
if ( num >= 5 )
break;
}
}
}
如果输入一个空格
hasNext() 检测空格不会匹配
而 hasNextLine() 会匹配
后面接着输入一个有效字符串,就会连着前面输入的空格一起输出
字符串中间包含空格时不会被换行:
C:\Users\byme\javaTest>javac test.java
C:\Users\byme\javaTest>java test
<<< qwer123 456re wq1
>>> [qwer123 456re wq1]
23eru893fh f4098wufw 'f[p4-[7fg4g
>>> [23eru893fh f4098wufw 'f[p4-[7fg4g]
mf4powfiw34tf04w-tgf4gf4t[w-gfw
>>> [mf4powfiw34tf04w-tgf4gf4t[w-gfw]
12-40=234;3[.][32;4 ;]45;4= ;.4]5[4p3
>>> [12-40=234;3[.][32;4 ;]45;4= ;.4]5[4p3]
`39-120-49''4'5'43'5'345345
>>> [`39-120-49''4'5'43'5'345345]
C:\Users\byme\javaTest>
——————————
使用 nextLine () 搭配 for 循环录入数据
使用 nextLine() 获取从控制台输入字符串
通过循环不停接收 直到达到最大次数跳出循环
test.java code:
import java.util.*; /* 导入 java.util 下所有包 */
public class test {
public static void main ( String[] args ) {
Scanner scan = new Scanner ( System.in ) ; /* 初始化 scan 对象 */
String line;
int index = 1; /* 循环次数 */
while ( true ) {
/* 如果返回结果不为假就永远循环 */
System.out.printf ( "请输入第 " + index +" 个字符串 <<< " ); /* 交互信息 */
line = scan.nextLine(); /* 使用 nextLine() 接收 存入字符串变量 line */
System.out.println ( "\tline >>> [" + line + "]" ); /* 交互信息 输出 line */
index++; /* 循环次数 +1 */
if ( index >= 11 ) { /* 限制程序循环 10 次 */
break; /* 跳出循环 结束程序 */
}
}
}
}
cmd demo:
C:\Users\byme\javaTest>javac test.java
C:\Users\byme\javaTest>java test
请输入第 1 个字符串 <<< 1
line >>> [1]
请输入第 2 个字符串 <<< a
line >>> [a]
请输入第 3 个字符串 <<< 123
line >>> [123]
请输入第 4 个字符串 <<< abc
line >>> [abc]
请输入第 5 个字符串 <<< 123 abc
line >>> [123 abc]
请输入第 6 个字符串 <<< 我喜欢你
line >>> [我喜欢你]
请输入第 7 个字符串 <<< 我也喜欢你!
line >>> [我也喜欢你!]
请输入第 8 个字符串 <<< 我好喜欢你鸭~
line >>> [我好喜欢你鸭~]
请输入第 9 个字符串 <<< 我才不喜欢你
line >>> [我才不喜欢你]
请输入第 10 个字符串 <<< 沃达死你
line >>> [沃达死你]
C:\Users\byme\javaTest>
——————————
测试录入不同类型的数据
测试录入数据类型:
boolean
int
String
long
test.java code:
import java.util.*;
public class test {
public static void main(String[] args) {
Scanner come = new Scanner(System.in);
System.out.printf("请输入一个布尔值(true/false):");
if(come.nextBoolean()){
System.out.println("true 真");
}else{
System.out.println("false 假");
}
System.out.printf("请输入一个数字:");
come.nextInt();
System.out.printf("请输入一个字符串:");
come.next();
System.out.printf("请输入一个长整形:");
come.nextLong();
}
}
cmd demo:
C:\Users\byme\javaTest>javac test.java
C:\Users\byme\javaTest>java test
请输入一个布尔值 (true/false) <<< false
false 假
请输入一个数字 <<< 5211314
请输入一个字符串 <<< 沃达死你
请输入一个长整形 <<< 10000000
C:\Users\byme\javaTest>
——————————
检测输入的字符串内容以进行判断
从控制台动态输入数据 对数据进行各种各样的处理 然后将数据输出是很常见的操作
例如 写一个小程序 输入的字符串 遇到 ok 就退出程序
code:
import java.util.*;
public class test {
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
System.out.print ( "请输入字符串 <<< " );
while (true) {
String line = s.nextLine();
if ( line.equals( "ok" ) ) {
/* 注意判断字符串包含字符这里不能用等号而用 equals */
break;
}
System.out.println ( ">>> [" + line + "]");
}
}
}
cmd demo:
C:\Users\byme\javaTest>java test
请输入字符串 <<< 啊啊啊啊
>>> [啊啊啊啊]
啊啊啊啊啊
>>> [啊啊啊啊啊]
啊啊啊啊啊啊啊啊啊啊
>>> [啊啊啊啊啊啊啊啊啊啊]
啊啊啊啊啊ok啊啊啊
>>> [啊啊啊啊啊ok啊啊啊]
ok
C:\Users\byme\javaTest>
单独输入 ok 被检测到 结束循环
next() 一定要读取到有效字符后才可以结束输入
对输入有效字符之前遇到的
空格键
Tab键
Enter键
等结束符 next 方法会自动将其去掉 只有在输入有效字符之后 next() 才将其后输入的
空格键
Tab键
Enter键
等视为分隔符或结束符
next 碰到 空格 换行 都结束输入
nextLine 只以 回车 才会结束输入
简单地说 next() 查找并返回来自此扫描器的下一个完整标记
完整标记的前后是与分隔模式匹配的输入信息
所以 next 方法不能得到带空格的字符串
而 nextLine() 的结束符只是 Enter 键
即 nextLine() 返回的是 Enter 键之前的所有字符!她是可以得到带空格的字符串的!
——————————
如何输入单个字符
既然
整型 in.nextInt();
单精度浮点型 in.nextFloat();
双精度浮点型 in.nextDouble();
字符串类型 in.next();/in.nextLine();
那么 你会不会以为 char 类型也如
in.nextChar();
这样呢?。。。。那一定会报错的。。
输入字符串用 next/nextLine 方法
而 Scanner 的对象中并没有现成的关于 char 类型的方法
所有要先用字符串类型的 next 方法获取输入的字符串
然后用 charAt() 这个方法获取指定下标位置的字符
test.java code:
import java.util.*;
public class test {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.printf ( "请输入一个字符串 <<< " );
char c = in.next().charAt(0);
System.out.printf ( "第一个字符为 >>> " + c );
System.out.println ( "\n" );
System.out.printf ( "请输入一个字符串 <<< " );
String str = in.next();
c = str.charAt(0); /* 字符串数组下标从 0 开始 */
System.out.printf ( "第一个字符为 >>> " + c );
System.out.println ( "\n" );
System.out.printf ( "请输入一个字符串 <<< " );
str = in.next();
c = str.charAt(4); /* 字符串数组下标从 0 开始 所以第 5 位置就是 5-1 */
System.out.printf ( "第 5 个字符为 >>> " + c );
}
}
cmd demo:
C:\Users\byme\javaTest>javac test.java
C:\Users\byme\javaTest>java test
请输入一个字符串 <<< qwer123
第一个字符为 >>> q
请输入一个字符串 <<< qwer123
第一个字符为 >>> q
请输入一个字符串 <<< qwer123
第 3 个字符为 >>> 1
C:\Users\byme\javaTest>
有时候需要我们用 Scanner 接收 char 而不是接收 String
例如 使用 switch() 选择方式时 就不能用 String 了
switch 中文是 开关/转换 的意思
switch 条件语句特别适合做一组变量相等的判断switch 表达式的类型只能为 byte、short、char 和 int 这 4 种之一
JDK 7 以后 switch() 中的表达式可以为字符串了!
但是以前真的不支持 那是 java 7 以后的新特性
当我们正常使用 Scanner 时接收字符时可以这样转换一下:
Scanner in = new Scanner(System.in);
char c = in.next().charAt(0);
下面是示例模拟计算器的程序:
import java.util.*;
public class test {
public static void main(String[] args){
Scanner in = new Scanner(System.in);
System.out.print("请输入操作数 1 <<< ");
int a = in.nextInt();
System.out.print("请输入操作数 2 <<< ");
int b = in.nextInt();
System.out.print("请输入运算符 <<< ");
char c = in.next().charAt(0);
switch ( c ) {
case '+':
System.out.print ( "结果为 >>> " );
System.out.printf ( "[%d]\n", a + b );
break;
case '-':
System.out.print ( "结果 >>> " );
System.out.printf ( "[%d]\n", a - b );
break;
case '*':
System.out.print ( "结果 >>> " );
System.out.printf ( "[%d]\n", a * b );
break;
case '/':
if ( b != 0 ) {
System.out.print ( "结果 >>> " );
System.out.printf ( "[%d]\n", a / b );
}
break;
}
}
}
模拟的计算器程序还有模有样的:
C:\Users\byme\javaTest>javac test.java
C:\Users\byme\javaTest>java test
请输入操作数 1 <<< 20
请输入操作数 2 <<< 30
请输入运算符 <<< -
结果 >>> [-10]
C:\Users\byme\javaTest>
##################################################
System 的标准输入输出
——————————
Java 常用类 System 是什么类
System 是系统类
位于 jdk 中的 lang 包下
System 类中的构造器有 private 修饰所以不允许被实例化
此类中的方法都是 static 修饰的 所以也可以很方便的进行调用
常用成员变量有
in 标准输入流/键盘输入
out 标准输出流/显示器输出
err 标准错误输入出流/显示器输出
系统级的很多属性和控制方法都放置在该类的内部
常用成员方法为:
native long currentTimeMillis()
该方法的作用是返回当前的计算机时间
时间的表达格式为当前计算机时间和 GMT 时间/格林威治时间 1970 年 1 月 1 号 0 时 0 分 0 秒所差的毫秒数
void exit(int status)
该方法的作用是退出程序
其中 status 的值为 0 代表正常退出 非零代表异常退出
使用该方法可以在图形界面编程中实现程序的退出功能等
例如 System.exit(0) 表示正常退出
void gc()
该方法的作用是请求系统进行垃圾回收
至于系统是否立刻回收,则取决于系统中垃圾回收算法的实现以及系统执行时的情况
多线程并行,所以在当前线程调用 gc() 只能请求 gc 线程的启用,但能不能立即启动,得看线程的调度情况
String getProperty(String key):
该方法的作用是获得系统中属性名为 key 的属性对应的值
系统中常见的属性名以及属性的作用如下
java.version Java 运行时环境版本
java.home Java 安装目录
os.name 操作系统的名称
os.version 操作系统的版本
user.name 用户的账户名称
user.home 用户的主目录
user.dir 用户的当前工作目录
——————————
标准输出流 System.out.printf() 与格式输出
最常见的标准输出你一定不陌生:
System.out.println();
请看如下代码:
public class test {
public static void main(String[] args) {
double a = 10.0 / 3.0;
System.out.println ( a );
}
}
运行结果为:
C:\Users\byme\javaTest>javac test.java
C:\Users\byme\javaTest>java test
3.3333333333333335
C:\Users\byme\javaTest>
如果输出的值表示的是货币的多少,那么太多的小数点位数就显得很不方便了
庆幸的是 Java SE 5.0 沿用了 C 语言库函数中的 printf 方法
例如, 调用
System.out.printf ( "%8.2f", c );
其可以用 8 个字符的宽度和小数点后两个字符的精度打印输出
也就是说 打印输出一个空格和 7 个字符
code:
public class test {
public static void main(String[] args) {
double a = 10.0 / 3.0;
System.out.println ( a );
System.out.printf ( "%8.2f", a );
}
}
demo:
C:\Users\byme\javaTest>javac test.java
C:\Users\byme\javaTest>java test
3.3333333333333335
3.33
C:\Users\byme\javaTest>
在 printf 中,每一个以 % 字符开始的格式说明符都用相应的参数替换:
转义符 类型 例子
d 十进制整数 521
x 十六进制整数 3f
e 八进制整数 137
f 定点浮点数 16.8
e 指数浮点数 16.8e+01
g 通用浮点数
a 十六进制浮点数 0x4.fccdp2
s 字符串 你好
c 字符 A
b 布尔变量 True 或 Flase
h 散列码 42628b2
tx/Tx 日期时间 已经过时 应该改为使用 java.time 类
% 百分号
n 与平台有关的行分隔符
还可以给出控制格式化输出的各种标志
例如逗号标志增加了分组的分隔符:
public class test {
public static void main(String[] args) {
double a = 10.0 / 3.0;
System.out.println ( a );
System.out.printf ( "%8.2f", a );
a = 10000.0 / 3.0;
System.out.printf ( "\n%,.2f", a );
}
}
demo:
C:\Users\byme\javaTest>javac test.java
C:\Users\byme\javaTest>java test
3.3333333333333335
3.33
3,333.33
C:\Users\byme\javaTest>
用于 printf() 的标志:
标志 解释
+ 打印正数和负数的符号
空格 在正数之前添加空格
0 数字前面补 0
- 左对齐
( 将负数括在括号内
, 添加分组分隔符
# 对于 f 格式包含小数点 对于 x 或 0 格式添加前缀 0x 或 0
$ 給定被格式化的参数索引 例如 %1$d, %1$x 将以十进制和十六进制格式打印第 1 个参数
< 格式化前面说明的数值 例如 %d%<x 以十进制和十六进制打印同一个数值
还可以使用 s 转换符格式化任意的对象
对于实现了 Formattable 接口的任意对象 将调用这个对象的 formatTo 方法
否则调用 toString 方法将这个对象转换为字符串
使用 String.format() 方法可创建一个格式化的字符串,而不打印输出
API:
public static String format(String format, Object... args)
public static String format(Locale l, String format, Object... args)
参数和 printf() 中的含义相同
String message = String.format ( "姓名 %s 年龄 %d", name, age );
——————————
认识输入流 System.in
System.in.read() 返回一个整型字节数据
该数据表示的是字节因此是 Unicode 的第一个字节或是字符的 ASCII 码值
该方法是从一个流中一个一个的读取数据,因此是一个迭代的过程
我们可以看出 in 是一个静态的流,因此在该程序中只有一个流!
重复调用 System.in.read() 实际上是在遍历该流中的每一个字节数据
最常见的流是键盘输入流
我们可以在键盘中输入一个字符串 其中按下的回车键代表了两个字符
\r\n
\r 的 ASCII 码值是 10
\n 是 13
我们可以重复调用 System.in.read() 这个方法来读取从键盘输入的字符串中的字符所代表的
字节/ASCII 值
%%%%%
read()
read() 从输入流中读取数据的下一个字节
返回 0 到 255 范围内的 int 字节值
如果因为已经到达流末尾而没有可用的字节 则返回值 -1
%%%%%
read ( byte[] b )
从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中
以整数形式返回实际读取的字节数
如果 b 的长度为 0 则不读取任何字节并返回 0
否则 则尝试读取至少一个字节
如果因为流位于文件末尾而没有可用的字节,则返回值 -1
否则,至少读取一个字节并将其存储在 b 中
将读取的第一个字节存储在元素 b[0] 中
下一个存储在 b[1] 中
依次类推
读取的字节数最多等于 b 的长度
假设 k 为实际读取的字节数
这些字节将存储在 b[0] 到 b[k-1] 的元素中
不影响 b[k] 到 b[b.length-1] 的元素
%%%%%
read ( byte[] b, int off, int len )
将输入流中最多 len 个数据字节读入 byte 数组
尝试读取 len 个字节,但读取的字节也可能小于该值
以整数形式返回实际读取的字节数
如果 len 为 0 则不读取任何字节并返回 0
否则,尝试读取至少一个字节
已到达流末尾而不再有数据可用 则返回值 -1
否则,至少读取一个字节并将其存储在 b 中
将读取的第一个字节存储在元素 b[off] 中
下一个存储在 b[off+1] 中
依次类推
读取的字节数最多等于 len
假设 k 为实际读取的字节数
这些字节将存储在 b[off] 到 b[off+k-1] 的元素中
不影响 b[off+k] 到 b[off+len-1] 的元素
在任何情况下 b[0] 到 b[off] 的元素以及 b[off+len] 到 b[b.length-1] 的元素都不会受到影响
%%%%%
System.in.read() 读取单字节
可以单独读取一个 字符/数字
需要使用 try catch 捕获编码过程中的异常
示例:
import java.util.*;
public class test {
public static void main(String[] args) {
try {
char str;
int num;
System.out.print ( "输入字符串 <<< " );
str = (char) System.in.read();
System.out.print("读取的第一个字符为 >>> [" + str + "]\n" );
Scanner read = new Scanner(System.in);
/* System.in.read() 是不需要实例化对象的 这是为了 read.nextLine() 清除缓冲区 故意实例化的 read 名字! */
read.nextLine();
System.out.print ( "输入一个字母 <<< " );
num = System.in.read();
System.out.print ( "该字母的 Unicode 编码为 >>> [" + num + "] \n" );
read.nextLine();
System.out.print ( "输入一个数字 <<< " );
num = System.in.read();
System.out.print ( "该数字的 Unicode 编码为 >>> [" + num + "] \n" );
} catch ( Exception e ) {
e.printStackTrace();
}
}
}
尽管控制台输入的是一个字符串 但是实际上只能读取一个字符
例如 输入数字 8
实际上 读取的是 56
这个数字可不是我们十进制的整数 而是计算机的 Unicode 编码
测试:
C:\Users\byme\javaTest>javac test.java
C:\Users\byme\javaTest>java test
输入字符串 <<< abcd1234
读取的第一个字符为 >>> [a]
输入一个字母 <<< a
该字母的 Unicode 编码为 >>> [97]
输入一个数字 <<< 8
该数字的 Unicode 编码为 >>> [56]
C:\Users\byme\javaTest>
##################################################
Java 中的字节流和字符流
——————————
Eclipse IDE 使用方式
这次使用 Eclipse 编写编译代码:
工作目录为:
C:\Users\byme\eclipse-workspace
新建项目:
默认 JRE 是 SE 17
项目名称 test
模块名称默认:
新建类:
默认对话框:
类名 Main
勾选 main 方法:
创建一个类成功
——————————
流概念
在开发中 这是最常用的三种
Scanner 类
BufferedInputStream 字节流
BufferedReader 字符流
try catch 是异常处理捕获的方式
什么是流?
好比水流 河流
java.util.Scanner 类就是一个一个的拼接
相当于 一滴水一滴水的
字节流/字符流 却是流动性的
流 就是 stream 一个连续的字节队列
字节流是由字节组成的,
字节流是最基本的,所有的 InputStrem 和 OutputStream 的子类都是
主要用在处理二进制数据 她是按字节来处理的
流是程序输入或输出的一个连续的字节序列
设备
例如
鼠标
键盘
磁盘
屏幕
打印机
的输入和输出都是用流来处理的
在 C 语言中,所有的流均以文件的形式出现
不一定是物理磁盘文件
还可以是对应与某个 输入/输出 源的逻辑文件
所有文件的存储都是字节的存储
我们日常在磁盘上保存的其实并不是文件的字符
而是先把字符转换成字节 再把这些字节储存到磁盘
在读取文件时 也是一个字节一个字节的读取
然后生成字节的序列
字节流可以处理任何对象
但是字符流呢 只用来处理字符或者字符串
可以这样说,字节流呢,提供了最基本 IO 功能 就是输入输出
可以处理任何 IO 操作,但是有一点 不可以直接处理 Unicode 字符 为什么呢?
因为 Unicode 字符是一个单元为 2 个字节的字符 而字节流的处理单元为 1 个字节
字符流是由 Java 虚拟机将字节转化为 2 个字节的 Unicode 字符为单位的字符形成的
如果使用字节流直接处理 Unicode 字符的话 由于各种编码实现的不同,就很容易出现乱码!
我们日常处理的很多数据都是文本
所以我们在字节流之外呢,又提出了字符流的概念
直接按照 Java 虚拟机的 encode 来处理
也就是在输出流和输入流之间 进行字符集的转换!
BufferedInputStream 是带缓冲区的输入流
默认缓冲区大小是 8 M
能够减少访问磁盘的次数,提高文件读取性能
BufferedOutputStream 是带缓冲区的输出流 能够提高文件的写入效率
BufferedInputStream 与 BufferedOutputStream 分别是 FilterInputStream 类和 FilterOutputStream 类的子类
实现了装饰设计模式
——————————
BufferedInputStream 字节流
介绍一下通过 BufferedInputStream/字节流 的方式读取控制台的输入
首先 需要导入这些包
java.io 包下的 6 个类:
import java.io.File;
import java.io.InputStream;
import java.io.FileInputStream;
import java.io.BufferedInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
java.text 下的 1 个类:
import java.text.SimpleDateFormat;
java.util 下的 1 个类:
import java.util.Date;
后来 ide 中发现全都是扯淡 只需要 java.io 包里的两个类:
import java.io.BufferedInputStream;
import java.io.IOException;
首先创建一个 BufferedInputStream 对象用于接收控制台的输入
然后创建一个数组 例如 byte
长度必须为 1024
用于接收储存字符串
使用 read 方法读取
最后使用 new String(byte[]) 将 byte 输入转换成字符串进行输出
代码中如果有异常 用 try catch 捕获即可
记事本中的代码:
import java.io.*;
public class test {
public static void main(String[] args) {
BufferedInputStream in = new BufferedInputStream(System.in);
System.out.print ( "请输入一个字符串 <<< " );
try {
byte[] b = new byte[1024];
in.read ( b );
System.out.print ( "读取的字段串为 >>> [" + new String ( b ) + "]" );
} catch ( IOException e ) {
e.printStackTrace();
}
}
}
导入包后将 main 方法中的代码体复制进 ide 环境:
Ctrl 11 编译运行点击确定:
编译通过 执行没有出错:
运行结果:
可以看到一共有 13 个字符外加一个回车 一共使用了 14 个位置
输出的其她莫名字符是 b 数组中剩余的元素
因为这个字节数组大小为 1024 而我们只使用了 14 个位置
剩下的 1010 都是没有使用的空元素:
请输入一个字符串 <<< abcd1234!~{}
读取的字段串为 >>> [abcd1234!~{}
——————————
BufferedReader 字符流
字符流就比字节流使用的方便的多
当然也是需要导包的:
只需要导入 java.io 的三个包就可以:
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
代码如下:
import java.io.*;
public class test {
public static void main(String[] args) {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); /* 这样是为了将数据传入流中,相当于数据流的入口 */
System.out.print ( "请输入一个字符串 <<< " );
try {
System.out.print ( "读取的字符串为 >>> [" + in.readLine() + "]\n");
} catch ( IOException e ) {
e.printStackTrace();
}
}
}
运行结果:
请输入一个字符串 <<< 我四针滴 Love 泥!
读取的字符串为 >>> [我四针滴 Love 泥!]
没有什么乱七八糟的元素 输入什么就输出什么!