0%

利用主线程控制子线程

通知

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package windowSale;

/**
* @author zss
*/
public class WindowSale1 {
public static int countTicket=10;

public static void main(String[] args) {
Window1 window1 = new Window1();
Thread thread=new Thread(window1);
thread.start();
while (true){
if (countTicket<=5){
System.out.println("小于5张,请停止售票");
window1.setJudge(false);
break;
}
else {System.out.println("不要停下来");}
try{
Thread.sleep(50);
}catch (InterruptedException interruptedException){
interruptedException.printStackTrace();
}
}

}
}
class Window1 implements Runnable{
private boolean judge=true;
@Override
public void run() {
while (judge){
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"售卖一张票");
WindowSale1.countTicket=WindowSale1.countTicket-1;
System.out.println("还剩"+WindowSale1.countTicket);
}
}

public void setJudge(boolean judge) {
this.judge = judge;
}
}

image-20220317153122728

线程常用的方法

setName 设置线程的名称,使之与参数name相同

start方法,线程开始执行,Java虚拟机底层调用该线程的start0方法

run调用线程的run方法

setPriority更改线程的优先级

getPriority获得线程的优先级

interrupt中断线程,并不是真正的结束线程,送一一般用于中断休眠的线程

yield:线程的礼让,让出cpu,让其他线程执行,但是礼让的时间不确定,所以不一定成功。资源紧张时成功概率比较大。

join:线程的插队,插队线程一旦插队成功,则肯定先执行完线程所有的任务

可以看出猪猪1吃包子的时候

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
/**
* @author zss
*/

public class Test {
public static void main(String[] args) throws InterruptedException {
Pig pig=new Pig();
Pig1 pig1=new Pig1();
Thread thread=new Thread(pig);
Thread thread1=new Thread(pig1);
thread.setName("猪猪");
thread1.setName("猪猪1");
thread.start();
thread1.start();
thread1.join();
//thread.setPriority(10);
Thread.sleep(10000);
System.out.println("老虎来了");
thread.interrupt();
thread1.interrupt();

}
}

class Pig implements Runnable{

@Override
public void run() {
while (true) {
System.out.println("猪猪吃包子");
try {
System.out.println("猪猪睡觉");
Thread.sleep(2000);
} catch (InterruptedException interruptedException) {
System.out.println("猪猪快跑,发生了异常");
break;
}
}
}
}

class Pig1 implements Runnable {

@Override
public void run() {
System.out.println("猪猪1吃包子");
System.out.println("猪猪1睡觉");
for (int i=0;i<5;i++){
System.out.println(i);
}
}
}


image-20220317161904334

练习

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/**
* @author zss
*/
public class Test {
public static void main(String[] args) throws InterruptedException {
int j=0;
while (true){
System.out.println(j);
j++;
if(j==5){
A a=new A();
a.start();
a.join();
System.out.println("子线程结束");
}
if (j==10){
System.out.println("主线程结束");
break;
}
}

}


}
class A extends Thread{
@Override
public void run(){
for (int i=0;i<10;i++){
System.out.println(i);
}
}
}

image-20220317163034660

用户线程与守护线程

用户线程:也叫工作线程,当线程的任务执行完或通知方式结束

守护线程:一般为工作线程服务,当所有用户线程结束,守护线程自动结束,比如垃圾回收机制。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
* @author zss
*/
public class Test {
public static void main(String[] args) throws InterruptedException {
MyDaemonThread myDaemonThread=new MyDaemonThread();
myDaemonThread.setDaemon(true);
myDaemonThread.start();
for (int i=0;i<10;i++){
Thread.sleep(100);
System.out.println("主线程运行中");
}
}
}
class MyDaemonThread extends Thread{
@Override
public void run() {
while (true){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("守护线程运行中");
}
}
}

在守护线程我们没有设计结束的标志,但是守护线程自动结束。

基本介绍

接口就是给出一次额没有实现的方法,封装到一起,到某个类要使用的时候,根据具体的情况把这些方法写出来。

