IO流、多线程

news2024/11/9 0:49:00

FileInputStream

 FileOutputStream 原理:

//1、创建一个FileOutputStream对象,构造方法中写入数据的目的地

FileOutStream fos = new FileOutputStream("C:\\a.txt");

//2、调用FileOutputStream对象中的方法write,把数据写入文件中

//public abstract void write(int b);//将指定的字节输出

fos.write(97);

//3、释放资源(流使用会占用一定的内存,使用完毕要把内存清空,提供程序的效率)

fos.close();

创建字节输出流对象:

  • 参数是字符串表示的路径或者是File对象都是可以的
  • 如果文件不存在会创建一个新的文件,但是要保证父级路径是存在的
  • 如果文件已经存在,默认会清空文件

写数据:

  • write方法的参数是整数,但是实际上写到本地文件中的是整数在ASCII上对应的字符

释放资源:

  • 每次使用完都要释放资源

 FileOutputStream写数据的三种方式:

void write(int b)

void write(byte[] b)

void write(byte[] b,int off,int len)

import java.io.FileOutputStream;
import java.io.IOException;

public class ByteStreamDemo {
    public static void main(String[] args) throws IOException {
        FileOutputStream fos=new FileOutputStream("D:\\javaj\\first\\src\\a.txt");
        fos.write(97);
        fos.close();
    }
}

换行写和续写:

如果要传入数字,可以用字符串转为 byte 形式写入;也可以传入 ACSII 对应的值(例如 0 的 ASCII 码值是 48)。

如果写入的数据要换行,在两条写入语句之间加入:

String str="\r\n";
byte []arr=str.getBytes();

默认情况下,打开已有文件时,会清空文件。

如果要续写,打开续写开关就可以了:开关位置在创建对象的第二个参数。

FileOutputStream fos=new FileOutputStream("D:\\javaj\\first\\src\\a.txt",true);

FileOutputStream

操作本地文件的字节输入流,可以把本文件中的数据读取到程序中来。

创建字节输入流对象:

  • 如果文件不存在,就直接报错

读取数据:

  • 一次读一个字节,读出来的就是书籍在 ASCII 码上对应的数字
  • 读到文件末尾了,read 方法返回 -1.(问:如果文件当中存在“-1”,怎么处理?        答:read方法将“-1”分为“-”和“1”处理,不会读到“-1”的结果)

释放资源

  • 每次使用完流必须要释放资源

循环读取:

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

public class ByteStreamDemo3 {
    public static void main(String[] args) throws IOException {
        FileInputStream fir =new FileInputStream("D:\\javaj\\first\\src\\a.txt");
        int b;
        while((b=fir.read())!=-1){
            System.out.println((char)b);
        }
        fir.close();
    }
}

问:这里定义的局部变量时多余的吗?

答:不是,如果没有这个局部变量,那输出时将这样写:

System.out.println(fir.read());

并且while语句中也存在 fir.read 语句,所以一次循环将读取两次,此时可以用一个局部变量存放读取的值。

文件拷贝

对于较小的文件,可以一个一个字节读取:

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

public class ByteStreamDemo4 {
    public static void main(String[] args) throws IOException {
        //创建对象
        FileInputStream fis=new FileInputStream("D:\\20230414154402.mp4");
        FileOutputStream fos= new FileOutputStream("D:\\javaj\\first\\src\\cope.mp4");
        //拷贝(边读边写)
        int b;
        while((b=fis.read())!=-1){
            fos.write(b);
        }
        //释放资源(先开的后关)
        fos.close();
        fis.close();
    }
}

所以想要一次读多个字节:

一次读多少个字节跟定义的数组长度有关。

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

public class ByteStreamDemo5 {
    public static void main(String[] args) throws IOException {
        //创建对象(如果文件中只有五个字符:abcde)
        FileInputStream fis=new FileInputStream("D:\\javaj\\first\\src\\a.txt");
        //读取数据
        byte[] bytes1 =new byte[2];
        byte[] bytes2 =new byte[2];
        byte[] bytes3 =new byte[2];
        //判断一次读取多少个字节,跟数组长度有关
        int len1=fis.read(bytes1);//第一次读取
        System.out.println(len1);//2
        int len2=fis.read(bytes2);//第二次读取
        System.out.println(len2);//2
        int len3=fis.read(bytes3);//第三次读取
        System.out.println(len3);//1


        //将刚刚读到的转换为字符串类型,并输出
        String str1 =new String(bytes1,0,len1);
        String str2 =new String(bytes2,0,len2);
        String str3 =new String(bytes3,0,len3);
        System.out.println(str1);//ab
        System.out.println(str2);//cd
        System.out.println(str3);//e
        //释放资源
        fis.close();
    }
}

