【Java进阶篇】第六章 IO流

news2024/11/24 12:40:46

文章目录

  • 一、IO流的概述
    • 1、流
    • 2、流的分类
    • 3、Java IO流的四大块
    • 4、流的两大特性
    • 5、java.io包下的16个常用流
  • 二、文件专属流
    • 1、java.io.FileInputStream
    • 2、java.io.FileOutputStream
    • 3、java.io.FileReader
    • 4、java.io.FileWriter
  • 三、缓冲流与转换流
    • 1、java.io.BufferedReader
    • 2、java.io.BufferedWriter
    • 3、java.io.InputStreamReader
  • 四、数据流
    • 1、java.io.DataOutputStream
    • 2、java.io.DataInputStream
  • 五、标准输出流
    • 1、java.io.PrintStream
    • 2、java.io.PrintWriter
  • 六、对象专属流与File类
    • 1、File类
    • 2、File类的常用方法
    • 3、对象流
    • 4、IO与Properties联合使用

一、IO流的概述

1、流

以内存为参照,读进内存为输入,反之为输出
流

2、流的分类

🍁以流的方向进行分类:

  • 以内存为参照物,往内存中写,称为输入、Input、读
  • 从内存中出来,叫输出、Output、写

🍁按照读取数据方式不同进行分类

  • 有的流按照字节的方式读取数据,一次读取一个字节byte,即8位bit,这种流是万能的,可读取任何类型的文件,如文本、图片、声音文件、视频文件。称字节流
  • 有的流按照字符的方式读取数据,一次读取一个字符,这种流方便了对普通文本的读取,不能读取图片、声音、视频等文件,只能读取纯文本,Word文件都无法读取。称字符流

如:file.txt文件,内容:a中国bcdef,a在Windows中占一个字节,中占两个字节,则:

字符流: a–>中–>国…
字节流:a–>中字符的一半–>中的另一半

🍺Java中的IO流已经写好了,都在java.io.*下

3、Java IO流的四大块

类名是否抽象类
java.io.InputStream字节输入流
java.io.OutputStream字节输出流
java.io.Reader字符输入流
java.io.Writer字符输出流

在Java中,只要类名以Stream结尾,都是字节流。只要类名以Reader/Writer结尾的都是字符流。 如InputStreamReader即字符流

4、流的两大特性

🍁

  • 所有流都实现了java.io.Closeable接口,都是可关闭的,都有close()方法,流就像一个管道,是内存和硬盘之间的通道,用完一定要关掉,不然会占用很多资源
  • 所有的输出流都是实现了java.io.Flushable接口,都是可刷新的,都有flush()方法。输出流在最终输出后,一定要用flush()刷新下,这个刷新表示将管道/通道中剩余未输出的数据强行输出完,清空管道,没flush()可能会导致丢数据

5、java.io包下的16个常用流

常用流

二、文件专属流

1、java.io.FileInputStream

文件字节输入流,万能的,可读任何类型的文件(硬盘–>内存)

  • 通过构造方法创建文件字节输入流对象
//注意路径在IDEA中\变\\,前面那个\表示转义
//你直接手输G:/JAVA/old files也行

//直接new报错,因为有异常未处理
FileInputStream fileInputStream = new FileInputStream("G:\\JAVA\\old files");
  • read()方法

read()

try{
    fileInputStream = new FileInputStream("G:\\JAVA\\old files");
    while(true){
        int readData = fileInputStream.read();
        //读完以后返回-1
        if(readData == -1){
            break;
        }
        System.out.println(readData);
    }
}catch(FileNotFoundException e) {
   e.printStackTrace();
//处理read方法的异常
}catch(IOException e){
   e.printStackTrace();
}....

以上使用while(true) + if–break可以优化为:

int readData = 0;

while( (readData = fileInputStream.read() ) != -1){
    System.out.println(readData);
}

以上,使用read()方法从输入流中一次读取一个字节,这样内存和硬盘之间的交互太频繁,耗费不必要的资源。

  • read(byte[ ] b)方法