语法:interface 接口名{

属性+方法

}

class 类名 implements 接口{

自己的属性//方法

}

注意:在jdk7以前都没有接口中的方法都没有方法体,而在8.0之后可以有静态方法,默认方法(需要用default进行标记),也就是说接口中有方法的具体实现,在接口中抽象方法可以进行省略。

1
2
3
4
5
6
7
8
9
10
public interface InterfaxeTest {
public int a=10;
public int sum();
default public void hi(){
System.out.println("你好");
}
public static void ok(){
System.out.println("OK");
}
}

接口的简单用法

  • 规范我们的书写,方便调用。比如,我们现需要写出三个类,分别链接mysql数据库,oracle数据库。我们程序员1写的链接mysql数据库链接方法定义为f1,断开为f2。而程序员2写的链接oracle数据库的方法为connect,与close方法。这样会导致我们使用不同的数据库时,调用函数的麻烦,但是当我我们使用接口,就可以规范每一个的命名,举个简单例子:
1
2
3
4
5
6
public interface DBInterface {
/**定义链接方法*/
public void connect();
/**定义关闭方法*/
public void stop();
}
1
2
3
4
5
6
7
8
9
10
11
public class Oracle implements DBInterface{
@Override
public void connect() {
System.out.println("链接oracle数据库");
}

@Override
public void stop() {
System.out.println("断开链接oracle数据库");
}
}
1
2
3
4
5
6
7
8
9
10
11
public class MySql implements DBInterface{
@Override
public void connect() {
System.out.println("链接mysql数据库");
}

@Override
public void stop() {
System.out.println("断开链接mysql数据库");
}
}
1
2
3
4
5
6
7
8
public class Test {
public static void main(String[] args) {
MySql mySql = new MySql();
mySql.connect();
mySql.stop();
}

}

接口的注意事项

  • 接口本身并不能被实例化
  • 接口中所有方法都为public方法,接口中的抽象方法,可以不用abstract修饰
  • 一个类继承该接口,就必须实现接口的所有方法
  • 一个类可以实现多个接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Oracle implements DBInterface,InterfaxeTest{
@Override
public void connect() {
System.out.println("链接oracle数据库");
}

@Override
public void stop() {
System.out.println("断开链接oracle数据库");
}

@Override
public int sum() {
return 0;
}

@Override
public void hi() {
InterfaxeTest.super.hi();
}
}
  • 接口中的属性只能是final,而且是public static final修饰符,比如int a=1;实际上为public static int a=1;

证明:

我们在刚才的接口中定义int a=0;

在main方法中输出如下;如果不报错并且可以正常输出,说明这个为public并且为static,我们并没有创建实例化对象。而final只需要我们尝试改变以下值即可。

1
2
3
4
5
6
7
public class Test {
public static void main(String[] args) {
System.out.println(MySql.a);

}

}

做个练习:

1
2
3
4
5
6
7
8
public class Test {
public static void main(String[] args) {
System.out.println(DBInterface.a);
System.out.println(MySql.a);
MySql mySql=new MySql();
System.out.println(mySql.a);
}
}

实现接口VS继承类

  • 首先继承关系我们可以自然的使用父类的功能,而不需要去重写,比如下面的一段的代码,monkey本身的本领就可以爬树,是从父辈上继承过来,而不需要去学习。但是如果悟空还想要飞翔则需要继承一个接口,提供相应的功能,同样悟空还可以学习更多的技能,也就需要更多的接口。
1
2
3
4
public interface Bird {
/**小鸟飞翔的功能*/
public void fly();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class Test {
public static void main(String[] args) {
Monkey monkey=new Monkey("悟空爸爸");
monkey.climbing();
LittleMonkey littleMonkey = new LittleMonkey("悟空");
littleMonkey.climbing();
littleMonkey.fly();
}
}
class Monkey{
private String name;
public Monkey(String name){
this.name=name;
}
public void climbing(){
System.out.println(name+"会爬树");
}
public String getName(){
return name;
}
}
class LittleMonkey extends Monkey implements Bird{
public LittleMonkey(String name){
super(name);
}
@Override
public void fly(){
System.out.println(getName()+"经过努力,学会了腾云驾雾");
}
}
  • 接口和我们Java类中的虚拟类很相似,但是接口可以定义static方法,而虚拟类不可以定义static方法。

接口的多态