在拷贝大文件时,可以定义一个较大的byte数组,接下来读取的次数就大大减少:

byte[] bytes=new byte[1024*1024*5];

try…catch…finally

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

public class ByteStreamDemo6 {

    public static void main(String[] args)  {
        FileInputStream fis=null;
        FileOutputStream fos=null;
        try{
            fis =new FileInputStream("D:\\javaj\\first\\src\\cope.mp4");
            fos =new FileOutputStream("D:\\20230414154402.mp4");
            int len;
            byte[]bytes=new byte[1024*1024*5];
            while((len=fis.read(bytes))!=-1){
                fos.write(bytes);
            }

        } catch (IOException e) {
           e.printStackTrace();
        } finally {
            try {
                fos.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            try {
                fis.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

字符集

GDK中:

一个英文占一个字节

一个中文占两个字节

Unicode字符集的UTF-8编码格式:

一个英文是用一个字节,二进制第一位是0,转成十进制是正数

一个中文是用三个字节,二进制第一位是1,第一个字节转成十进制是负数

UTF-8不是字符集。

乱码出现的原因:

  • 读取数据是未读完整个汉字
  • 编码和解码时的方式不统一

所以不要用字节流读取文本文件。

编码解码使用同一个码表,同一个编码方式。

字节流读取中文会乱码,因为是一个一个字节读的,但是拷贝不会出现乱码,数据没有丢失。

编码方式

编码

public byte[] getBytes()      //默认方式进行编码(UTF-8)

public byte[] getBytes(String charseName)      //指定方式进行编码

解码

String (byte[] bytes)         // //默认方式进行解码(UTF-8)

String(byte[] bytes,String charseName)           //指定方式进行解码

字符输入流

1.创建字符输入流关联本地文件

public FileReader(file file)   

public FileReader(String pathname) 

2.读取数据,读到末尾返回-1

public int Read()

public int Read(char[] buffer)//读取多个数据

  • 按字节进行读取,遇到中文,一次读多个字节,读取后解码,返回一个整数
  • 读到文件末尾了,read方法返回-1

3.释放资源

文本文件:

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

public class CharStreamDemo {
    public static void main(String[] args) throws IOException {
        FileReader fr=new FileReader("D:\\javaj\\first\\src\\a.txt");
        int ch;
        while((ch=fr.read())!=-1){
            System.out.print((char)ch);//输出的时候强转,就可以看到文本文件了
        }
        fr.close();
    }
}

空参的构造方法:

int ch=fr.read();//返回的是读到的数字

fr.read(chars);//读取数据、解码、强转合并,将强转之后的字符放到数组中

字符输出流

1、创建字符输出流对象(底层:关联文件,并创建缓冲区(长度为8192的字节数组))

  • 参数是字符串表示的路径或者File对象都是可以的
  • 如果文件不存在会创建一个新文件,但是父级路径要存在
  • 如果文件存在,默认会清空文件,如果要续写可以打开续写开关

2、写数据(底层:

                判断缓冲区有没有数据可以读取

                缓冲区没有数据:从文件中获取数据,装到缓冲区,如果文件也没有数据了,就返回-1

                缓冲区有数据:从缓冲区读取)

  • 如果write方法的参数是整数,但是实际上写到本地文件中的是整数在字符集上对应的字符

3、释放资源

flush和close方法

public void flush()                 将缓冲区中的数据,刷新到本地文件中

刷新之后还可以继续往文件中写出数据

public void close()                释放资源/关流

断开通道,无法再向文件写出数据


字节流

  • 拷贝任意类型的文件

字符流

  • 读取纯文本文件中的数据
  • 往纯文本文件中写出数据

拷贝的是文件或者是文本

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

public class Test01 {
    public static void main(String[] args) throws IOException {
        //拷贝一个文件夹,考虑子文件
        //创建对象表示数据源
        File test = new File("D:\\javaj\\first\\test");
        //创建对象表示目的地
        File dest=new File("D:\\dest");
        //调用方法开始拷贝
        copydir(test,dest);
    }
    private static void copydir(File test,File dest) throws IOException {
        dest.mkdirs();//创建文件夹
        File[] files=test.listFiles();

        for(File file:files){
            if(file.isFile()){
                FileInputStream fis=new FileInputStream(file);
                FileOutputStream fos =new FileOutputStream(new File(dest,file.getName()));
                byte[]bytes=new byte[1024];
                int len;
                while((len=fis.read(bytes))!=-1){
                    fos.write(bytes,0,len);
                }
                fos.close();
                fis.close();
            }
            else{
                copydir(file,new File(dest,file.getName()));
            }

        }
    }
}

读取数据排序后存入文件:

FileReader fr=new FileReader("D:\\javaj\\first\\test\\aaa.txt");
        StringBuilder sb=new StringBuilder();
        int ch;
        while((ch=fr.read())!=-1){
            sb.append((char)ch);
        }
        fr.close();
        System.out.println(sb);
        String str = sb.toString();
        String[]arrStr=str.split("-");
        ArrayList<Integer> list=new ArrayList<>();
        for (String s : arrStr) {
            int i=Integer.parseInt(s);
            list.add(i);
        }
        Collections.sort(list);
        FileWriter fw=new FileWriter("D:\\test.txt");
        for (int i = 0; i < list.size(); i++) {
            if(i==list.size()-1){
                fw.write(list.get(i)+"");
            }
            else {
                fw.write(list.get(i)+"-");
            }
        }
        fw.close();

字节缓冲流和字符缓冲流

在创建对象时包装了FileOutputStream和FileInputStream。内部创建一个缓冲区数组,使用 8192 个字节的缓冲区,增加缓冲功能,避免频繁读写硬盘。

字节缓冲流,明显加快了文件的读写效率

字符缓冲流,相对比字符流的话,已经存在缓冲区了,但是在缓冲流存在两个有用的方法:

整行读取(遇到换行会停止,但是不会读取到换行符)
 

        BufferedReader br=new BufferedReader(new FileReader("D:\\javaj\\first\\test\\aaa.txt"));
        String line=br.readLine();

如果读不到,不是返回的-1,是返回null。

换行方法(用于写入一个行分隔符,方法会根据不同的平台自动写入相应的行分隔符,因此使用newline()方法能够保证写入的文本文件在不同平台下都能以正确的方式表示每一行末尾的分隔符。)

    public static void main(String[] args) throws IOException {
        BufferedWriter bw=new BufferedWriter(new FileWriter("D:\\javaj\\first\\test\\aaa.txt",true));
        bw.write("123");
        bw.newLine();
        bw.write("456");
        bw.close();
    }

练习:1.根据文件中的序号排序   2.控制软件运行次数

import java.io.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
//根据文件中的序号排序
public class Test04 {
    public static void main(String[] args) throws IOException {
        BufferedReader br=new BufferedReader(new FileReader("D:\\javaj\\first\\test\\aaa.txt"));
        String line;
        ArrayList<String> list=new ArrayList<>();
        while((line=br.readLine())!=null){
            list.add(line);
        }
        br.close();
        BufferedWriter bw=new BufferedWriter(new FileWriter("D:\\test.txt"));
        Collections.sort(list,new Comparator<String>(){
            public int compare(String o1,String o2){
                int i1=Integer.parseInt(o1.split("\\.")[0]);
                int i2=Integer.parseInt(o2.split("\\.")[0]);
                return i1-i2;
            }
        });
        System.out.println(list);
        for (String s : list) {
            bw.write(s);
            bw.newLine();
        }
        bw.close();
    }
}

转换流

在Java中,字符是以Unicode编码存储的,但是文件通常是以字节的形式存储的,因此在读写文本文件时就需要使用转换流来进行转换,这样才能正确地读写文件内容。

InputStreamReader将字节输入流转换为字符输入流,它通过指定字符集将字节格式的数据解码成字符格式的数据。OutputStreamWriter则将字符输出流转换为字节输出流,也通过指定字符集将字符格式的数据编码成字节格式的数据。

BufferedReader br=new BufferedReader(new InputStreamReader(new FileInputStream("D:\\javaj\\first\\test\\aaa.txt")));

序列化流

将被序列化的流要继承 Serializable 类,这个类没有抽象类,只是一个标记,有了这个标记才可以被序列化。

序列化:

public class ObjectStudent {
    public static void main(String[] args) throws IOException {
        Student stu=new Student("zhang",24);
        ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("D:\\javaj\\first\\aaa.txt"));
        oos.writeObject(stu);
        oos.close();
    }
}

反序列化:

public class ObjectStreamDemo2 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        ObjectInputStream ois =new ObjectInputStream(new FileInputStream("D:\\javaj\\first\\aaa.txt"));
        Student o=(Student ) ois.readObject();
        System.out.println(o);
        ois.close();
    }
}

版本号的作用在于,在类的定义发生变化时,比如增加或删除了成员变量或方法,版本号也会随之改变,这样就可以避免反序列化时出现异常。

瞬态序列化:

用transient关键字修饰变量,不会把当前数学序列化到本地文件中。

读写多个对象,并且不知道对象的个数,如果循环往下读,读到文件末尾了,并不会返回-1或者null,而是会抛出EOFException 异常,所以循环读取时,可以用try…catch…语句捕获异常,另一个方法是:把对象放在集合中,一次写入文件,然后读取的时候也只要读取一次。

public class ObjectStudentDemo3 {
    public static void main(String[] args) throws IOException {
        Student2 st1=new Student2("zhang",15,"南京");
        Student2 st2=new Student2("wang",17,"重庆");
        Student2 st3=new Student2("li",20,"北京");
        ArrayList<Student2>list=new ArrayList<>();

        list.add(st1);
        list.add(st2);
        list.add(st3);
        ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("D:\\javaj\\first\\test\\aaa.txt"));
        oos.writeObject(list);
        oos.close();
    }
}
public class ObjectStudentDemo4 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        ObjectInputStream ois=new ObjectInputStream(new FileInputStream("D:\\javaj\\first\\test\\aaa.txt"));
        ArrayList<Student2> list = (ArrayList<Student2>) ois.readObject();

