1.IO流分类:
1) 流的方向
输入流:读取数据
输出流:写入数据
2) 数据类型
字节流
字节输入流InputStreamàFileInputStream
字节缓冲输入流BufferedInputStream
字节输出流OutputStreamàFileOutputStream
字节缓冲输出流BufferedOutputStream
字符流 //字符流中的close:关闭该流的同时,之前一定要刷新流
字符输入流Reader
字符缓冲输入流BufferedReader
字符输出流Writer
字符缓冲输出流BufferedWriter
2.编码和解码
package 临时;
/*编码和解码:前后的编码格式要一致!
* 编码:
* 简单理解:将能看懂的东西--->看不懂的东西
* 解码:
* 看不懂的东西---能看懂的东西
*
* 举例: 谍战片
*
* 今天老地方见...
* 编码:
* 今---->字节---->二进制数据
*
* 解码:二进制数据-->十进制数据--->字节---->字符串
* 今
*
* 编码: 将字符串变成一个字节数组
* public byte[] getBytes() :平台默认编码集(默认的是Gbk)
* public byte[] getBytes(Charset charset);"指定编码格式
*
* 解码:将字节数组--->字符串
* public String(byte[] bytes) :使用平台默认编码集(gbk)
* public String(byte[] bytes,Charset charset):用指定的编码格式来解码*/
import java.util.Arrays;
/**
*计算机如何存储中文的?
* 当前平台默认编码集 :GBK 一个中文两个字节
* 第一个字节:一定是负数
* 第二个字节:一般是负数,可能也会是正数,不会影响的结果.
*
*/
public class 编码解码 {
publicstatic void main(String[] args) {
Strings="中国";
byte[]bys=s.getBytes();
//System.out.println(bys);//[B@532760d8
System.out.println(Arrays.toString(bys));//[-42,-48, -71, -6]
System.out.println(newString(bys));//中国
}
}
3. 常用流
1)字节输入流:一次读取字节数组
一次读取一个字节数组的方式要比一次读取一个字节方式高效
* 一次读取一个字节数组,相当于构造一个缓冲区,有没有比一次读取一个字节数组还要高效的流
* 字节缓冲流 :
public class FileInputStreamDemo {
publicstatic void main(String[] args) throws IOException {
//复制操作:将e盘下的abc.mp4复制到当前项目下,输出copy.mp4
//封装源文件
FileInputStreamfis = new FileInputStream("e://abc.mp4") ;
//封装目的地文件
FileOutputStreamfos = new FileOutputStream("copy.mp4") ;
//读写操作:一次读取字节数组
byte[]bys = new byte[1024] ;
intlen = 0 ;
while((len=fis.read(bys))!=-1){
//边读边写
fos.write(bys,0, len);
}
//释放资源
fis.close();
fos.close();
}
}
2)
1.字节缓冲输入流
* public BufferedInputStream(InputStream in):默认缓冲区大小构造缓冲输入流对象
* public BufferedInputStream(InputStream in,intsize):指定缓冲区大小构造缓冲输入流对象
* public int read() 读取字节完毕后返回-1
* public int read(byte[] b,int off,int len) 返回字节数组长度,读取完毕后返回-1
*
*在使输入流的时候,
* 两种方式读取(一次读取一个字节/一次读取一个字节数在),只能用一种方式,否则,会出现错误!
//构造一个字节缓冲输入流对象
BufferedInputStreambis=new BufferedInputStream(new FileInputStream("bos.txt"));
//读数据
//一次读取一个字节
/* int by = 0 ;
while((by=bis.read())!=-1){
System.out.print((char)by);
}*/
//一次读取一个字节数组
byte[]bys = new byte[1024] ;
intlen = 0 ;
while((len=bis.read(bys))!=-1){
System.out.println(newString(bys, 0, len));
}
//释放资源
bis.close();
2.字节缓冲输出流:
* 构造方式:
* (第一种开发中) public BufferedOutputStream(OutputStreamout):采用的默认的缓冲区大小(足够大了) ,来构造一个字节缓冲输出流对象
* publicBufferedOutputStream(OutputStream out,int size):指定size缓冲区大小构造缓冲输出流对象
* IllegalArgumentException- 如果 size <= 0
*
* 写数据的方式:
* 一次写一个字节
* write(int by)
* 一次写一个字节数组的一部分
* write(byte[] b,int off, int len)
*
* 方法:
* void flush() ;刷新缓冲区的流
*
* 面试题:
* 字节缓冲输出流它的构造方法为什么不能直接传递路径/文件?
* 缓冲输入流/缓冲输出流,它只是在底层内部提供一个缓冲区的数组,
* 底层实现文件的复制/读取/写入这些操作都依赖于基本流对象来操作
示例
//构造一个字节缓冲输出流对象
//publicBufferedOutputStream(OutputStream out)
/*OutputStreamout = new FileOutputStream("out.txt") ;
BufferedOutputStreambos = new BufferedOutputStream(out) ;*/
//符合Java一种设计模式:装饰者设计模式(过滤器:Filter)
BufferedOutputStreambos = new BufferedOutputStream(new FileOutputStream("bos.txt")) ;
//写数据
bos.write("hello".getBytes());
//释放资源
bos.close();
3)
1.字符转换输入流:InputStreamReader
*InputStreamReader(InputStream in) :构造一个字符转换输入流,默认编码
*public InputStreamReader(InputStreamin,Charset cs) 构造一个字符转换输入流,指定编码
*字符转换输入流=字节流+编码格式
*/
InputStreamReader isr = newInputStreamReader(new FileInputStream("osw.txt") ;
InputStreamReader isr = newInputStreamReader(new FileInputStream("osw.txt"),"gbk") ;
2.字符转换输出流
构造方法
*public OutputStreamWriter(OutputStream out):使用默认的编码格式构造一个字符转换输出流对象
*public OutputStreamWriter(OutputStream out, Charset cs):使用指定编码格式构造一个字符转换输出流对象
转换流的对象的创建,格式比较长,非常麻烦,Java--->转换流的便捷类
4)
1. 便捷类:FileReader,
Reader:抽象类:字符输入流
* inputStreamReader(字符转换输入流:inputStream+编码格式)
* 便捷类:FileReader,这个类可以直接对文件进行操作
*字符输入流读数据的方法:
* int read(char[] chs):读取一个字符数组
* int read():读取单个字符
*
2.便捷类FileWriter,
Writer:抽象类:字符输出流
* outputStreamWriter(字符转换输出流:outputStream+编码格式)
* 便捷类:FileWriter,这个类可以直接对文件进行操作
*字符输出流写数据的功能:
* public void write(int c):写单个字符
* public void write(char[] cbuf):写字符数组
* public abstract void write(char[] cbuf, intoff, int len):写字符数组的一部分
* public void write(String str):写字符串
* public void write(String str,int off, intlen):写字符串的某一部分
示例
//读取当前项目下的StringDemo.java文件
FileReaderfr = new FileReader("StringDemo.java") ;
/创建字符输出流对象
FileWriterfw = new FileWriter("fw.txt") ;
//字符流中的close:关闭该流的同时,之前一定要刷新流
*flush和close方法的区别?
* close:关闭该流,关闭该流对象以及它关联的资源文件,关闭之后,不能再对流对象进行操作了,否则会有异常
* flush:刷新该流,为了防止一些文件(图片文件/音频文件),缺失,或者没有加载到流对象中,刷新了该流,还是可以流对象进行操作
5)
1.字符缓冲输出流:
* 特有功能:public voidnewLine():写入一个行的分隔符号
bw.write("\r\n");//写入换行符号
bw.newLine();//换行
BufferedWrier:文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入
* 构造方法
* BufferedWriter(Writer out):默认缓冲区大小构造字符缓冲输出流对象
* BufferedWriter(Writerout,int size):指定缓冲区大小
//创建一个字符缓冲输出流对象
BufferedWriterbw = new BufferedWriter(new FileWriter("bw.txt")) ;
2.字符缓冲输入流:
*特有功能: public String readLine():一次读取一行
构造方法
* public BufferedReader(Reader in)创建一个使用默认大小输入缓冲区的缓冲字符输入流。
* public BufferedReader(Reader in, intsz)创建一个使用指定大小输入缓冲区的缓冲字符输入流。
//创建字符缓冲输入流对象
BufferedReaderbr = new BufferedReader(new FileReader("bw.txt"));
4.其他流
①内存操作流:适用于临时存储文件.(该流不需要关闭)
内存操作输入流:byteArrayInputStream
ByteArrayInputStream(byte[]buf)
内存操作输出流: byteArrayOutputStream
构造方法:ByteArrayOutputStream()
内存操作流:一个程序结束后,那么这些程序的变量,就会从内存消失(马上消失的这些数据进行读取写入)
//创建内存操作输入流对象
ByteArrayInputStream bais = newByteArrayInputStream(bys) ;
//创建内存操作输出流对象
ByteArrayOutputStream baos = newByteArrayOutputStream() ;
②打印流
字符打印流(针对文本进行操作:PrintWriter)
字节打印流(printStream 和标准输出流有关系 System.out;)
PrintWriter:属于输出流
1)只能写数据(只能针对目的地文件进行操作),不能读数据(不能针对源文件进行操作)
2)可以针对文件直接进行操作
如果一个类中的构造方法里面有File对象或者String类型数据,这个类可以对文本文件直接操作
FileInputStream
FileOutputStream
FileWriter
FileReader..
PrintWriter
3)自动刷新功能::PrintWriter(OutputStream out/Writer out,boolean autoflush);第二个参数如果是true 表示启动自动刷新功能
4)打印的方法:print(XXX x)/println(XXX xx)
示例
//创建一个字符打印流对象
PrintWriter pw = new PrintWriter(newFileWriter("pw.txt")) ;
/*创建一个字符打印流对象,启动自动刷新
PrintWriter pw = new PrintWriter(newFileWriter("pw2.txt"), true) ;*/
//写数据
/*pw.write("hello");
pw.write("world");
pw.write("java");*/
pw.println("hello");//本身自动换行并且向pw.txt文件打印内容
pw.flush(); //本身在构造的时候,就可以启动自动刷新
//关闭流
pw.close();
③数据流:针对Java基本类型的数据进行读写操作
*数据输入流:DataInputStream
*数据输出流:DataOutputStream
示例
DataOutputStream dos= new DataOutputStream(newFileOutputStream("dos.txt")) ;
//给流中写入数据
dos.writeInt(10);
dos.writeShort(100);
dos.writeByte(120);
dos.writeDouble(13.34);
dos.writeFloat(12.56F);
dos.writeBoolean(true);
dos.writeChar('a');
//读
DataInputStream dis= new DataInputStream(newFileInputStream("dos.txt")) ;
inti = dis.readInt() ;
shorts = dis.readShort() ;
byteb = dis.readByte() ;
doubled = dis.readDouble() ;
floatf = dis.readFloat();
booleanflag = dis.readBoolean() ;
charch = dis.readChar() ;
dis.close();
System.out.println(i);
System.out.println("---------");
System.out.println(s);
System.out.println(b);
System.out.println(d);
System.out.println(f);
System.out.println(flag);
System.out.println(ch);
④合并流
SequenceInputStream表示其他输入流的逻辑串联
构造方法
1.publicSequenceInputStream(InputStream s1, InputStream s2)
示例
//封装源文件
InputStream in1 = newFileInputStream("StringDemo.java") ;
InputStream in2 = new FileInputStream("SystemInDemo.java");
//创建合并流对象
SequenceInputStream sis = newSequenceInputStream(in1, in2) ;
//创建一个字节缓冲输入流对象
BufferedOutputStream bos = newBufferedOutputStream(
newFileOutputStream("Copy.java"));
//原来怎么读写,现在依然这样读写
byte[] bys = new byte[1024] ;
int len = 0 ;
while((len=sis.read(bys))!=-1) {
bos.write(bys, 0, len);
bos.flush(); //读图片文件的时候
}
//关闭资源
sis.close();
bos.close();
*sequenceInputStream另一种构造方式
2.public SequenceInputStream(Enumeration e)
*
* 将多个输入流对象进行合并
* a.txt+b.txt+c.txt--->d.txt
示例
//定义一个集合Vector
Vector<InputStream>v = new Vector<InputStream>();
//使用InputStream封装文件
InputStream s1 = newFileInputStream("StringDemo.java") ;
InputStream s2 = newFileInputStream("SystemInDemo.java") ;
InputStream s3 = newFileInputStream("PrintWriterDemo.java") ;
//将流对象添加到集合中
v.add(s1) ;
v.add(s2) ;
v.add(s3) ;
//特有功能
Enumeration<InputStream> en =v.elements() ;
//创建合并输入流对象
SequenceInputStream sis = new SequenceInputStream(en);
//创建字节缓冲输出流对象
BufferedOutputStream bos = newBufferedOutputStream(new FileOutputStream("Copy.java")) ;
//一次读取一个字节数组
byte[] bys = new byte[1024] ;
int len = 0 ;
while((len=sis.read(bys))!=-1) {
bos.write(bys, 0, len);
bos.flush();
}
//关闭资源
bos.close();
sis.close();
⑤标准的输入输出流
* InputStreamin = System.in
* PrintStreamout = Syste.out ;
*
*jdk5以后,Java--->Scanner(InputStream in)
*
* 键盘录入
* 1)Scanner
* 2)BufferedReader里面包装字符转换输入流,包装System.in
标准输出流
PrintStream ps =System.out ;
//PrintStream的功能
//public void println(String x)
ps.println("我爱高圆圆");
ps.println();
// ps.print() ;没有该功能
标准输入流
//创建输入流对象
InputStream in = System.in ;
//使用这个类最终可不可实现一次读取一行?readLine()
//想要实现一次读取一行,使用BufferedReader
//构造一个字符转换输入流对象
InputStreamReader isr = newInputStreamReader(in) ;
BufferedReader br = newBufferedReader(isr) ;
/*构造BufferedReader流对象
BufferedReader br = newBufferedReader(in) ; //不能直接将字节流使用BufferedReader进行包装*/
⑥序列化:将对象按照流的方式存储到文本文件中或者再网络中传输 对象---->流数据序列化流 (ObjectOutputStream)
反序列化:将文本文件中的流对象或者网络传输中的流对象还原成对象 流数据--->对象 反序列化流(ObjectInputStream)
示例
//反序列化 将文本文件中的流对象或者网络传输中的流对象还原成对象
private static void read() throwsFileNotFoundException, IOException, ClassNotFoundException {
//创建反序列化流对象
//public ObjectInputStream(InputStreamin)
ObjectInputStream in = newObjectInputStream(new FileInputStream("oos.txt")) ;
//读
//publicfinal Object readObject():从 ObjectInputStream 读取对象。
Objectobj = in.readObject() ;
in.close();
System.out.println(obj);//Person [name=高圆圆, age=27]
}
//序列化 将对象按照流的方式存储到文本文件中或者再网络中
private static void write() throwsFileNotFoundException, IOException {
//创建一个序列化流对象
//public ObjectOutputStream(OutputStreamout)
ObjectOutputStream oos = newObjectOutputStream(new FileOutputStream("oos.txt")) ;
//创建一个Person类对象
Person p = new Person("高圆圆", 27) ;
//publicfinal void writeObject(Object obj)
oos.writeObject(p);
//关闭资源
oos.close();
5. Properties:表示了一个持久的属性集(简称:属性集合类)
1.Properties:表示了一个持久的属性集(简称:属性集合类) extends Hashtable<K,V>
Map集合的
* 可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串。
* public Properties():无参构造
//创建一个属性集合类对象
// Properties<String,String> prop = newProperties<String,String>() ;错误的构造方式
Properties prop = new Properties() ;
System.out.println(prop);
System.out.println("---------------------");
//给属性集合类中的属性列表添加元素
prop.put("高圆圆", "赵又廷") ;
prop.put("文章", "马伊琍") ;
prop.put("黄晓明", "baby") ;
System.out.println(prop);
//遍历属性集合类
Set<Object> keySet = prop.keySet();
for(Object key :keySet) {
Object value = prop.get(key) ;
System.out.println(key+"="+value);
}
2.属性集合类的特有功能:
publicObject setProperty(String key, String value) :给属性列表中添加键和值,并且强制都使用String,相当于put();
publicSet<String> stringPropertyNames():遍历的功能,相当于keySet();
publicString getProperty(String key)用指定的键在此属性列表中搜索属性,相当于get(key);
//遍历
//获取所有的键的集合
Set<String>keyset = prop.stringPropertyNames() ;
for(String key:keyset) {
//通过键找值
Stringvalue = prop.getProperty(key) ;
System.out.println(key+"----"+value);
3.可保存在流中或从流中加载,只能使用属性集合类
* public void store(Writer writer,Stringcomments):把集合中的数据保存文本文件中(属性集合)
* publicvoid load(Reader reader):将文本文件中的数据加载到属性集合中
示例
//将文本文件中的数据加载属性集合类中
private static void MyLoad() throwsIOException {
//创建属性集合类对象
Properties prop =new Properties() ;
//public void load(Reader reader):将文本文件中的数据加载到属性集合中
FileReader fr = new FileReader("prop.txt");
//加载
prop.load(fr);
fr.close();
System.out.println(prop);
}
//将属性集合中的数据保存到文本文件中
private static void MyStore() throwsIOException {
//创建一个属性集合类对象
Properties prop = new Properties() ;
//添加元素
prop.setProperty("张三", "20") ;
prop.setProperty("文章", "29") ;
prop.setProperty("成龙", "55") ;
//public void store(Writer writer,Stringcomments):把集合中的数据保存文本文件中(属性集合)
FileWriter fw = newFileWriter("name.txt") ;
//将数据保存到文本文件中
prop.store(fw, "names'content");
//释放资源
fw.close();
6.多线程
我们学习多线程,首先先学习什么是进程,线程依赖于进程存在
进程:系统可以进行独立调配并且是一个不可分割 独立单元
开启一个任务管理器,很多进程(应用软件/某些客户端)
什么是多进程?
多进程的意义:是为了提高CPU的使用率
现在计算机都是多进程,假设:在听音乐的同时,也在打游戏..,他们是同时进行的吗?
他们不是同时进行的,感觉同时,一点点CPU的时间片在同一个时刻在两个进程之间进行高效的切换!
什么是线程?
线程:进程的一个独立的单元
一个进程里面有多个任务,把每一个任务看成一个线程
多线程:
线程之间在抢占CPU的执行权(抢占资源)
多线程的执行具有随机性
举例"
打篮球:1v1 两个人抢占篮球的几率同样大
1v5 5个人抢占篮球的几率大,并不能说一定抢到 (随机性的)
JVM:Java虚拟机 识别main(主线程)
面试题:
JVM是多线程程序吗?至少有几条线程..
jvm是多线程的,
至少有2条线程...
有主线程,main..执行这些代码,能够被Jvm识别
在执行一些程序的时候,一些对象Jvm释放掉,原因,
它开启了垃圾回收线程,里面GC:垃圾回收器(回收一些没有更多引用的对象或者变量...)
如何实现多线程程序呢?
要实现多线程程序,需要开启进程,
开启进程,是需要创建系统资源,但是Java语言不能创建系统资源
只有C/C++可以创建系统资源, 利用c语言创建好的系统资源实现
Java提供了一个类:Thread类
实现多线程程序的步骤:
1)将类声明为 Thread 的子类
2)该子类应重写 Thread 类的 run 方法
3)在主线程进行该自定义的线程类的对象的创建
并行和并发(高并发:MyBatis --->IBatis:半自动化)
前者的同时,指的是同一个时间点
后者的同时,指的是同一个时间段,宏观上体现为同时,微观上不是同时
示例
public classMyThread extends Thread {
@Override
public void run() {
// System.out.println("helloworld");
for(int x = 0 ;x <200; x ++) { //两个线程都需要执行这个代码
System.out.println(x);
}
}
-------------------------------------------------------------
public staticvoid main(String[] args) {
//创建MyThread类对象
// MyThread my = new MyThread() ;
//当前Thread类有一个run public void run()
// my.run();
// System.out.println("-------------------");
// my.run();
//执行线程不是run方法 ,run方法的调用相当于一个普通方法的调用
/*publicvoid start()使该线程开始执行;Java 虚拟机调用该线程的 run 方法。
结果是两个线程并发地运行*/
MyThread t1 = new MyThread() ;
t1.start();
//IllegalThreadStateException:非法状态异常,同一个线程只能被执行一次
// t1.start();
MyThread t2 = new MyThread() ;
t2.start();
}
Thread类提供了一些方法
* publicfinal void setName(String name):给线程起名称
* publicfinal String getName() :获取线程名称
Thread类中提供另一个功能:
//publicstatic Thread currentThread():返回当前正在执行的线程对象的引用
publicfinal void setDaemon(boolean on) :true时,表示为守护线程
* 将该线程标记为守护线程或用户线程。当正在运行的线程都是守护线程时,Java 虚拟机退出。(守护线程不会立即结束掉,它会执行一段时间在结束掉)
* 该方法必须在启动线程前调用。
跟线程优先级相关的方法:
public final int getPriority()返回线程的优先级。
public final void setPriority(intnewPriority)更改线程的优先级
线程存在一个默认优先级
public static final int MAX_PRIORITY 10 最大优先级
public static final int MIN_PRIORITY 1 最小优先级
public static final int NORM_PRIORITY 5 默认优先级
publicfinal void join():等待该线程终止 有interruputedException 中断异常
publicstatic void sleep(long millis):线程睡眠指定是时间毫秒值 throws InterruptedException
*publicfinal void stop() ;强迫线程停止执行。 不会执行了 (过时了),方法能使用的
publicstatic void yield()暂停当前正在执行的线程对象,并执行其他线程
两个区别?
public final voidstop() ;强迫线程停止执行。 不会执行了 (过时了),方法能使用的
public voidinterrupt()中断线程。 表示中断线程的一种状态
面试题
wait()和sleep()区别?
wait(): wait()调用的,立即释放锁 (同步锁/Lock锁)
sleep(): 线程睡眠,调用不会释放锁
实现多线程程序的第二种方式:
1)自定义一个类,实现Runnable接口
2)实现接口中的run方法,对耗时的代码进行操作
3)然后在主线程中创建该类对象,将该类对象做为一个资源类,创建Thread类的对象,将刚才的资源类作为参数进行传递
示例
//自定义类实现接口,实现run方法
public classMyThread implements Runnable {
@Override
public void run() {
for(int x= 0; x <100 ; x ++) {
// System.out.println(getName()+":"+x);错误的
System.out.println(Thread.currentThread().getName()+":"+x);
}
}
}
public staticvoid main(String[] args) {
//创建当前类对象
MyThread my =new MyThread() ;
//实现多线程
//public Thread(Runnable target,Stringname)
Thread t1 = new Thread(my, "高圆圆") ;
Thread t2 = new Thread(my, "赵又廷") ;
//启动线程
t1.start();
t2.start();
}