  • 多态参数

就像我们现实生活中电脑的usb接口,我们既可以接受手机对象,又可以接受相机对象,等等,体现了接口的多态,查看以下代码

接口:

1
2
3
4
5
6
package InterfaceM;

public interface Interface {
public void join();
public void stop();
}

手机类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package InterfaceM;

public class Phone implements Interface{

@Override
public void join() {
System.out.println(this.toString()+"接入了电脑");
}

@Override
public void stop() {
System.out.println(this.toString()+"离开了电脑");
}
}

相机类;

1
2
3
4
5
6
7
8
9
10
11
12
13
package InterfaceM;

public class Camera implements Interface {
@Override
public void join() {
System.out.println(this.toString()+"接入了电脑");
}

@Override
public void stop() {
System.out.println(this.toString()+"离开了电脑");
}
}

电脑类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package InterfaceM;

public class Computer {
public void work(Interface interF){
interF.join();
interF.stop();
}

public static void main(String[] args) {
Camera camera=new Camera();
Phone phone=new Phone();
//将相机接入电脑
Computer computer=new Computer();
computer.work(camera);
computer.work(phone);
}
}
  • 多态数组

在computer类型的数组中,我们即可以存放多种对象类型的数组。而且对应不同的数组对象,我们可以做出不同的事件。

在刚才的上述代码中我们在phone类中加入call功能,要求有插入phone时,调用call函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package InterfaceM;

public class Computer {
public void work(Interface interF){
interF.join();
interF.stop();
}

public static void main(String[] args) {
Camera camera=new Camera();
Phone phone=new Phone();
//将相机接入电脑
Interface []interf=new Interface[2];
interf[0]=camera;
interf[1]=phone;
Computer computer=new Computer();
for (int i=0;i<interf.length;i++){
computer.work(interf[i]);
if (interf[i]instanceof Phone){
phone.call();
}
}
}
}
  • 接口的多态传递现象

如果我们运行以下代码,由于ih并没有被teacher继承,会发生报错,但是当我们用ig继承ih之后,我们可以发现这样就不会报错。这样体现出了多态的继承传递现象。

1
2
3
4
5
6
7
8
9
10
11
public class Test {
public static void main(String[] args) {
IG ig=new Teacher();
IH ih=new Teacher();
}
}
interface IH{}
interface IG{}
class Teacher implements IG{

}
1
2
3
4
5
6
7
8
9
10
11
public class Test {
public static void main(String[] args) {
IG ig=new Teacher();
IH ih=new Teacher();
}
}
interface IH{}
interface IG extends IH{}
class Teacher implements IG{

}

打印流以及Properties

字节打印流

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import java.io.*;
import java.nio.charset.StandardCharsets;

/**
* @author zss
*/
public class Test {
public static void main(String[] args) throws IOException {
PrintStream out=System.out;
//默认打印在显示器上
out.println("join,hello");
//out底层调用的是write,所以可以直接调用write进行输出
out.write("你好啊".getBytes(StandardCharsets.UTF_8));
//我们也可以更改打印的位置
System.setOut(new PrintStream("D:\\文件下载\\hello.txt"));
//在文件中显示
System.out.println("hello");
out.close();
}
}

字符打印流

1
2
3
4
5
6
7
8
9
10
11
12
13
import java.io.*;
import java.nio.charset.StandardCharsets;

/**
* @author zss
*/
public class Test {
public static void main(String[] args) throws IOException {
PrintWriter printWriter=new PrintWriter(new FileWriter("D:\\文件下载\\hello.txt"));
printWriter.println("你好啊");
printWriter.close();
}
}

Properties

传统方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import java.io.*;

/**
* @author zss
*/
public class Test {
public static void main(String[] args) throws IOException {
BufferedReader bufferedReader=new BufferedReader( new FileReader("src\\Information.properties"));
String line;
while ((line=bufferedReader.readLine())!=null){
String []split=line.split("=");
System.out.println(split[0]+"的值"+split[1]);
}
bufferedReader.close();
}
}

image-20220703171201137

使用Properties类

专门用于读写配置文件的集合类,配置文件的格式:

键=值,键值对不需要有空格,值不需要用引号,默认为String类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import java.io.*;
import java.util.Properties;

/**
* @author zss
*/
public class Test {
public static void main(String[] args) throws IOException {
//创建Properties类来读取文件
Properties properties=new Properties();
//加载指定配置的文件
properties.load(new FileReader("src\\Information.properties"));
//KV显示在控制台
properties.list(System.out);
//根据key获取相应的值
String user= properties.getProperty("user");
System.out.println(user);
//修改相应的文件
properties.setProperty("password","55555");
properties.list(System.out);

}
}

image-20220703171313929

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import java.io.*;
import java.util.Properties;

/**
* @author zss
*/
public class Test {
public static void main(String[] args) throws IOException {
//创建Properties类来读取文件
Properties properties=new Properties();
properties.setProperty("password","55555");
properties.setProperty("user","zss");
properties.setProperty("id","11");
//注释效果
properties.store(new FileOutputStream("src\\test.properties"),"hello");

}

}

image-20220703171913787

练习

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import java.io.*;
import java.util.Properties;

/**
* @author zss
*/
public class Test {
public static void main(String[] args) throws IOException, ClassNotFoundException {
Properties properties=new Properties();
properties.load(new FileReader("src\\test.properties"));
Employee employee=new Employee(properties.getProperty("user"),Integer.parseInt(properties.getProperty("id")), properties.getProperty("password") );
System.out.println(employee);
ObjectOutputStream objectOutputStream=new ObjectOutputStream(new FileOutputStream("D:\\文件下载\\test.dat"));
objectOutputStream.writeObject(employee);
objectOutputStream.close();
ObjectInputStream objectInputStream=new ObjectInputStream(new FileInputStream("D:\\文件下载\\test.dat"));
Employee employee1=(Employee) objectInputStream.readObject();
System.out.println(employee1);
objectInputStream.close();

}
}
class Employee implements Serializable{
String user;
int id;
String password;

public Employee(String user, int id, String password) {
this.user = user;
this.id = id;
this.password = password;
}

@Override
public String toString() {
return "Employee{" +
"user='" + user + '\'' +
", id=" + id +
", password='" + password + '\'' +
'}';
}
}


image-20220703171940795

文件字符流

FileReader

read每一次读取单个字符,返回该字符,如果到文件末尾则返回-

read(char[ ]):批量读取多个字符到数组,返回读取到的字符数,如果到文件末尾返回-

new String(char[] )将char[]转换成String

new String(char[],off,len):将char[]的指定部分转换为String

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.io.FileReader;
import java.io.IOException;

/**
* @author zss
*/
public class Test {
public static void main(String[] args) throws IOException {
Test test=new Test();
test.fileReader();
}
public void fileReader() throws IOException {
String filePath="D:\\壁纸\\hello.txt";
FileReader fileReader=new FileReader(filePath);
int flag;
while ((flag=fileReader.read())!=-1){
System.out.print((char)flag);
}
fileReader.close();
}
}
1
2
3
4
char []buff=new char[5];
while ((flag=fileReader.read(buff))!=-1){
System.out.print(new String(buff,0, buff.length));
}

image-20220703170939054

FileWrite

在这里也可以分别使用追加模式和覆盖模式,在构造器中加入true可以使其在尾端加上

当我们使用之后,必须关闭该对象或者刷新,否则这个不会到文件中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

/**
* @author zss
*/
public class Test {
public static void main(String[] args) throws IOException {
Test test=new Test();
test.fileWrite();
}
public void fileWrite() throws IOException {
String filePath="D:\\壁纸\\hello.txt";
FileWriter fileWriter=new FileWriter(filePath,true);
String content="风雨之后,即见彩虹";
fileWriter.write(content);
fileWriter.write(content,1,3);
fileWriter.write('g');
//fileWriter.flush();
fileWriter.close();
}
}

标准的输入输出流与转换流

标准的输入输出流

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import java.io.*;

/**
* @author zss
*/
public class Test {
public static void main(String[] args) {
//标准输入流,编译类型为InputStream,而运行类型为BufferInputStream
System.out.println(System.in.getClass());

//标准输出流,编译类型为PrintStream,运行类型为PrintStream
System.out.println(System.out.getClass());

}
}

image-20220703173029581

转换流

可以将字节流转换为字符流,解决文件乱码的问题,默认情况下按照utf-8编码进行阅读的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import java.io.*;

/**
* @author zss
*/
public class Test {
public static void main(String[] args) throws IOException {
String filePath="D:\\文件下载\\hello.txt";
BufferedReader bufferedReader=new BufferedReader(new FileReader(filePath));
String line;
while ((line=bufferedReader.readLine())!=null){
System.out.println(line);
}
bufferedReader.close();
}
}

image-20220703173043100

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import java.io.*;

/**
* @author zss
*/
public class Test {
public static void main(String[] args) throws IOException {
String filePath="D:\\文件下载\\hello.txt";
//首先利用放入到InputStreamReader可以设置编码格式的构造函数,构造成这样
InputStreamReader inputStreamReader=new InputStreamReader(new FileInputStream(filePath),"gbk");
//然后在使用BufferedReader去重新接受
BufferedReader bufferedReader=new BufferedReader(inputStreamReader);
String line;
while ((line=bufferedReader.readLine())!=null){
System.out.println(line);
}
bufferedReader.close();
}
}

image-20220703173051761

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import java.io.*;
import java.nio.charset.StandardCharsets;

/**
* @author zss
*/
public class Test {
public static void main(String[] args) throws IOException {
String filePath="D:\\文件下载\\hello.txt";
OutputStreamWriter outputStreamWriter=new OutputStreamWriter(new FileOutputStream(filePath), StandardCharsets.UTF_8);
BufferedWriter bufferedWriter=new BufferedWriter(outputStreamWriter);
bufferedWriter.write("你好啊");
bufferedWriter.close();
}
}

处理流与其实现类

节点流

节点流可以从一个特定的数据源读写程序,比如FileReader等

处理流

处理流(包装流)是连接已经存在的流(节点流或处理流之上),为程序提供更加强大的读写功能,比如BufferedReader、BufferedWriter

image-20220703171033084

上面含有一个Reader,可以对节点流进行包装,只要是reader的子类即可,对文件,数组,数据源等都可以进行相应的操作,关闭处理流的时候只需要关闭处理流即可,处理流调用节点流的close,自动关闭。如果想要以追加的方式写入,只需要在节点流哪里true即可,尽量不要使用该方法操作二进制文件,会造成文件损毁。

字节处理流

BufferReader

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

/**
* @author zss
*/
public class Test {
public static void main(String[] args) throws IOException {
String filePath="D:\\壁纸\\hello.txt";
BufferedReader bufferedReader=null;
try {
bufferedReader = new BufferedReader(new FileReader(filePath));
/*按行读取*/
String line;

/*当返回空时,结束读取*/
while ((line = bufferedReader.readLine()) != null) {
System.out.println(line);
}
}catch (IOException ioException){
ioException.printStackTrace();
}finally {
bufferedReader.close();
}
}


}

BufferWriter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import java.io.*;

/**
* @author zss
*/
public class Test {
public static void main(String[] args) throws IOException {
String filePath="D:\\壁纸\\hello.txt";
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath));
bufferedWriter.write("你好啊");
//换行
bufferedWriter.newLine();
bufferedWriter.write("你好啊");
bufferedWriter.close();
}
}