        for (Student2 student2 : list) {
            System.out.println(student2);
        }
    }
}

打印流

只有输出流(写),没有输入流(读)。

打印流是指:PrintStream(字节打印流)、PrintWrite(字符打印流)两个类。

  • 只能操作文件目的地,不操作数据源。
  • 特有的方法可以事项,数据原样写出(打印:97,文件中:97)
  • 特有的写出方法,可以实现自动刷新,自动换行(打印一次数据=写出+换行+刷新—)

字节打印流

字节流底层没有缓冲区,开不开自动刷新都一样。

特有方法:

public void println(Xxx xx)                //打印任意数据,自动刷新和换行

public void print(Xxx xx)                //打印任意数据,不换行

public void printf(String format,Object…args)            //带有占位符的打印语句,不换行

字符打印流

字符流底层有缓冲区,想要自动刷新需要开启,它的效率更高。

特有方法与字节打印流一样。

解压缩流

解压本质:把每一个zipEntry按照层级拷贝到本地另一个文件夹中。

public class ZipStreamDemo1 {
    public static void main(String[] args) throws IOException {
        File src =new File("D:\\javaj\\first\\test.zip");
        File dest=new File("D:\\");//这里要创建一个test的文件夹,否则找不到路径
        unzip(src,dest);
    }
    public static void unzip(File src,File dest) throws IOException {
        ZipInputStream zip=new ZipInputStream(new FileInputStream(src));
        ZipEntry entry;
        while((entry=zip.getNextEntry())!=null){
            System.out.println(entry);
            if(entry.isDirectory()){
                //文件夹:需要创建一个文件夹
                File file=new File(dest,entry.toString());
                file.mkdirs();//创建一个文件夹
            }
            else{
                //文件:需要读取到压缩包中的文件,并把它存放到目的地dest文件夹中
                FileOutputStream fos=new FileOutputStream(new File(dest,entry.toString()));
                int b;
                while((b=zip.read())!=-1){
                    fos.write(b);
                }
                fos.close();
                zip.closeEntry();
            }
        }
        zip.close();
    }
}

