API(Application Programming Interface,应用程序接口)是一些预先定义的函数,或指软件系统不同组成部分衔接的约定。
类 Object 是类层次结构的根类。每个类都使用 Object 作为超类。所有对象(包括数组)都实现这个类的方法。
创建对象
Object()
常用方法
hashCode( )返回该对象的哈希码值
equals(Object obj) 指示其他某个对象是否与此对象“相等”
toString( )返回该对象的字符串表示
public class Test_Object {
public static void main(String[] args) {
//1,创建Object对象
Object o = new Object();//触发无参构造
//2,调用常用方法
System.out.println( o.hashCode() );//366712642,o对象在内存中的哈希码值
System.out.println( o.toString() );//java.lang.Object@15db9742,展示对象在内存中的地址值
System.out.println( o.equals("jack") );//false,比较o对象和"jack"是否相等
}
}
其他方法
getClass( )返回此 Object 的运行时类
clone( ) 创建并返回此对象的一个副本
wait( )调用其方法的线程进入等待状态(重载方法)
notify( )/notifyAll( )唤醒在此对象监视器上等待的单个线程/所有线程
finalize( )当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法
String 类代表字符串。Java 程序中的所有字符串字面值(如 “abc” )都作为此类的实例实现。
特点(底层源码)
public final class String --不能被继承
private final char value[ ];–字符串是常量
常用方法
char charAt(int index)-----返回指定索引处的 char 值。
String concat(String str)-----将指定字符串连接到此字符串的结尾。
boolean endsWith(String suffix)-----测试此字符串是否以指定的后缀结束。
boolean equals(Object anObject)-----将此字符串与指定的对象比较。
byte[] getBytes()-----使用平台的默认字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中
int hashCode()-----返回此字符串的哈希码。
int indexOf(String str)-----返回指定子字符串在此字符串中第一次出现处的索引
int lastIndexOf(String str)-----返回指定子字符串在此字符串中最右边出现处的索引。
boolean isEmpty()-----当且仅当 length() 为 0 时返回 true。
int length()-----返回此字符串的长度。
String replace(char oldChar, char newChar) -----返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。
String[] split(String regex)----- 根据给定正则表达式的匹配拆分此字符串。
boolean startsWith(String prefix)-----测试此字符串是否以指定的前缀开始。
String substring(int beginIndex)-----返回一个新的字符串,它是此字符串的一个子字符串。
String substring(int beginIndex, int endIndex)-----返回一个新字符串,它是此字符串的一个子字符串。
char[] toCharArray()-----将此字符串转换为一个新的字符数组。
String toLowerCase()----- 使用默认语言环境的规则将此 String 中的所有字符都转换为小写
String toUpperCase()----- 使用默认语言环境的规则将此 String 中的所有字符都转换为大写
String trim()-----返回字符串的副本,忽略前导空白和尾部空白。
static String valueOf(int i)----- 返回 int 参数的字符串表示形式。
import java.util.Arrays;
//测试 String工具类
public class Test_String {
public static void main(String[] args) {
//1,创建String对象
char[] cs = {
'a','b','c','a'};
String str = new String(cs);//触发String(char[] value)
String str2 = "abcdefabc" ;//相当于简写形式
//2,调用方法
System.out.println( str.charAt(2) );//c---根据下标2,获取对应的字符
System.out.println( str.concat("xyz") );//abcaxyz---拼接字符串
System.out.println( str.endsWith("abc"));//false---判断是否以指定数据结尾
System.out.println( str.equals("abca"));//true---判断两个字符串的内容是否相同
System.out.println("1--------------");
System.out.println( str.hashCode() );//2987071---计算哈希码值
System.out.println( str.indexOf("a") );//0---获取第一次出现的索引值
System.out.println( str.lastIndexOf("a") );//3---获取最后一次出现的索引值
System.out.println( str.isEmpty() );//false---判断字符串是否为空
System.out.println( str.length() );//4---获取字符串的长度
System.out.println("2--------------");
System.out.println( str.replace('a','x') );//xbcx---把旧字符换成新字符
System.out.println( str.startsWith("ab") );//true---判断是否以指定内容开始
System.out.println( str.substring(2) );//ca---截取字符串,从指定位置开始到末尾处
System.out.println("3--------------");
System.out.println( str.substring(1,3) );//bc---截取字符串,从1开始,到3结束,含头不含尾[1,3)
System.out.println( str.toLowerCase() );//abca---全转小写
System.out.println( str.toUpperCase() );//ABCA---全转大写
System.out.println("4--------------");
str = " abc 1 23 " ;
System.out.println( str.trim() );//abc 1 23---去除前导和后导多余的空格
String s = String.valueOf(10);//把指定的数字10转成字符串
System.out.println(s+1);//101---字符串拼接
System.out.println("5--------------");
char[] css = str.toCharArray();//把字符串的数据存入char[]
System.out.println(css);// abc 1 23
byte[] bs = str.getBytes() ;//把字符串的数据,转成整数并存入byte[]
System.out.println( Arrays.toString(bs) );//[32, 32, 32, 97, 98, 99, 32, 49, 32, 32, 50, 51, 32, 32, 32, 32, 32]
System.out.println("6--------------");
str = "a1b1c1d1" ;
String[] ss = str.split("1") ;//按照指定的字符串切割字符串
System.out.println( Arrays.toString(ss) );//[a, b, c, d]
//TODO 打印字符串里的每个字符-----------------
char[] a = str.toCharArray() ;
for (int i = 0; i < a.length; i++) {
//遍历char[]数组
System.out.println(a[i]);//根据下标获取数据
}
for(int i = 0; i < str.length() ;i++) {
//遍历字符串
char c = str.charAt(i);//根据下标获取字符
System.out.println(c);
}
}
}
结果
c
abcaxyz
false
true
1--------------
2987071
0
3
false
4
2--------------
xbcx
true
ca
3--------------
bc
abca
ABCA
4--------------
abc 1 23
101
5--------------
abc 1 23
[32, 32, 32, 97, 98, 99, 32, 49, 32, 32, 50, 51, 32, 32, 32, 32, 32]
6--------------
[a, b, c, d]
a
1
b
1
c
1
d
1
a
1
b
1
c
1
d
1
StringBuffer 字符串变量(线程安全)
StringBuilder 字符串变量(非线程安全)
当对字符串进行修改的时候,特别是字符串对象经常改变的情况下,需要使用 StringBuffer 和 StringBuilder 类。
和 String 类不同的是,StringBuffer 和 StringBuilder 类的对象能够被多次的修改,并且不产生新的未使用对象。
StringBuilder 类在 Java 5 中被提出,它和 StringBuffer 之间的最大不同在于 StringBuilder 的方法不是线程安全的(不能同步访问)。
由于 StringBuilder 相较于 StringBuffer 有速度优势,所以多数情况下建议使用 StringBuilder 类。然而在应用程序要求线程安全的情况下,则必须使用 StringBuffer 类。
常用方法
StringBuilder append(String str)//拼接
public class Test_StringBuilder {
public static void main(String[] args) {
method();//+拼接
method2();//StringBuilder拼接
}
public static void method2() {
//把指定的字符串拼接10000次
String s = "abcdefghijklmnopqrstuvwxyz" ;
StringBuilder sb = new StringBuilder();
long start = System.currentTimeMillis();//计时开始
for (int i = 0; i < 10000; i++) {
sb.append(s) ;//工具拼接
}
long end = System.currentTimeMillis();//计时结束
System.out.println(end-start);//1ms
}
//+拼接
public static void method() {
//把指定的字符串拼接10000次
String s = "abcdefghijklmnopqrstuvwxyz" ;
String res = "" ;//定义变量,记录结果
long start = System.currentTimeMillis();//计时开始
for (int i = 0; i < 10000; i++) {
res = res + s ;//+拼接慢
}
long end = System.currentTimeMillis();//计时结束
System.out.println(end-start);//1643ms
}
}
包装类的作用就是为对应的基本类型,提供丰富的功能
--基本类型 byte short int long float double char boolean
--包装类型 Byte Short Integer Long Float Double Character Boolean
为什么需要包装类?
首先,Java语言是一个面向对象的语言,但是Java中的基本数据类型却是不面向对象的,将每个基本数据类型设计一个对应的类进行代表,这种方式增强了Java面向对象的性质。
其次,如果仅仅有基本数据类型,那么在实际使用时将存在很多的不便,很多地方都需要使用对象而不是基本数据类型。比如,在集合类中,我们是无法将int 、double等类型放进去的,因为集合的容器要求元素是Object类型。而包装类型的存在使得向集合中传入数值成为可能,包装类的存在弥补了基本数据类型的不足。
此外,包装类还为基本类型添加了属性和方法,丰富了基本类型的操作。如当我们想知道int取值范围的最小值,我们需要通过运算,如下面所示,但是有了包装类,我们可以直接使用Integer.MAX_VALUE即可。
为什么要保留基本数据类型?
我们都知道在Java语言中,用new关键字创建的对象是存储在堆里的,我们通过栈中的引用来使用这些对象,所以,对象本身来说是比较消耗资源的。对于经常用到的类型,如int等,如果我们每次使用这种变量的时候都需要new一个对象的话,就会比较笨重了。所以,Java提供了基本数据类型,这种数据的变量不需要使用new在堆上创建,而是直接在栈内存中存储,因此会更加高效。
**自动装箱:**将基本类型的变量赋值给对应的包装类
**自动拆箱:**将包装类对象直接赋值给对应的基础类型变量
public class Test_Number {
public static void main(String[] args) {
//1,创建对象--把基本类型的5 变成 包装类型 i i2--为了用包装类丰富的方法
Integer i = new Integer(5);//触发含参构造Integer(int value)
//整数类型高效--相同数据不再开辟空间存储--范围:-128~127
Integer i2 = Integer.valueOf(5) ;
Integer i3 = Integer.valueOf(5) ;
System.out.println(i2 == i3);//true---i3就使用了已经存在的数据
//2,调用方法
int a = i.intValue();//把包装类型 包着的值 取出来--用于运算--自动拆箱
System.out.println(a);//5
//把字符串类型的数字 转成 基本类型的数字
int b = Integer.parseInt("123");
System.out.println(b+1);//124
//double<->Double
//自动装箱--把基本类型的 变成 包装类型
Double d = new Double(1.1) ;//double->Double --包起来--自动装箱
Double d2 = Double.valueOf(1.1);
//自动拆箱--把包装类型 包的值拆出来 基本类型
double m = d.doubleValue() ;//double<-Double --拆出来--自动拆箱
System.out.println(m);//1.1
double n = Double.parseDouble("1.1");//内容变成double类型
System.out.println(n+1);//2.1
}
}
通过查看包装类源码,Java为了在自动装箱时避免每次去创建包装类型,采用了缓存技术。即在类加载时,初始化一定数量的常用数据对象,放入缓存池中,等到使用时直接命中缓存,减少资源浪费。也就是说使用valueOf()时,如果指定范围内的值,访问缓存对象,而不新建对象;如果指定范围外的值,直接新建对象。
Integer a = new Integer(5);//创建对象
Integer b = Integer.valueOf(5);//读取缓存
Integer c = Integer.valueOf(5);//读取缓存
System.out.println(b==c);//true
System.out.println(a==b);//false
System.out.println(a.equals(b));//true
方法
parseInt();字符串转换成int
toBinaryString();把整数转换成2进制数据
toOctalString();把整数转换成8进制数据
toHexString();把整数转换成16进制数据
类Date 表示特定的瞬间,精确到毫秒。
毫秒:千分之一秒 1000毫秒=1秒
把日期转换成毫秒:
当前的日期:2019-07-18
时间原点(0毫秒):1970-01-01 00:00:00(英国格林威治)
就是计算当前日期到时间原点之间一共经历了多少毫秒
注意:
中国属于东八区,会把时间增加8个小时: 1970-01-01 08:00:00
把毫秒转换为日期:1天 = 246060 = 86400秒 = 86400*1000=86400000毫秒
import java.util.Date;
//测试 日期工具类
public class Test_Date {
public static void main(String[] args) {
//1,创建Date对象
Date date = new Date();
//TODO 2,调用方法
System.out.println( date.getDate() );//今天是多少号
System.out.println( date.getDay() );// 今天是星期几(0代表星期天)
System.out.println( date.getHours() );//现在是几点
System.out.println( date.getMinutes() );//现在是多少分钟
System.out.println( date.getMonth() );//现在是几月????(结果为当前月减 1)
System.out.println( date.getSeconds() );//现在是多少秒
System.out.println( date.getTime() );//从1970.1.1 零点到现在的毫秒值
System.out.println( date.getYear() );//从1900年到现在是多少年
System.out.println( date.toLocaleString() );//2020-10-18 1:33:09
}
}
日期格式化工具,可以把Date对象格式化成字符串,也可以日期字符串解析成Date对象。
创建对象
new SimpleDateFormat(格式)
格式:yyyy-MM-dd HH:mm:ss MM/dd/yyyy…
常见方法
format(Date):把Date格式化成字符串
parse(String):把String解析成Date
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;
//测试 日期格式化的工具类SimpleDateFormat -- Date<->String
public class Test_SimpleDF {
public static void main(String[] args) throws Exception {
//1,创建对象--参数是日期的格式 年y-月M-日d 月/日/年
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
//2,常用方法
String str = sdf.format(new Date());//Date->String
System.out.println(str);//2020-10-18
Date d = sdf.parse("2020-10-18");//String->Date
System.out.println(d.getMonth());//9---月份减一
//3,计算存活天数
//接收输入的出生日期 输入的出生日期格式必须按上面设定的格式输入!
String birthday = new Scanner(System.in).nextLine();
//String->Date 输入的日期是以字符串格式存入的,先转换成date格式
Date birth = sdf.parse(birthday);
//计算天数
long start = birth.getTime() ;//出生日期 对应的毫秒值
long now = System.currentTimeMillis() ;//当前时间的毫秒值
System.out.println( (now-start)/1000/60/60/24 );//通过计算算出出生天数
}
}
BigDecimal:常用来解决精确的浮点数运算。
BigInteger:常用来解决超大的整数运算。
常用方法
add(BigDecimal bd): 做加法运算
substract(BigDecimal bd) : 做减法运算
multiply(BigDecimal bd) : 做乘法运算
divide(BigDecimal bd) : 做除法运算
divide(BigDecimal bd,保留位数,舍入方式):除不尽时使用
setScale(保留位数,舍入方式):同上
pow(int n):求数据的几次幂
import java.math.BigDecimal;
import java.util.Scanner;
public class Test2_BigD {
public static void main(String[] args) {
double a = new Scanner(System.in).nextDouble();
double b = new Scanner(System.in).nextDouble();
System.out.println(a+b);
System.out.println(a-b);
System.out.println(a*b);
System.out.println(a/b);//不精确
System.out.println(“===上面的除法不精确===”);
BigDecimal bd1 = BigDecimal.valueOf(a);
BigDecimal bd2 = BigDecimal.valueOf(b);
BigDecimal bd3;
bd3=bd1.add(bd2);
System.out.println(bd3.doubleValue());
bd3=bd1.subtract(bd2);
System.out.println(bd3.doubleValue());
bd3=bd1.multiply(bd2);
System.out.println(bd3.doubleValue());
// bd3=bd1.divide(bd2);//报错除不尽
//保留位数和舍入方式
bd3=bd1.divide(bd2,5,BigDecimal.ROUND_HALF_UP);
bd3=bd3.setScale(2, BigDecimal.ROUND_HALF_UP);//保留两位
System.out.println(bd3.doubleValue());
}
}
in/out相对于程序而言的输入(读取)和输出(写出)的过程。
–in/I :从磁盘里读取到程序里
–out/O : 从程序里写出到磁盘中
在Java中,根据处理的数据单位不同,分为字节流和字符流
字符流: 只能操作字符文件.txt
字节流: 可以操作任何数据 – 应用的更加广泛
字节流:针对二进制文件
InputStream
–FileInputStream
–BufferedInputStream
–ObjectInputStream
OutputStream
–FileOutputStream
–BufferedOutputStream
–ObjectOutputStream
字符流:针对文本文件。读写容易发生乱码现象,在读写时最好指定编码集为utf-8
Writer
–BufferedWriter
–OutputStreamWriter
Reader
–BufferedReader
–InputStreamReader
–PrintWriter/PrintStream
封装一个磁盘路径字符串,对这个路径可以执行一次操作。可以用来封装文件路径、文件夹路径、不存在的路径。
File(String pathname)
通过将给定路径名字符串转换为抽象路径名来创建一个新 File 实例。
length():文件的字节量
exists():是否存在,存在返回true
isFile():是否为文件,是文件返回true
isDirectory():是否为文件夹,是文件夹返回true
getName():获取文件/文件夹名
getParent():获取父文件夹的路径
getAbsolutePath():获取文件的完整路径
createNewFile():新建文件,文件夹不存在会异常,文件已经存在返回false
mkdirs():新建多层不存在的文件夹\a\b\c
mkdir():新建单层不存在的文件夹\a
delete():删除文件,删除空文件夹
list():返回String[],包含文件名
listFiles():返回File[],包含文件对象
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Scanner;
// 测试 File工具类
public class Test_File {
public static void main(String[] args) throws IOException {
//1,新建File对象--参数是一个路径
File file = new File("D:\\iotest\\1.txt");
//2,调用方法
System.out.println( file.length() );//获取文件的字节量
System.out.println( file.exists() );//判断文件是否存在
System.out.println( file.isFile() );//判断是不是文件
System.out.println( file.isDirectory() );//判断是不是文件夹
System.out.println( file.getName() );//获取文件名
System.out.println( file.getParent() );//获取父路径
System.out.println( file.getAbsolutePath() );//获取完整路径
file = new File("D:\\iotest\\2.txt");
System.out.println( file.createNewFile() );//新建文件
file = new File("D:\\iotest\\xyz");
System.out.println( file.mkdir() );//新建一层不存在的文件夹
file = new File("D:\\iotest\\a");
System.out.println( file.mkdirs() );//新建多层不存在的文件夹
file = new File("D:\\iotest\\2.txt");
System.out.println( file.delete() );//删除文件 或者 空的文件夹
//列出文件夹里的资源
file = new File("D:\\iotest");
String[] strs = file.list();//获取资源名称,放入String[]
System.out.println( Arrays.toString(strs) );
//获取到资源,并把资源一个一个的封装成File对象存入File[]--推荐
File[] fs = file.listFiles();
System.out.println( Arrays.toString(fs) );
//TODO 练习:
//接收用户输入的文件夹路径
String path = new Scanner(System.in).nextLine();
File f = new File(path) ;//把路径封装成File对象
//列出文件夹里的所有资源
File[] a = f.listFiles() ;
long sum = 0 ;//定义变量,记录文件的总大小
//遍历数组,获取每个资源
for(int i = 0 ; i < a.length ;i++) {
//判断,拿到的资源是文件吗? -- a[i]
if( a[i].isDirectory() ) {
//如果是文件夹
System.out.println("这是一个文件夹,文件夹名字是:"+a[i].getName());
}else if( a[i].isFile() ) {
//如果是文件
sum = sum + a[i].length() ;//求所有文件的总大小
}
}
System.out.println("文件总大小是:"+sum);
}
}
练习递归求目录大小
import java.io.File;
import org.junit.Test;
//递归求目录总大小
public class Test2_File2 {
public static void main(String[] args) {
// 1、把指定目录封装成File对象
File file = new File("D:\\teach\\a");
int size =count(file);
System.out.println(size);
}
private static int count(File file) {
// 2、把文件夹列表列出来
File[] files = file.listFiles();
//2.1 遍历数组里的每个资源
int sum = 0;//记录文件的大小
for (int i = 0; i < files.length; i++) {
// 3、判断,如果是文件,直接把f.length()相加
// files[i]表示每次遍历到的资源
if(files[i].isFile()) {
sum += files[i].length();//求文件的和
}else if(files[i].isDirectory()){
// 4、判断,如果是文件夹,继续列表,继续判断,如果是文件相加,如果又是文件夹,继续列表,继续判断,如果是文件相加......
// 5、如果是文件夹,递归调用方法本身的业务逻辑
sum += count(file[i]);//把当前遍历到的文件夹继续循环判断求和
}
}
return sum ;
}
}
字节流是由字节组成的,字符流是由字符组成的. Java里字符由两个字节组成.字节流是最基本的,所有的InputStream和OutputStream的子类都是,主要用在处理二进制数据。
流式传输主要指将整个音频和视频及三维媒体等多媒体文件经过特定的压缩方式解析成一个个压缩包,由视频服务器向用户计算机顺序或实时传送。在采用流式传输方式的系统中,用户不必像采用下载方式那样等到整个文件全部下载完毕,而是只需经过几秒或几十秒的启动延时即可在用户的计算机上利用解压设备对压缩的A/V、3D等多媒体文件解压后进行播放和观看。此时多媒体文件的剩余部分将在后台的服务器内继续下载。
此抽象类是表示字节输入流的所有类的超类/抽象类。
常用方法
abstract int read()//从输入流中读取数据的下一个字节。
int read(byte[] b)// 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。
int read(byte[] b, int off, int len) //将输入流中最多 len 个数据字节读入 byte 数组。
void close()// 关闭此输入流并释放与该流关联的所有系统资源。
直接插在文件上,直接读取文件数据。
创建对象
FileInputStream(File file)// 通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的File 对象 file 指定。
FileInputStream(String pathname)// 通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名 name 指定。
BufferedInputStream 为另一个输入流添加一些功能,即缓冲输入以及支持 mark 和 reset 方法的能力。在创建 BufferedInputStream 时,会创建一个内部缓冲区数组(默认8M大小)。在读取或跳过流中的字节时,可根据需要从包含的输入流再次填充该内部缓冲区,一次填充多个字节。
创建对象
BufferedInputStream(InputStream in)// 创建一个 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。
此抽象类是表示输出字节流的所有类的超类。输出流接受输出字节并将这些字节发送到某个接收器。
常用方法
void close()// 关闭此输出流并释放与此流有关的所有系统资源。
void flush()// 刷新此输出流并强制写出所有缓冲的输出字节。
void write(byte[] b)// 将 b.length 个字节从指定的 byte 数组写入此输出流。
void write(byte[] b, int off, int len)// 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。
abstract void write(int b)//将指定的字节写入此输出流。
直接插在文件上,直接写出文件数据
创建对象
FileOutputStream(String name)// 创建一个向具有指定名称的文件中写入数据的输出文件流。FileOutputStream(File file)//创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
FileOutputStream(File file, boolean append) //追加创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
该类实现缓冲的输出流。通过设置这种输出流,应用程序就可以将各个字节写入底层输出流中,而不必针对每次字节写入调用底层系统。
创建对象
BufferedOutputStream(OutputStream out)//创建一个新的缓冲输出流,以将数据写入指定的底层输出流。
读取代码演示
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
//测试 字节读取流
//总结
//1,效率上: BufferedInputStream > FileInputStream
//2,原因是:BufferedInputStream底层维护一个byte[],把byte[]填满了
//程序才读取一次.减少了程序从流中的读取次数,提高了效率.
//3,byte[] 的容量可以自己设置,也可以使用默认的,默认的是8192字节,相当于8K大小
public class Test_InputStream {
public static void main(String[] args) throws IOException {
method();//FileInputStream读取
method2();//BufferedInputStream读取
}
//FileInputStream读取
public static void method() throws IOException {
//1,创建多态对象
//触发String含参构造
InputStream in = new FileInputStream("D:\\iotest\\1.txt");
//触发File含参构造
InputStream in2 = new FileInputStream( new File("D:\\iotest\\1.txt") );
//2,开始读取
int data = in.read() ;//读取到了第一个字节
System.out.println(data);
System.out.println(in.read());
System.out.println(in.read());
//没数据了,还读,不会报错,而是永远得到-1
System.out.println(in.read());
System.out.println(in.read());
//改造
int b = 0 ;//定义变量,记录read()的返回值
while( ( b = in.read() ) != -1) {
//有数据就一直读,没数据就返回-1循环结束
System.out.println(b);//打印读取到的数据
}
//3,释放资源
in.close();
//流已经关闭了,就别读了,不然会抛出异常:java.io.IOException: Stream Closed
//System.out.println(in.read());
}
//BufferedInputStream读取
public static void method2() throws IOException {
//1,创建多态对象
InputStream in = new BufferedInputStream( new FileInputStream("D:\\iotest\\1.txt"));
//2,开始读取
int b = 0 ;//定义变量,记录read()的返回值
while( ( b = in.read() ) != -1) {
//返回-1说明没数据了循环结束
System.out.println(b);//打印读到的数据
}
//3,释放资源
in.close();
}
}
写出代码演示
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
//测试 字节读写出
//总结
//1,效率上:BufferedOutputStream > FileOutputStream
//2,原因是:BufferedOutputStream底层维护了一个byte[] ,把数组填满了,才写出一次,
//减少了写出数次,提高了效率
//3,byte[] 可以自定义容量大小,也可以使用默认的大小,默认是8192字节,相当于8K的大小
//4,FileOutputStream 在写出数据时,默认是数据覆盖模式,也可以控制成数据追加模式
public class Test_OutputStream {
public static void main(String[] args) throws IOException {
method();//FileOutputStream写出
method2();//BufferedOutputStream写出
}
public static void method() throws IOException {
//1,创建多态对象
// OutputStream out = new FileOutputStream("D:\\iotest\\1.txt");//默认发生数据覆盖
OutputStream out = new FileOutputStream("D:\\iotest\\1.txt",true);//数据追加
// OutputStream out2 = new FileOutputStream(new File("D:\\iotest\\1.txt"));
//2,开始写出
out.write(97);
out.write(97);
out.write(97);
out.write(97);
//3,释放资源
out.close();
}
public static void method2() throws IOException {
//1,创建多态对象
//OutputStream out = new BufferedOutputStream(
// new FileOutputStream("D:\\iotest\\1.txt") );//数据覆盖
OutputStream out = new BufferedOutputStream(
new FileOutputStream("D:\\iotest\\1.txt",true) );//数据追加
//2,开始写出
out.write(97);
out.write(97);
out.write(97);
//3,释放资源
out.close();
}
//FileOutputStream写出
}
此抽象类是表示字符输入流的所有类的超类/抽象类。
常用方法:
int read()读取单个字符。
int read(char[] cbuf)将字符读入数组。
abstract int read(char[] cbuf, int off, int len)将字符读入数组的某一部分。
int read(CharBuffer target) 试图将字符读入指定的字符缓冲区。
abstract void close()关闭该流并释放与之关联的所有资源。
创建对象
FileReader(String fileName)
FileReader (File file)
创建对象
InputStreamReader(InputStream in, String charsetName)
InputStreamReader(InputStream in)
创建对象
BufferedReader(Reader in)
此抽象类是表示字符输出流的所有类的超类/抽象类。
常用方法:
void write(char[] cbuf)写入字符数组。
abstract void write(char[] cbuf, int off, int len) 写入字符数组的某一部分。
void write(int c)写入单个字符。
void write(String str)写入字符串。
void write(String str, int off, int len)写入字符串的某一部分。
abstract void close()关闭此流,但要先刷新它。
创建对象
FileWriter(String fileName)
FileWriter(String fileName,boolean append)
创建对象
OutputStreamWriter(OutputStream out, String charsetName)
OutputStreamWriter(OutputStream out)
创建对象
BufferedWriter(Writer out)
序列化 (Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。
1、序列化:利用ObjectOutputStream,对象的信息,按固定格式转成一串字节值输出并持久保存到磁盘化。
2、反序列化:利用ObjectInputStream,读取磁盘中序列化数据,重新恢复对象。
注意:
1、 需要序列化的文件必须实现Serializable接口以启用其序列化功能。
2、 每个被序列化的文件都有一个唯一id,如果没有添加编译器会根据类的定义信息计算产生一个版本号。
用来作为桥梁,把字节流转成字符流的桥梁。用来解决字符流读写乱码问题。
OutputStreamWriter:是字节流通向字符流的桥梁
创建对象
OutputStreamWriter(OutputStream out, String charsetName)
OutputStreamWriter(OutputStream out)
InputStreamReader:是字节流通向字符流的桥梁
创建对象
InputStreamReader(InputStream in, String charsetName)
InputStreamReader(InputStream in)
阻塞IO,BIO 就是传统的 java.io 包,它是基于流模型实现的,交互的方式是同步、阻塞方式,也就是说在读入输入流或者输出流时,在读写动作完成之前,线程会一直阻塞在那里,它们之间的调用时可靠的线性顺序。它的有点就是代码比较简单、直观;缺点就是 IO 的效率和扩展性很低,容易成为应用性能瓶颈。
非阻塞IO,NIO 是 Java 1.4 引入的 java.nio 包,提供了 Channel、Selector、Buffer 等新的抽象,可以构建多路复用的、同步非阻塞 IO 程序,同时提供了更接近操作系统底层高性能的数据操作方式。
异步IO,AIO 是 Java 1.7 之后引入的包,是 NIO 的升级版本,提供了异步非堵塞的 IO 操作方式,所以人们叫它 AIO(Asynchronous IO),异步 IO 是基于事件和回调机制实现的,也就是应用操作之后会直接返回,不会堵塞在那里,当后台处理完成,操作系统会通知相应的线程进行后续的操作。但目前还不够成熟,应用不多。