练习

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import java.io.*;

/**
* @author zss
*/
public class Test {
public static void main(String[] args) throws IOException {
String filePath="D:\\壁纸\\hello.txt";
String filePath1="D:\\文件下载\\hello.txt";
BufferedReader bufferedReader=new BufferedReader(new FileReader(filePath));
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath1));
String line;
while ((line=bufferedReader.readLine())!=null){
bufferedWriter.write(line);
bufferedWriter.newLine();
}
bufferedReader.close();
bufferedWriter.close();
}
}

字节处理流

BufferInputStream,BufferOutputStream

拷贝二进制的图片

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import java.io.*;

/**
* @author zss
*/
public class Test {
public static void main(String[] args) throws IOException {
String filePath="D:\\壁纸\\彩云.png";
String filePath1="D:\\文件下载\\彩云.png";
BufferedInputStream bufferedInputStream=new BufferedInputStream(new FileInputStream(filePath));
BufferedOutputStream bufferedOutputStream=new BufferedOutputStream(new FileOutputStream(filePath1));
int flag;
while ((flag=bufferedInputStream.read())!=-1){
bufferedOutputStream.write(flag);
}
bufferedInputStream.close();
bufferedOutputStream.close();
}
}

对象处理流

比如保存int 100,而不是仅仅保存100这个数据,或者可以保存这个对象以及其相应的数据类型