压缩本质:把每一个(文件/文件夹)看成ZipEntry对象放在压缩包中。

//压缩一个文件夹
public class ZipStreamDemo3 {
    public static void main(String[] args) throws IOException {
        //创建File对象表示要压缩的文件夹
        File src =new File("D:\\javaj\\first\\test");
        //创建File对象表示压缩包放在哪里
        File destParent=src.getParentFile();
        //创建File对象表示压缩包的路径
        File dest=new File(destParent,src.getName()+".zip");
        //创建压缩流关联压缩包
        ZipOutputStream zos=new ZipOutputStream((new FileOutputStream(dest)));
        //获取src里面的每一个文件,放入压缩包中
        toZip(src,zos,src.getName());//test
        //释放资源
        zos.close();
    }
    public static  void toZip(File src,ZipOutputStream zos,String name) throws IOException {
        //进入src文件夹
        File[] files =src.listFiles();
        for (File file : files) {
            if(file.isFile()){
                ZipEntry entry=new ZipEntry(name+"\\"+file.getName());
                zos.putNextEntry(entry);
                FileInputStream fis=new FileInputStream(file);
                int b;
                while((b=fis.read())!=-1){
                    zos.write(b);
                }
                fis.close();
                zos.closeEntry();
            }
            else {
                toZip(file,zos,name+"\\"+file.getName());
            }
        }
    }
}