从输入流中将最多b.length个字节的数据先读入一个byte数组中

try{
   fileInputStream = new FileInputStream("G:\\JAVA\\test.txt");
   byte[] bytes = new byte[4];
   //注意传入数组时read返回的是读取到的字节数量
   //不是字节本身
   int readCount1 = fileInputStream.read(bytes);
   //4
   System.out.println(readCount1);
   //abcd
   System.out.println(new String(bytes));
   int readCount2 = fileInputStream.read(bytes);
   //2
   System.out.println(readCount2);
   //efcd
   System.out.println(new String(bytes));
   int readCount3 = fileInputStream.read(bytes);
   //-1,表示一个都没有读到
   System.out.println(readCount3);
   System.out.println(new String(bytes));
   ...

过程分析:
分析

运行结果:
run
程序优化:

//利用String的构造方法,传入数组,转为String
System.out.println(new String(bytes));

//改为用另一个构造方法,传入启示下标和长度
//使用readCount,即可“读到多少个,转多少个”
System.out.println(new String(bytes,0,readCount));

FileInputStream最终版代码:

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class FileInputStreamTest {
    public static void main(String[] args) {
    	//try域中的fileInputStream变量在finally域中识别不到
    	//所以在外面定义
        FileInputStream fis = null;
        try {
            fis = new FileInputStream("G:\\JAVA\\test.txt");
            byte[] bytes = new byte[6];
            int readCount = 0;
            while((readCount = fis.read(bytes)) != -1){
                System.out.println(new String(bytes,0,readCount));
            }
        }catch(FileNotFoundException e){
            e.printStackTrace();
        }catch(IOException e){
            e.printStackTrace();
        //在finally语句中确保流一定被关闭
        }finally{
        	//关闭的前提是流不为空
            if(fis != null){
                try{
                    fis.close();
                //这里处理close方法的异常
                }catch(IOException e){
                    e.printStackTrace();
                }

            }
        }
    }
}

  • FileInputStream类中的其他常用方法

🍁int available()方法

返回流当中剩余的没有读到的字节数量

System.out.println("流中的总字节数:" + fileInputStream.available());
//读一个
int data = fileInputStream.read();
//流中剩余的字节数
System.out.println(fileInputStream.available());

有了总字节数,我们就可以创建一个对应长度的byte数组,这样直接一次性拿完,不用再根据read的返回值来写循环了

byte[] byte1 = new byte[fileInputStream.available()];
int readCount = fileInputStream.read(byte1);
System.out.println(new String(byte1));

//但byte数组不能太大,所以以上不适用于大文件。

🍁long skip()方法

跳过几个字节不取

fis = new FileInputStream("G:\\JAVA\\test.txt");
fis.skip(2);

2、java.io.FileOutputStream

文件字节输出流,负责写,从内存到硬盘。

通过构造方法创建文件字节输出流对象

加不加true传参,就像Linux中的 > 和 >>的区别:

//tempFile如果不存在,运行程序会自动创建

//不加参数true,调用write方法会清空文件原来的内容
fos = new FileOutputStream("tempFile");

//append参数传true,则write方法是追加而不是清空重写
fos = new FileOutputStream("tempFile",true);

write()方法

FileOutputStream fos = null;
//即abcd
byte[] bytes = {97,98,99,100};
try{
    fos = new FileOutputStream("tempFile",true);
    //将数组中的内容全部写到tempFile
    fos.write(bytes);
    //只要bytes数组中的前两位
    fos.write(bytes,0,2);
    fos.flush();
}catch(FileNotFoundException e){
    e.printStackTrace();
}catch(IOException e){
    e.printStackTrace();
}finally{
    try{
        if(fos != null){

            fos.close();
        }
    }catch(IOException e){
        e.printStackTrace();
    }
}
String s = "这是个字符串";
//String转byte数组
byte[] bs = s.getBytes();
fos.write(bs);
fos.flush();

🍺🍺🍺综合练习:复制D盘文件1.avi到C盘
复制文件

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class Copy {
    public static void main(String[] args) {
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            fis = new FileInputStream("D:\\course\\1.avi");
            fos = new FileOutputStream("C:\\1.avi");
            //一次读1M
            byte[] bytes = new byte[1024*1024];
            int readCount = 0;
            while ((readCount = fis.read(bytes)) != -1) {
                //在循环条件中读,在循环体中写
                fos.write(bytes,0,readCount);
            }
            //输出流最后要刷新
            fos.flush();


        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (fis != null) {
                    fis.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            //注意这里fis和fos分开try
            try {
                if (fos != null) {
                    fos.close();
                }

            } catch (IOException e) {
                e.printStackTrace();

            }
        }
    }
}

注意最后:

√ 如果把fis和fos的关闭流分支写在一起:

...
 } finally {
      try {
          if (fis != null) {
              fis.close();
          }
          if (fos != null) {
              fos.close();
          }
      } catch (IOException e) {
          e.printStackTrace();
      }
      ...

当fis出现异常的时候,fos的关闭流代码就执行不了了,所以分开try…catch

3、java.io.FileReader

文件字符输入流,只能读取普通文本。

//用法和类中的方法,类比FileInputStream

FileReader reader = null;
try{
    reader = new FileReader("D:\\1.txt");
    char[] chars = new char[4];
    int readerCount = 0;
    while( (readerCount = reader.read(chars)) != -1){
        System.out.println(new String(chars,0,readerCount));
    }
}catch(FileNotFoundException e){
    e.printStackTrace();
}catch(IOException e){
    e.printStackTrace();
}finally{
    try{
        if(reader != null){
            reader.close();
        }
    }catch(IOException e){
        e.printStackTrace();
    }
}

4、java.io.FileWriter

文件字符输出流,将文本从内存写到磁盘,只能传输普通文本,word文件不是普通文本。

与字节输出流不同的是:字符输出流的write方法可以直接传字符串,也能写成功

FileWriter fw = null;
    try{
        fw = new FileWriter("temp.txt");
        char[] chars = {'字','符','输','出'};
        fw.write(chars);
        fw.write(chars,0,2);
        //write(String str)
        fw.write("可以直接写字符串了");
    }catch(IOException e){
        e.printStackTrace();
    }finally{
    ....

🍺🍺🍺综合练习:拷贝普通文本文件

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class TxtCopy {
    public static void main(String[] args) {
        FileReader fr = null;
        FileWriter fw = null;
        try{
            fr = new FileReader("D:\\course\\HelloWorld.java");
            fw = new FileWriter("E:\\HelloWorld_copy.java");
            int charCount = 0;
            //循环一次1M
            char[] chars = new char[1024*512];
            while((charCount = fr.read(chars)) != -1){
                fw.write(chars,0,charCount);
            }
        }catch(IOException e){
            e.printStackTrace();
        }finally {
            try{
                if(fr != null){
                    fr.close();
                }

            }catch(IOException e){
                e.printStackTrace();
            }
            try{
                if(fw != null){
                    fw.close();
                }
            }catch(IOException e){
                e.printStackTrace();
            }
        }
    }
}

注意:
能用记事本编辑的都是普通文本文件,如xx.java,并不是单指txt文件

三、缓冲流与转换流

Buffered

1、java.io.BufferedReader

BufferedReader类的构造方法:

带有缓冲区的字符输入流,使用这个流不用自定义char数组,自带缓冲

FileReader fileReader = new FileReader("D:\\1.txt");
BufferedReader br = new BufferedReader(fileReader);
//注意,根据源码,BufferedReader只能传字符流,不能传字节流,对应的

当一个流的构造方法中需要传入另一个流的时候,这个被传进来的流称为节点流,如上面的FileReader,外部负责包装这个流的,称包装流,也称处理流。如上面的BufferedReader

🍁

br.close();

对于包装流来说,只需要关闭最外层的流就好,里面的节点流有底层源码去自动关闭。

readLine()方法

String firstLine = br.readLine();
//readLine方法不带换行,所以这里选择println
System.out.println(firstLine);
String s =null;
//读全部
while((s = br.readLine()) != null){
    System.out.println(s);
}

2、java.io.BufferedWriter

带有缓冲的字符输出流

FileWriter fileWriter = new FileWriter("temp.txt");
BufferedWriter bw = new BufferedWriter(fileWriter);
bw.write("hello world!");
bw.write("\n");
bw.flush();
//只关闭最外层
bw.close()

传入FileOutputStream时,用转换流

3、java.io.InputStreamReader

前面提到:BufferedReader的构造方法只能传字符流,不能传字节流,可通过转换流转字节流为字符流:

FileInputStream in = new FileInputStream("D:\\course\\1.txt");
//这里reader是包装流
//字节流转为字符流
InputStreamReader reader = new InputStreamReader(in);
BufferedReader bfReader = new BufferedReader(reader);

合并代码:

BufferedReader bfReader = new BufferedReader(new InputStreamReader(new FileInputStream("D:\\course\\1.txt")));

四、数据流

1、java.io.DataOutputStream

数据专属流,这个流可以将数据连同数据的类型一并写入文件(那么这个文件就不是普通的文本文件了,用记事本打开就会乱码)

//注意DataOutputStream的构造方法中传入一个字节流做为节点流
DataOutputStream dos = new DataOutputStream(new FileOutputStream("tempData"));

byte b = 100;
int i = 300;
char c = 'a';
//把数据类型一并写入文件中
dos.writeByte(b);
dos.writeInt(i);
dos.writeChar(c);
dos.flush();

2、java.io.DataInputStream

数据字输入流,DataOutputStream写的文件,只能使用DataInputStream去读,且读的时候需要提前知道写入的顺序(读的顺序和写的顺序一致,才能正常取出数据)

DataInputStream dis = new DataInputStream(new FileInputStream("tempData"));
//注意和写的顺序一致
byte b1 = dis.readByte();
int i1 = dis.readInt();

五、标准输出流

标准输出流

1、java.io.PrintStream

标准的字节输出流,默认输出到控制台,标准输出流不需要close()

//System.out.println
PrintStream ps = System.out;
ps.println();

总结回顾之前System类中的方法

  • System.gc()
  • System.currentTimeMills()
  • System.exit(0);
  • System.arrayCopy()
//传入一个文件字节输出流做为节点流
PrintStream printStream = new PrintStream(new FileOutputStream("log"));
//标准输出流不再指向控制台,修改成了log文件
System.setOut(printStream);
//再输出
System.out.println("hello");
System.out.println("log");
//这时候就输出到文件中去了

以上也是日志输出的一个实现思路:

/**
 * 日志记录
 */
public class Logger {
    public static void main(String[] args) {
      Logger.log("System is ready!");
    }
    public static void log(String msg){
        try {
            PrintStream printStream = new PrintStream(new FileOutputStream("log.txt",true));
            System.setOut(printStream);
            //日期
            Date nowTime = new Date();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
            String strTime = sdf.format(nowTime);
            System.out.println(strTime + ":" + msg);

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
}

2、java.io.PrintWriter

标准输出流之字符流,用法参照PrintStream

六、对象专属流与File类

1、File类

  • java.io.File类的父类是java.lang.Object
  • File对象是文件和目录路径名的抽象表现形式。如C:\course是一个File对象,也可能是文件,也可能是目录
  • File类和四大流没有关系,所以File类不能完成文件的读和写

2、File类的常用方法

🍁 exists()方法

//判断文件是否存在
File f1 = new File("D:\\file");
System.out.println(f1.exists());

🍁 createNewFile()和mkdir()

//若D:\\file不存在,则以文件的形式创建
if(!f1.exists()){
   f1.createNewFile();
}

//以目录的形式创建
if(!f1.exists()){
   f1.mkdir();
}

注意:

当f1对象中的路径是多重目录时,mkdir方法变为mkdirs()

🍁getParent()方法

//获取文件的父路径
File f2 = new File("D:\\course\\src\\1.txt");
// D:\course\src
String parentPath = f2.getParent();
File parentPathFile = f2.getParentFile();

相对应的,有个getAbsolutePath() 方法:

//获取绝对路径

File f3 = new File("FileTest.java");
System.out.println(f3.getAbsoluteFile());
System.out.println(f3.getAbsolutePath());

🍁getName()方法

//获取文件名

File f2 = new File("D:\\course\\src\\1.txt");
//1.txt
System.out.println(f2.getName());

🍁isDirectory()和isFile()方法

//判断是文件/目录
File f2 = new File("D:\\course\\src\\1.txt");
//false
System.out.println(f2.isDirectory());

🍁lastModified()方法

File f2 = new File("D:\\course\\src\\1.txt");
//从1970年0:0到现在的总毫秒数
Long times = f2.lastModified();

Date time = new Date(times);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
String strTime = sdf.format(time);
System.out.println(strTime);

🍁length()方法

//获取文件大小
Long size = f2.length();

🍁File[ ] listFiles()方法

//获取当前目录下的所有子文件,返回一个File[]数组
File f = new File("D:\\course");
File[] files = f.listFiles();

//增强for循环获取子文件的绝对路径
for(File fObj:files){
    System.out.println(fObj.getAbsoluteFile());
}

❀❀❀练习–目录拷贝

/**
 * 业务功能:实现任意两个目录间文件的拷贝
 */

import java.io.*;

public class CopyAll {
    public static void main(String[] args) {
        File src = new File("D:\\course");
        File dest = new File("E:\\copy");
        copyDir(src,dest);

    }
    public static void copyDir(File srcFile,File destFile){
        /**
         * 源文件是一个文件
         */
        if(srcFile.isFile()){
            FileInputStream in = null;
            FileOutputStream out = null;
            try {
                in = new FileInputStream(srcFile);
                /**
                 * 三目运算符,判断目标路径结尾是不是\
                 * 不是则加\,并截取源目录除盘符以外的目录拼接给它
                 */
                String path = destFile.getAbsolutePath().endsWith("\\") ?
                        destFile.getAbsolutePath():
                        destFile.getAbsolutePath() + "\\" + srcFile.getAbsolutePath().substring(3);
                if(!new File(path).exists()){
                    new File(path).getParentFile().mkdirs();
                }
                out = new FileOutputStream(path);
                byte[] bytes = new byte[1024*1024];
                int readCount = 0;
                while( (readCount = in.read(bytes)) != -1 ){
                    out.write(bytes,0,readCount);
                }
                out.flush();
            } catch(FileNotFoundException e) {
                e.printStackTrace();
            }catch(IOException e){
                e.printStackTrace();
            }finally{
                try{
                    if(in != null){
                        in.close();
                    }
                }catch(IOException e){
                    e.printStackTrace();
                }
                try{
                    if(out != null){
                        out.close();
                    }
                }catch(IOException e){
                    e.printStackTrace();
                }
            }
            System.out.println("拷贝完成,进度100%!");
            //如果源文件是文件,则一定不是目录,下面的目录复制
            //下面的目录复制不必再执行
            return;
        }
        /**
         * 能执行到这儿说明源文件是一个目录
         * 这里要是再加if分支判断是否为目录,则上面的return就不必了
         * 但要么文件要么目录,所以直接上面return了
         */
        //获取源目录下的所有子文件
        File[] files = srcFile.listFiles();
        for(File file:files){
            if(file.isDirectory()){
                String destPath = (destFile.getAbsolutePath().endsWith("\\") ?
                        destFile.getAbsolutePath():
                        destFile.getAbsolutePath() + "\\" + srcFile.getAbsolutePath().substring(3));
                File newFile = new File(destPath);
                if(!newFile.exists()){
                    newFile.mkdirs();
                }

            }
            //执行到这里,说明源目录的子文件是一个文件,不是目录
            // 递归调用copy就行
            copyDir(file,destFile);
        }
        System.out.println("拷贝完成,进度100%!");

    }
}

在刚开始调代码的时候遇到一个error:

error:
java.io.FileNotFoundException:.\xxx\xxx.txt (系统找不到指定的路径。)
java.io.FileNotFoundException: E:\xx\xx (拒绝访问。)

分析:

在构造一个File对象时,指定的文件路径是什么都可以,就算不存在也能够构造File对象,但是,现在你要对文件进行输入输出操作,也就是InputStream和OutputStream操作时,如果填写的路径不存在,那么就会报系统找不到指定路径,如果指定的是xxx\,就会报拒绝访问异常。

具体参考【BUG】

3、对象流

序列化与反序列化
🍁序列化:
Serialize,Java对象存储到文件中,将Java对象的状态保存下来的过程,用ObjectOutputStream实现。

🍁反序列化:
DeSerialize,将硬盘上的数据重新恢复到内存中,恢复成Java对象

public class Students implements Serializable{

	private int age;
	.....
}

参与序列化和反序列化的对象,必须实现Serializable接口 ,否则报错java.io.NotSerializableException

//Serializabl接口的源码就这两行
public interface Serializable {
}

Serializable接口中没有任何方法,是一个标志性接口。标志性接口,起到标识作用,Java虚拟机看到这个类实现了这个接口,可能会对这个类进行特殊待遇,即为该类自动生成一个序列化版本号。

//定义实现序列化接口的Students类
class Students implements Serializable{
    int no;
    String name;
    public Students(){

    }
    public Students(int no,String name){
        this.no = no;
        this.name = name;
    }

}

Students s = new Students(111,"llg");
//序列化,将对象存到硬盘,文件名称students
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("students"));
oos.writeObject(s);
oos.flush();


//将硬盘中的文件students反序列化成对象,读进内存
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("students"));
Object obj = ois.readObject();
System.out.println(obj);

对象序列化后的文件,用txt查看乱码:
序列化
🍁序列化多个对象和反序列化多个对象:

把对象放到集合中,writeObject方法中传入一个集合

List<Students> studentsList = new ArrayList<>();
studentsList.add(new Students(02,"A"));
studentsList.add(new Students(03,"B"));
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("studentsList"));
//传入了一个List集合
//ArrayList类已经实现了Serializable
oos.writeObject(studentsList);

反序列化多个对象:

ObjectInputStream ois = new ObjectInputStream(new FileInputStream("studentsList"));
//readObject方法返回的是Object类型,更细分析这里是一个List,故强转
List<Students> objList = (List<Students>) ois.readObject();
for(Students objStudents:objList){
   System.out.println(objStudents);
}

🍁transient关键字

transient关键字表示游离的,不参与序列化。

private transient String name;

即对象的name属性序列化的时候不会再序列化到文件中,则此后再反序列化,需要new对象时name就无值,出现默认值null

🍁IDEA生成序列化版本号
IDEA

private static final Long serialVersionUID = -7876415467956846468432L;

❀自动生成序列化版本号的缺陷:

一旦代码后续修改,重新编译会生成全新的序列化版本号。而序列化版本号是用来区分类的,故JVM会认为这是一个全新的类。再反序列化的时候就会报错。

因此:实现Serializable后,手动在代码中写一个固定的序列化版本号,别自动生成(自动生成的不显示,且代码修改编译后,序列化版本号会改变)。

4、IO与Properties联合使用

//有文件userinfo.txt
username=root
password=123qweASD

将userinfo.txt文件中的数据加载到Properties对象中(温习:Properties是一个Map集合,其key和value都是String类型)

FileReader reader = new FileReader("userinfo.txt");
Properties pro = new Properties();
//Properties对象的load方法,将文件中的数据加载到Map集合中
//其中,等号左边为key,右边为value
pro.load(reader);
//由key取value
String value = pro.getProperty("username");

对于经常变动的数据,可以单独写到一个文件中(即配置文件),使用程序动态读取。后续修改只需改配置文件,不用改代码,不用重新编译。

当配置文件的内容格式是key=value的时候,称为属性配置文件,文件名常以.properties结尾。=也可用:且=左右两边最好别加空格。

Properies是专门存放属性配置文件内容的一个类。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/47355.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【面试题】深度解析Java多线程中的 run() 与 start() 有什么区别?

【面试题】深度解析Java多线程中的 run() 与 start() 有什么区别&#xff1f; 大多数人的回答 start() run() 深入底层源码的解析 run() 与 start() 为什么我们不能直接调用 run() 方法&#xff1f; 如何证明 start() 会调用 run() 方法&#xff1f; JVM -> OS执行全…

Nodejs -- 数据库基本概念的介绍及在Express中操作数据库

文章目录1. 数据库的基本概念1.1 什么是数据库1.2 常见的数据库及分类1.3 传统型数据库的数据组织结构1.3.1 Excel的数据组织结构1.3.2 传统型数据库的数据组织结构1.3.3 实际开发中库、表、行、字段的关系2. 在Express中操作MySQL2.1 在项目中操作数据库的步骤2.2 安装与配置m…

Java编程案例:买飞机票

编程案例&#xff1a; 一、目的 复习前半段课程学习的Java编程知识&#xff0c;能够使用所学的知识解决问题&#xff0c;提升同学们的编程能力。 二、涉及到的知识点 变量、数组。运算符&#xff1a;基本运算符、关系运算符、逻辑运算符…程序流程控制&#xff1a;if、switc…

np.meshgrid()函数

文章目录(1)自己理解(2)官方解释(3)参数:3.1 x1, x2,…, xn:array_like3.2 sparse:bool, optional 默认false3.3 copy:bool, optional(1)自己理解 np.meshgrid(a, b,indexing "xy") 函数会返回 b.shape() 行 &#xff0c;a.shape() 列的二维数组。 因此 i, j 都是 …

【序列召回推荐】(task6)多兴趣召回Comirec-SA

note Comirec-SA基于attention的多兴趣建模&#xff0c;论文中先通过attention提取单一兴趣&#xff0c;再推广到多兴趣建模。另外使用贪心算法优化带有准确度多样性的目标函数。DR把MIND的attention换成argmax&#xff08;还有初始化方式不同、序列胶囊到兴趣胶囊用可学习权重…

2.线性代数基础

1.矩阵 2. 特殊矩阵 正交矩阵 AATE&#xff08;E为单位矩阵&#xff0c;AT表示“矩阵A的转置矩阵”。&#xff09;或ATAE&#xff0c;则n阶实矩阵A称为正交矩阵 正交矩阵有如下性质&#xff1a; A是正交矩阵&#xff0c;AT也是正交矩阵A的各行是单位向量且两两正交&#xff0…

html实现ezuikit.js萤石云直播监控,ezuikit.js实时监控实现,萤石云实时监控简单实现

效果图 实现 下面的播放url获取&#xff1a;登录萤石云->控制台->我的资源->设备列表->列表中&#xff1a;查看通道->监控地址 appKey和appSecret获取&#xff1a;登录萤石云->控制台->我的账号->应用信息->右侧&#xff1a;应用密钥 下载ezuikit…

(服务器客户端)网络通信是怎么实现的?7000字爆肝----原来java网络编程技术功不可没(多线程,URL,InetAddressm,TCP,UDP)集结

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 秩沅 原创 收录于专栏 java ⭐java网络编程技术⭐ 文章目录⭐java网络编程技术⭐&#x1f468;‍&#x1f4bb;一&#xff0c;URL类…

[附源码]Python计算机毕业设计Django的4s店车辆管理系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

虎牙、斗鱼同道同命:共同御寒

配图来自Canva可画 回顾游戏直播行业过去十年&#xff0c;先是直播行业野蛮发展玩家快速跑马圈地&#xff0c;而后历经千播大战形成斗鱼、虎牙分天下的市场格局&#xff0c;现在头部平台进入精细化、多元化运作阶段&#xff0c;市场竞争愈加激烈。 也就是说&#xff0c;游戏直…

4G DTU能装4G物联网卡吗?

科技的发展日新月异&#xff0c;我们国家的发展战略也是支持高新科技公司的发展&#xff0c;所以越来越多的高新科技公司出现&#xff0c;但凡是高新科技公司&#xff0c;在设备的联网中&#xff0c;都会用到物联卡&#xff0c;所以物联卡的市场也愈发火爆&#xff0c;那么今天…

食物链【并查集+不知道1是A,B,C哪一类的?用x,x+n,x+n+n分别表示A,B,C中有个1】【并查集中用距离表示关系】【压缩路径】

欢迎观看我的博客&#xff0c;如有问题交流&#xff0c;欢迎评论区留言&#xff0c;一定尽快回复&#xff01;&#xff08;大家可以去看我的专栏&#xff0c;是所有文章的目录&#xff09; 文章字体风格&#xff1a; 红色文字表示&#xff1a;重难点 蓝色文字表示&#xff1a;思…

jenkins项目构建类型 -----Pipeline流水线项目构建

壹&#xff0c;概念 pipeline 是一套运行在jenkins上得工作流框架&#xff0c;将原本运行于单个或者多个节点得任务连接起来&#xff0c;用来实现单个任务难以完成得复杂流程编排和可视化得工作。 贰 优点 代码持久可停止多功能可扩展 叁 如何创建Jenkins Pipeline pipeli…

计算机物联网控制|5.5常规控制方案 5.6先进控制方案

11.16日课堂作业 1.已知模拟PID算式为 试推导差分增量算式。 2.PID参数Kc、Ti、Td对系统动态特性和稳态特性有何影响&#xff1f; 目录 11.16日…

[附源码]计算机毕业设计springboot高校实验室仪器设备管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

Telemetry原理

Telemetry是一种网络设备监控技术&#xff0c;提供周期采样网络设备内的统计数据和状态数据的能力。 一、Telemetry概述 1.1、技术背景&#xff1a; 网络设备的统一监控和性能管理是运维平台的重要功能&#xff0c;设备的监控数据包括数据、控制和管理平面数据。 获取设备监…

学习Python的8天

1、异常处理机制 Python 中&#xff0c;用try except语句块捕获并处理异常&#xff0c;其基本语法结构如下所示&#xff1a; try:可能产生异常的代码块 except [ (Error1, Error2, ... ) [as e] ]:#(e是别名&#xff0c;可以自己起)处理异常的代码块1 except [ (Error3, Error…

【强化学习论文合集 | 2020年合集】一. ICML-2020 强化学习论文

强化学习(Reinforcement Learning, RL),又称再励学习、评价学习或增强学习,是机器学习的范式和方法论之一,用于描述和解决智能体(agent)在与环境的交互过程中通过学习策略以达成回报最大化或实现特定目标的问题。 本专栏整理了近几年国际顶级会议中,涉及强化学习(Rein…

Workfine使用Oracle Express Edition数据库

Workfine 应用环境和工具 Win10 专业版操作系统Windows Terminaldocker desktop 4.10.1 安装设置Oracle Express Edition数据库 1、获取Oracle XE 18.4.0 docker 镜像&#xff0c;在 Windows Terminal 终端里执行如下命令 docker pull gvenzl/oracle-xe:18.4.0 2、下载成功…

小啊呜产品读书笔记001:《邱岳的产品手记-14》第26讲 写好产品文档的诀窍 第27讲 产品案例分析: QuartzHooked的对话式交互

小啊呜产品读书笔记001&#xff1a;《邱岳的产品手记-14》第26讲 写好产品文档的诀窍 & 第27讲 产品案例分析&#xff1a; Quartz&Hooked的对话式交互一、今日阅读计划二、泛读&知识摘录1、第26讲 写好产品文档的诀窍2、第27讲 产品案例分析&#xff1a; Quartz&am…