序列化和反序列化

  1. 序列化就是在保存数据时,保存数据的值和数据类型
  2. 反序列化就是在恢复数据的时候,回复数据的值和数据类型
  3. 需要将某个对象支持序列化机制,则必须让其类是可序列化的,为了让某个类是可序列化的,该类必须实现如下的两个接口之一:Serializable或者Externalizable(该接口有方法需要实现)

ObjectInputStream(序列化)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import java.io.*;

/**
* @author zss
*/
public class Test {
public static void main(String[] args) throws IOException, ClassNotFoundException {
ObjectInputStream objectInputStream=new ObjectInputStream(new FileInputStream("D:\\文件下载\\test.dat"));
//反序列化的顺序要和序列化的顺序一致
System.out.println(objectInputStream.readInt());
System.out.println(objectInputStream.readUTF());
Object dog=objectInputStream.readObject();
System.out.println(dog);
objectInputStream.close();

}
}
class Dog implements Serializable{
String name;
int age;

public Dog(String name, int age) {
this.name = name;
this.age = age;
}
//如果想要输出真是的信息,则应该在序列化时就定义了tostring,当然如果我们想要调用dog的方法,则向下转型,这是需要见dog的定义可以引用到序列化的文件,而且对象的包也必须在同一个文件夹,否则我们存储的类就无法进行转换

/*@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}*/
}