Comments工具包

Hutool工具包

多线程

线程是操作系统能够运行调度的最小单位,他被包含在进程之中,是进程中的实际运作单位。

进程是程序的基本执行实体。

多线程:软件中互相独立独立,可以同时运行的功能

并发:在同一时刻,有多个指令在单个CPU上交替执行。

并行:在同一时刻,有多个指令在单个CPU上

实现方式

  1. 继承Thread类的方式进行实现

  2. 实现Runnable接口的方式进行实现

  3. 利用Callable接口和Future接口方式实现(重写call,可以获取到多线程运行的结果)

//第一个方法
//先创建一个MyTread类继承Thread,然后里面可以是输出的方法
//接着用类去调用
public class Tread {
    public static void main(String[] args) {
        MyTread t1=new MyTread();
        MyTread t2=new MyTread();
        t1.setName("线程1");
        t2.setName("线程2");
        t1.start();
        t2.start();
    }
}

//第二个方法
//先定义一个Myrun类实现Runnable接口
//接着可以调用
public class ThreadDemo1 {
    public static void main(String[] args) {
        MyRun mr=new MyRun();
        Thread t1=new Thread(mr);
        Thread t2=new Thread(mr);
         t1.setName("线程1");
         t2.setName("线程2");

        t1.start();
        t2.start();
    }
}
//第三个方法
//定义的类实现Callable接口
public class MyCallable implements Callable<Integer> {
    public Integer call(){
        int sum=0;
        for (int i = 0; i < 100; i++) {
            sum=sum+i;
        }
        return sum;
    }
}




//接着
public class ThreadDemo2 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {//创建一个类MyCallable实现Callable接口
        //重写call(有返回值)
        //创建MyCallable对象(表示多线程哟啊执行的任务)
        MyCallable mc = new MyCallable();
        //创建FutureTask对象(作用管理多线程运行的结果)
        FutureTask<Integer> ft = new FutureTask<>(mc);
        //创建Thread类的对象,并启动(表示线程)
        Thread t1 = new Thread(ft);
        t1.start();
        Integer result = ft.get();
        System.out.println(result);
    }
}

常用的成员方法

void setName(String name); 

  •  如果没有给线程设置名字,线程也有默认名字
  • 如果要给线程设置名字,可以用set方法设置,也可以构造方法设置

static Thread currentThread();

  • 当JVM虚拟机启动之后,会自动的启动多条线程,其中有一条线程就叫main线程,它的作用就是调用main方法,并执行里面的代码

static void sleep(long time);//以毫秒为单位

  • 哪条线程执行到这个方法,你们哪条线程就会在这里停留对应的时间
  • 当时间到了,线程会自动醒来,继续执行下面的代码

final void setDaemon(boolena on);

  • 当其他的非守护线程执行完毕之后,守护线程会陆续结束

public static void yield();

  • 让线程的执行更加均匀

public final void join();

  • 插入线程

线程的生命周期

sleep方法会让线程睡眠,时间到了之后,不会立马执行下面的的代码,会进入就绪状态。

同步代码块

synchronized(锁){

        操作共享数据的代码

}

  • 锁默认打开,有一个线程进去了,锁自动关闭
  • 里面的代码全部执行完毕,线程出来,锁自动打开

锁对象一定要是唯一的。

同步方法

修饰符 synchronized 返回值类型 方法名(方法参数){…}

  •  同步方法是锁住方法里面所有的代码
  • 锁对象不能自己指定

非静态:this

静态:当前类的字节码文件

Ctrl+Alt+M  提取方法

StringBuilder 线程不安全,适用于单线程

StringBuffer 线程安全

实现Lock接口

自定义锁:static Lock lock=new ReentrantLock(Lock的实现类)

