API
API(Application Programming Interface,应用程序接口)是一些预先定义的函数,或指软件系统不同组成部分衔接的约定。
Object
类 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
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
StringBuilder/StringBuffer
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为了在自动装箱时避免每次去创建包装类型,采用了缓存技术。即在类加载时,初始化一定数量的常用数据对象,放入缓存中,等到使用时直接命中缓存,减少资源浪费。
Number类
是所有数字类型 包装类的父类,被修饰成了抽象类,不能new
byte byteValue() 以 byte 形式返回指定的数值。
abstract double doubleValue() 以 double 形式返回指定的数值。
abstract float floatValue() 以 float 形式返回指定的数值。
abstract int intValue() 以 int 形式返回指定的数值。
abstract long longValue() 以 long 形式返回指定的数值。
short shortValue() 以 short 形式返回指定的数值。
Date日期类
类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() );//18---今天是多少号
System.out.println( date.getDay() );//---0 今天是星期几(0代表星期天)
System.out.println( date.getHours() );//1---现在是几点
System.out.println( date.getMinutes() );//33---现在是多少分钟
System.out.println( date.getMonth() );//9---现在是几月????(结果为当前月减 1)
System.out.println( date.getSeconds() );//9---现在是多少秒
System.out.println( date.getTime() );//1602955989808---从1970.1.1 零点到现在的毫秒值
System.out.println( date.getYear() );//120---从1900年到现在是多少年
System.out.println( date.toLocaleString() );//2020-10-18 1:33:09
}
}
日期工具SimpleDateFormat
专门用来把日期数据进行转化.把 String类型的日期 和 Date类型的日期互转
创建对象
SimpleDateFormat(String pattern)
常见方法
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 birth = sdf.parse(birthday);
//计算天数
long start = birth.getTime() ;//出生日期 对应的毫秒值
long now = System.currentTimeMillis() ;//当前时间的毫秒值
System.out.println( (now-start)/1000/60/60/24 );
}
}
结果(输入生日计算)
2020-10-18
9
1995-09-14
9166
BigDecimal/BigInteger
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 Test_BigDecimal {
public static void main(String[] args) {
method();//暴露问题
method2();//解决方案
}
//暴露问题
public static void method() {
double a = 1.1111;
double b = 2.22;
//做运算
System.out.println(a+b);//3.3311
System.out.println(a-b);//-1.1089000000000002
System.out.println(a*b);//2.4666420000000002
System.out.println(a/b);//0.5004954954954954
}
public static void method2() {
double a = 1.1111;
double b = 2.22;
//创建对象
//含参构造BigDecimal(double val)--有坑
//BigDecimal bd1 = new BigDecimal(a);
//BigDecimal bd2 = new BigDecimal(b);
//触发含参构造BigDecimal(String val) -- 推荐
BigDecimal bd1 = new BigDecimal( String.valueOf(a) );//double->String
BigDecimal bd2 = new BigDecimal(b+"");//double->String
BigDecimal bd3 = bd1.add(bd2);//加法
System.out.println(bd3);//3.3311
bd3 = bd1.subtract(bd2);//减法
System.out.println(bd3);//-1.1089
bd3 = bd1.multiply(bd2);//乘法
System.out.println(bd3);//2.466642
//除法--除不尽时--java.lang.ArithmeticException
//bd3 = bd1.divide(bd2);
//重载的divide(x,y,z)-x是要参与运算的对象名称,y是保留的小数位数,z是舍入模式
bd3 = bd1.divide(bd2,5,BigDecimal.ROUND_HALF_UP);
System.out.println(bd3);//0.50050
}
}
IO
概述
--主要是把 程序中的数据 和磁盘里的数据 进行交互
--in/I :从磁盘里读取到程序里
--out/O : 从程序里写出到磁盘中
--无论进行读in还是写out,都可以用字节流和字符流完成
到底用哪种流读写呢? ----根据操作数据的单位不同.jpg .txt .mp4??
字符流: 只能操作字符文件.txt
字节流: 可以操作任何数据 -- 应用的更加广泛
File文件流
用于文件或者目录的描述信息,例如生成新目录,修改文件名,删除文件,判断文件所在路径等。
创建对象
File(String pathname)
常用方法
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);
}
}
字节流
InputStream抽象类
此抽象类是表示字节输入流的所有类的超类/抽象类。
常用方法
abstract int read() 从输入流中读取数据的下一个字节。
int read(byte[] b) 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。
int read(byte[] b, int off, int len)将输入流中最多 len 个数据字节读入 byte 数组。
void close() 关闭此输入流并释放与该流关联的所有系统资源。
FileInputStream子类
创建对象
FileInputStream(File file)
FileInputStream(String name)
BufferedInputStream子类
创建对象
BufferedInputStream(InputStream in)
测试
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();
}
}
OutputStream抽象类
此抽象类是表示字节输出流的所有类的超类/抽象类。
常用方法
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子类
创建对象
FileOutputStream(File file)
FileOutputStream(File file, boolean append)
FileOutputStream(FileDescriptor fdObj)
FileOutputStream(String name)
FileOutputStream(String name, boolean append)
BufferedOutputStream子类
创建对象
BufferedOutputStream(OutputStream out)
测试
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写出
}
字符流
Reader抽象类
此抽象类是表示字符输入流的所有类的超类/抽象类。
常用方法:
int read()读取单个字符。
int read(char[] cbuf)将字符读入数组。
abstract int read(char[] cbuf, int off, int len)将字符读入数组的某一部分。
int read(CharBuffer target) 试图将字符读入指定的字符缓冲区。
abstract void close()关闭该流并释放与之关联的所有资源。
FileReader子类
创建对象
FileReader(String fileName)
FileReader (File file)
InputStreamReader子类
创建对象
InputStreamReader(InputStream in, String charsetName)
InputStreamReader(InputStream in)
BufferedReader子类
创建对象
BufferedReader(Reader in)
Writer抽象类
此抽象类是表示字符输出流的所有类的超类/抽象类。
常用方法:
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子类
创建对象
FileWriter(String fileName)
FileWriter(String fileName,boolean append)
OutputStreamWriter子类
创建对象
OutputStreamWriter(OutputStream out, String charsetName)
OutputStreamWriter(OutputStream out)
BufferedWriter子类
创建对象
BufferedWriter(Writer out)
测试字符流读写
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
public class RW {
public static void main(String[] args) throws Exception {
method1();//字符读取
method2();//字符写出
}
private static void method1() throws Exception {
// 字符流读图片乱码
BufferedReader in = new BufferedReader(
new InputStreamReader(new FileInputStream(new File("D:\\teach\\a\\1.txt"))));
// System.out.println(in.readLine());
// System.out.println(in.readLine());//null读到/n/r
String line = "";
while ((line = in.readLine()) != null) {// 一行一行读
System.out.println(line);
}
in.close();
}
private static void method2() throws Exception {
Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File("D:\\\\teach\\\\a.txt")) , "utf-8"));
long s = System.currentTimeMillis();
for (int i = 48; i < 1000000; i++) {
out.write(i);
}
s = System.currentTimeMillis() - s;
System.out.println(s + "--");// 266
out.close();
}
}
序列化/反序列化
序列化 (Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。
1、序列化:利用ObjectOutputStream,对象的信息,按固定格式转成一串字节值输出并持久保存到磁盘化。
2、反序列化:利用ObjectInputStream,读取磁盘中序列化数据,重新恢复对象。
注意:
1、 需要序列化的文件必须实现Serializable接口以启用其序列化功能。
2、 每个被序列化的文件都有一个唯一id,如果没有添加编译器会根据类的定义信息计算产生一个版本号。
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class Test_Seri {
public static void main(String[] args) throws Exception, IOException {
//序列化:就是把java对象保存在磁盘中
ObjectOutputStream os =
new ObjectOutputStream(
new FileOutputStream(
"D:\\teach\\a\\student.txt"));
Student s = new Student("张三",20,"成都");
os.writeObject(s);//序列化,把Student对象信息保存到指定文件中
os.close();//关闭输出资源
//反序列化:从磁盘读到程序里
ObjectInputStream in =
new ObjectInputStream(
new FileInputStream(
"D:\\teach\\a\\student.txt"));
//反序列化,把文件里的数据读到程序中,封装成对象,默认是Object
Object obj =in.readObject();
System.out.println(obj);
}
}
//1,如果想完成序列化,类必须实现Serializable接口
//只是用来做标记,需要序列化
class Student implements Serializable{
//创建对象用
public Student(String name, int age, String addr) {
this.name = name;
this.age = age;
this.addr = addr;
}
//一般序列化的都是属性
String name = "张三";
int age = 20;
String addr = "成都";
//为了看属性值
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + ", addr=" + addr + "]";
}
}
编码转换流
用来作为桥梁,把字节流转成字符流的桥梁。用来解决字符流读写乱码问题。
OutputStreamWriter:是字节流通向字符流的桥梁
创建对象
OutputStreamWriter(OutputStream out, String charsetName)
OutputStreamWriter(OutputStream out)
InputStreamReader:是字节流通向字符流的桥梁
创建对象
InputStreamReader(InputStream in, String charsetName)
InputStreamReader(InputStream in)
测试
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
//编码转换流的测试
public class Test_Decode {
public static void main(String[] args) {
method();//输出的转换流
method2();//读取的转换流
}
private static void method() {
try {
// 1,创建转换流输出对象,OutputStreamWriter是字节流通向字符流的桥梁
//第二个参数可以设置编码表,解决乱码现象
//写出去的文件如果使用了utf-8表,打开时,使用了默认的gbk编码表,就会出现乱码
// OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream("1.txt"), "utf-8");
OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream("1.txt"), "gbk");
// 2,开始写出数据
// 当数据的保存方式和打开方式,使用的不是一张表时,就会出现乱码!!
out.write("大家好,我是渣渣辉");
// TODO 3,释放资源
out.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
private static void method2() {
try {
//1,创建转换对象
//第二个参数可以设置编码表,解决乱码现象
//文件保存时使用的是gbk编码,如果用utf-8就会乱码
// BufferedReader in = new BufferedReader(
// new InputStreamReader(
// new FileInputStream("1.txt"),"utf-8"));//乱码
BufferedReader in = new BufferedReader(
new InputStreamReader(
new FileInputStream("1.txt"),"gbk"));
//2,读取一行数据
String line = in.readLine();//子类BufferedReader的特有方法
System.out.println(line);
//3,释放资源
}catch(Exception e) {
e.printStackTrace();
}
}
}