image-20220703171101937

ObjectOuputStream(反序列化)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import java.io.*;

/**
* @author zss
*/
public class Excesice {
public static void main(String[] args) throws IOException {
ObjectOutputStream objectOutputStream=new ObjectOutputStream(new FileOutputStream("D:\\文件下载\\test.dat"));

/*下面的方法中调用的包装类,Integer等,本身就已经继承了Serializable接口*/
objectOutputStream.writeInt(1);
objectOutputStream.writeUTF("你好");

objectOutputStream.writeObject(new Dog("旺财",99));
objectOutputStream.close();
}
}
class Dog implements Serializable{
String name;
int age;

public Dog(String name, int age) {
this.name = name;
this.age = age;
}
}

image-20220703171119879

注意:序列化的时候,默认将所有的属性都进行了序列化,但是除了static或者transient修饰的成员。而进行序列化对象的时候,,要求属性里面的所有都实现序列化,继承接口。

流的分类

  • 按照操作数据单位不同分为:字节流(8bit)操作二进制文件不会造成损失,字符流(效率比较高,操作文本文件)
  • 按数据流的流向不同分为:输入流,输出流
  • 按流的角色的不同分为节点流,处理流/包装流
抽象基类 字节流 字符流
输入流 InputStream(抽象类) Reader
输出流 OutputStream(抽象类) Write