lock.lock();//锁关闭

lock.unlock();//锁打开

注意循环语句释放锁的时候,可以加上finally语句,否则会导致某一个线程带着锁,并没有打开,所以其他线程在 lock.lock()语句停止,程序不会停止。

也可以在循环语句外面重复写一句 lock.unlock();

死锁:注意不要让两个锁嵌套使用

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

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

相关文章

【微信小程序】关于实现自定义图片代替checkbox样式的记录

前言 checkbox很好使&#xff0c;使用中往往需要改变它的样式。 记录一下用自定义的图片代替原有样式的过程。 关于把checkbox从&#xff1a;变成的过程 正文 思路 问题拆分&#xff1a; ①如何修改checkbox的样式 ②如何使用图片代替原有样式 如何修改checkbox的样式 修…

氢原子的电子轨道半径、能量、速度

在https://blog.csdn.net/qq_35379989/article/details/130065868?spm1001.2014.3001.5501中我们已经给出了波尔模型的三大假设&#xff1a;定态假设、跃迁假设以及角动量量子化。 一、氢原子的轨道半径 在跃迁假设中&#xff0c;通过设定波尔模型轨道能量&#xff1a;与电子…

各种商业版本的ChatGPT已经推出了,还有必要搞个人的Chat吗?

一、引言 虽然市面上已经存在许多商业版本的ChatGPT交互产品&#xff0c;但在我们的开发中&#xff0c;决定专注于打造一个更加个性化、更贴合个人需求的智能助手。我们相信&#xff0c;每个人都是独一无二的&#xff0c;他们的需求也是各不相同的。因此&#xff0c;个人ChatG…

浅析PHP代码审计中的SQL注入漏洞

浅析PHP代码审计中的SQL注入漏洞1.概述2.普通注入3.编码注入宽字节注入二次urldecode注入4.漏洞防范gpc/rutime魔术引号过滤函数和类addslashes函数mysql_[real_]escape_string函数intval等字符转换PDO prepare预编译1.概述 SQL注入的攻击方式有下面几种&#xff1a; 在权限较…

常用电阻的作用

1、限流&#xff1a; 根据公式&#xff1a;I U / R&#xff1b;可知&#xff0c;电压固定的情况下&#xff0c;电阻越大&#xff0c;电流越小 常用于保护器件&#xff0c; 例如&#xff1a;MCU的输入输出信号线串联电阻&#xff0c;以避免电流过大&#xff0c;损坏元器件 …

快鲸scrm助力眼科机构提效客户运营,提升转化率

眼科机构普遍面临着以下几方面的业务挑战 &#xff08;1&#xff09;存在信任危机&#xff0c;用户决策周期长 眼睛是心灵的窗户&#xff0c;患者在对眼部治疗机构的选择上格外慎重&#xff0c;因而决策周期较长&#xff0c;眼科机构需要通过品牌建设、 IP 的打造、优质的产品…

SDL(2)-加载图片

加载BMP 1.使用SDL_init初始化SDL库 2.使用SDL_CreateWindow创建一个窗口 3.使用SDL_GetWindowSurface获取创建窗口的surface 4.使用SDL_LoadBMP加载一张BMP图片 5.使用SDL_BlitSurface将加载的bmp surface拷贝到窗口的surface 6.使用SDL_UpdateWindowSurface更新到窗口 …

【严重】vm2 <3.9.15 沙箱逃逸漏洞(CVE-2023-29017)

漏洞描述 vm2 是一个沙箱&#xff0c;用于在 Node.js 环境中运行不受信任的代码。宿主对象(Host objects)是指由 Node.js 的宿主环境提供的对象&#xff0c;例如全局对象、文件系统或网络请求等。 vm2 3.9.15之前版本中&#xff0c;当处理异步错误时未正确处理 Error.prepare…

中国大学哪家强?Python爬取排名榜,太棒啦(31)

小朋友们好&#xff0c;大朋友们好&#xff01; 我是猫妹&#xff0c;一名爱上Python编程的小学生。 欢迎和猫妹一起&#xff0c;趣味学Python。 今日主题 如何用Python&#xff0c;抓取并分析2023中国大学排名数据。 用到的Python库有requests、bs4。 requests库 reque…

PixiJS 渲染优化