字节输入/输出流

image-20220703170702227

FileInputStream

image-20220703170650957

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

/**
* @author zss
*/
public class Test {
public static void main(String[] args) throws IOException {
Test test=new Test();
test.readFile1();
}
public void readFile1() throws IOException {
String filePath="D:\\文件下载\\test.txt";
FileInputStream fileInputStream=new FileInputStream(filePath);
int readDate;
try {
//从该输入读取一个字节的数据,如果没有输入可用,此方法将阻止,返回-1表示读取完毕
while ((readDate=fileInputStream.read())!=-1){
System.out.print((char)readDate);
}
}
catch (IOException ioException){
ioException.printStackTrace();
System.out.println("文件读取失败");
//最终一定要关闭这个流文件,释放资源
}finally {

fileInputStream.close();
}
System.out.println("文件读取成功");
}


}

image-20220703170526909

虽然文件读取成功,但是这里的中文是以乱码的方式出现,在utf-8中,一个中文由三个字节组成,但是这里是一次性读取一个字节,会出现乱码,而且这样的方式读取比较缓慢。

所以我们可以使用read(byte[] b)的方法来提高效率,下面这一段代码中,我们设置成3个为一组进行读取,可以正常读取出相应的值。而且效率比较高。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import java.io.FileInputStream;
import java.io.IOException;

/**
* @author zss
*/
public class Test {
public static void main(String[] args) throws IOException {
Test test=new Test();
test.readFile1();
}
public void readFile1() throws IOException {
String filePath="D:\\文件下载\\test.txt";
FileInputStream fileInputStream=new FileInputStream(filePath);
byte []buff=new byte[3];
int readLine;
try {
//从该输入读取一个字节的数据,如果没有输入可用,此方法将阻止,返回-1表示读取完毕
//如果读取正常,则返回实际读取的个数
while ((readLine=fileInputStream.read(buff))!=-1){
System.out.println(readLine);
System.out.print(new String(buff,0,readLine));
}
} finally {

fileInputStream.close();
}
System.out.println("文件读取成功");
}


}

image-20220703170633908

FileOutStream

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37


import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

/**
* @author zss
*/
public class Test {
public static void main(String[] args) throws IOException {
Test test=new Test();
test.writeFile();
}
/**将数据写入到文件中,如果文件不存在,则创建该文件*/
public void writeFile() throws IOException {
String filePath="D:\\文件下载\\test1.txt";
FileOutputStream fileOutputStream=null;
try {
fileOutputStream=new FileOutputStream(filePath);
//写入一个字节
//fileOutputStream.write('h');
//写入多个字节
String str="hello world";
//将字符串数组转成字符
//fileOutputStream.write(str.getBytes(StandardCharsets.UTF_8));
//传入一个数组
fileOutputStream.write(str.getBytes(),0,str.length());
}
catch (IOException ioException){
System.out.println("文件写出失败");
}finally {
assert fileOutputStream != null;
fileOutputStream.close();}
}
}

只是这种方法会掩盖原来的文章,如果不想要掩盖原来的文章,在构造器中,添加一个true

1
fileOutputStream=new FileOutputStream(filePath,true);

练习

将图片拷贝到另外一个文件夹

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import java.io.*;

/**
* @author zss
*/
public class Excesice {
static String picture;

public static void main(String[] args) throws IOException {
Excesice excesice = new Excesice();
excesice.copy();
}

public void copy() throws IOException {
byte[] buff = new byte[1024];
String pictureAddress = "D:\\壁纸\\彩云.png";
String pictureDenAddress="D:\\文件下载\\彩云.png";
FileInputStream fileInputStream = new FileInputStream(pictureAddress);
FileOutputStream fileOutputStream=new FileOutputStream(pictureDenAddress);
int pictureDate;
try {
while ((pictureDate = fileInputStream.read(buff)) != -1) {
/**必须使用此方法,而不可以使用fileOutputStream.write(str.getBytes(),0,str.length());,因为不知道是好结束,否则文件会发生错误*/
fileOutputStream.write(buff);
}
} catch (IOException ioException) {
System.out.println("文件访问失败");
} finally {
fileInputStream.close();
fileOutputStream.close();
}
}
}

文件

输入流:数据从数据源到程序的路径

输出流:数据从程序到数据源的路径

流:数据子啊数据源和程序之间经历的路径

创建文件

image-20220703170247406

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
import java.io.File;
import java.io.IOException;

/**
* @author zss
*/
public class Test {
public static void main(String[] args) {
Test test = new Test();
test.createFile2();
}

/**
* 方式1
*/
public void createFile() {
String filePath = "D:\\文件下载\\test.txt";
File file = new File(filePath);
try {
file.createNewFile();
} catch (IOException ioException) {
ioException.printStackTrace();
}
System.out.println("文件创建成功");
}

/**
* 方式2,在父目录创建多个文件时,此方法比较方便
*/
public void createFile1() {
File file = new File("D:\\文件下载\\");
String filename = "test2.txt";
File newFile = new File(file, filename);
//上面的几步只是表示在内存里面拥有了对象,并没有创建到内存
try {
newFile.createNewFile();
} catch (IOException io) {
io.printStackTrace();
}
}
/**方式3*/
public void createFile2() {
String parentPath="D:\\文件下载\\";
String fileName="test3.txt";
File file=new File(parentPath,fileName);
try {
System.out.println(file.createNewFile());
} catch (IOException e) {
e.printStackTrace();
}
}
}

image-20220703170203584

获取文件的相关信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import java.io.File;
import java.io.IOException;

/**
* @author zss
*/
public class Test {
public static void main(String[] args) {
Test test=new Test();
test.getInfo();
}
public void getInfo(){
File file=new File("D:\\文件下载\\test.txt");
String name=file.getName();
System.out.println(name);
//得到路径
System.out.println(file.getAbsoluteFile());
//得到父级目录
System.out.println(file.getParent());
//得到文件大小
System.out.println(file.length());
//文件是否存在
System.out.println(file.exists());
//文件是否为文件或者目录
System.out.println(file.isFile());
System.out.println(file.isDirectory());
}

}

image-20220703170223706

目录的操作文件删除

文件是否存在,以及删除

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import java.io.File;
import java.io.IOException;

/**
* @author zss
*/
public class Test {
public static void main(String[] args) {
Test test=new Test();
test.judge();
}
public void judge(){
String filePath="D:\\文件下载\\test.txt";
File file=new File(filePath);
if (file.exists()){
if (file.delete()){
System.out.println("删除成功");
}else{
System.out.println("删除失败");
}

}
else {
System.out.println("文件不存在");
}
}
}

目录是否存在以及删除,在Java中目录也是文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import java.io.File;
import java.io.IOException;

/**
* @author zss
*/
public class Test {
public static void main(String[] args) {
Test test=new Test();
test.judge();
}
public void judge(){
String filePath="D:\\文件下载\\目录";
File file=new File(filePath);
if (file.exists()){
if (file.delete()){
System.out.println("删除成功");
}else{
System.out.println("删除失败");
}

}
else {
System.out.println("目录不存在");
}
}
}

创建目录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import java.io.File;
import java.io.IOException;

/**
* @author zss
*/
public class Test {
public static void main(String[] args) {
Test test=new Test();
test.judge();
}
public void judge(){
String filePath="D:\\文件下载\\目录\\解决";
File file=new File(filePath);
if (file.exists()) {
System.out.println("目录已经存在");
}
else {
if (file.mkdirs()){
System.out.println("创建成功");
}
else {
System.out.println("创建失败");
}
}

}


}