最近做在线CAD可视化与编辑&#xff0c;对前端的可视化渲染技术进行了选型&#xff0c;对于二维CAD来说一般用canvas就够了&#xff0c;但是canvas每一次平移&#xff0c;缩放&#xff0c;更新数据都需要重新计算渲染所有的图形数据&#xff0c;数据一多就显得非常卡。如果使用…

TCP和UDP在实际工作中的应用

前言 日常在网上浏览一些文章时都会看到一些介绍TCP和UDP的文章&#xff0c;每次都是草草浏览&#xff0c;而没有深入的去研究&#xff0c;这几天在做日志采集工具的时候恰好遇到一个问题&#xff0c;就是采集端将采集到的内容发送到服务端时这里采用的通信协议应该如何考量&a…

SpringBoot源码分析

SpringBoot源码分析1.启动类分析2.SpringBoot的项目启动流程1.SpringApplication构造函数1&#xff09;deduceFromClasspath()2&#xff09;getSpringFactoriesInstances2.1&#xff09;loadFactoryNames加载类名称2.2&#xff09;createSpringFactoriesInstances创建实例2.run…

gradle环境搭建

目录 gradle是什么 gradle环境搭建 IDEA 配置 Gradle 创建 Gradle 项目 gradle是什么 Gradle是一个基于Apache Ant和Apache Maven概念的项目自动化构建开源工具。它使用一种基于Groovy的特定领域语言(DSL)来声明项目设置&#xff0c;也增加了基于Kotlin语言的kotlin-based …

Java基础总结(二)

文章目录一、ObjectObject中的成员方法&#xff08;11个&#xff09;toStringequalsclone二、Objects三、BigInteger和BigDecimaBigIntegerBigDecima四、正则表达式五、DateJDK7前时间相关类SimpleDateFormat类Calendar类JDK8新增时间相关类六、包装类一、Object 没有一个属性…

【密码算法 之十四】非对称算法,ECC椭圆曲线算法 之 ECDSA、ECDH、SM2、SM9等

文章目录1. ECC椭圆曲线1.1 曲线类型1.2 曲线标准1.3 表示方法1.4 曲线运算1.4.1 点加&#xff08;Point Addition&#xff09;1.4.2 点乘&#xff08;Point Multiplication&#xff09;1.4.3 倍点&#xff08;Point Double&#xff09;2. ECDSA2.1 私钥签名2.2 公钥验签3. ECD…

Java——旋转数组的最小数字

题目链接 牛客在线oj题——旋转数组的最小数字 题目描述 有一个长度为 n 的非降序数组&#xff0c;比如[1,2,3,4,5]&#xff0c;将它进行旋转&#xff0c;即把一个数组最开始的若干个元素搬到数组的末尾&#xff0c;变成一个旋转数组&#xff0c;比如变成了[3,4,5,1,2]&…

Stable Diffusion成为生产力工具(五):放大并修复老照片、马赛克照片、身份证件照

S&#xff1a;你安装stable diffusion就是为了看小姐姐么&#xff1f; I &#xff1a;当然不是&#xff0c;当然是为了公司的发展谋出路~~ 预先学习&#xff1a; 安装webui《Windows安装Stable Diffusion WebUI及问题解决记录》。运行使用时问题《Windows使用Stable Diffusion时…

Kubernetes 多集群管理工具Kuboard v3

目录 一、概述 二、安装和基本使用 2.1 添加k8s集群 2.2 信息查看 2.2.1概要信息查看 2.2.2导入集群的节点信息 2.2.3 存储 2.3创建工作负载 一、概述 Kuboard&#xff0c;是一款免费的 Kubernetes 图形化管理工具&#xff0c;Kuboard 力图帮助用户快速在 Kubernetes 上…

Tomcat8性能优化

文章目录授人以鱼不如授人以渔目的服务器资源Tomcat整体架构Tomcat配置优化Linux环境安装运行Tomcat8AJP连接什么是AJP执行器&#xff08;线程池&#xff09;3种运行模式bionioapr禁用DNS查询添加Listener版本号隐藏压缩传输部署测试用的web项目查看服务器信息查看Linux版本查看…

three.js学习 01-使用最基本的方法创建出来一个threejs立方体,three.js开发环境搭建

1.当前实现的最终效果&#xff1a; 我们将会在页面上使用threejs的渲染器创建场景和相机&#xff0c;并且将一个简单几何体结果的canvas嵌入到我们的网页中 2.环境以及工具介绍&#xff1a; three中文官方文档地址&#xff1a;https://www.three3d.cn/docs/index.html 使用的开…