【文件IO】文件系统的操作 流对象 字节流(Reader/Writer)和字符流 (InputStream/OutputStream)的用法

news2025/1/11 11:43:56

目录

1.文件系统的操作 (File类)

2.文件内容的读写 (Stream流对象)

2.1 字节流

2.2 字符流

2.3 如何判断输入输出?

2.4 reader读操作 (字符流)

2.5 文件描述符表

2.6 Writer写操作 (字符流)

2.7 InputStream (字节流)

2.8 OutputStream (字节流)

 2.9 字节流转字符流

3.练习题

3.1 扫描指定目录

3.2 进行文件的复制

3.3 扫描指定目录


什么是文件?

文件是一个广义的概念。操作系统里会把很多的硬件设备和软件资源都抽象成"文件",统一进行管理。大部分情况下,谈到的文件都是指硬盘的文件。文件就相当于是针对"硬盘"数据的一种抽象。

硬盘大致分为:

  • 机械硬盘(HDD) 适合于顺序读写,不适合随机读写。
  • 固态硬盘(SSD) 现在的电脑基本都是固态硬盘。

IO

  • I : input输入
  • O:   output输出

内存和硬盘

  1. 内存速度快,硬盘速度慢。
  2. 内存空间小,硬盘空间大。
  3. 内存贵,硬盘便宜。
  4. 内存的数据断电就会丢失,硬盘的数据断电还在。

目录:其实是一种树形结构,描述文件所在的位置。

文件系统:用来管理一台计算机上的很多文件

路径:分为绝对路径和相对路径。用来定位某一计算机资源。

  • 绝对路径:指的是一个文件从根目录开始的实际存在于硬盘中的路径。
  • 相对路径:指的是相对于当前目录的路径。

文本类型

从编码的角度来看,文件主要是两大类:

  1. 文本 (文件中保存的数据,都是字符串,保存的内容要求都是合法的字符)
  2. 二进制 (文件中保存的数据,是二进制数据,不要求保存的内容是合法的字符)

常见的字符集有UTF-8,GBK。 查看码表  ->  点击查看


如何判断一个文件是文本还是二进制?

一种方法是直接用记事本打开这个文件,如果打开之后出现乱码,则文件就是二进制;反之就是文本。(能用记事本打开的原因是因为记事本就是会尝试按照字符的方式来展示内容,这个过程就会自动查码表)。在我们电脑上,很多文件都是二进制的,比如docx,pptx,... 都属于二进制。同时区分文本和二进制也是很重要的。


Java中对于文件的操作 ,有两类:

(1)文件系统的操作 (File类)

  • 创建文件,删除文件,判断文件是否存在,判定文件类型等。

(2)文件内容的操作 (流对象 Stream)

  • 读文件/写文件(InputStream / OutputStream,Reader / Writer)

1.文件系统的操作 (File类)

一个目录中,用来分割目录的路径分隔符,“/”。由于操作系统不同,有的可能是“/”,有的可能是“\”。于是Java提供了pathSeparator()这个方法,后续使用都可以调用这个方法,可以避免在不同的操作系统上运行时出错。


构造方法:

最常用是第二个,在构造对象的时候。传入路径。相对路径或绝对路径。


常用的方法:

举个例子:我们在D盘下创建一个文件:text.txt。

public class test {
    public static void main(String[] args) throws IOException {

        File file = new File("d:/test.txt");
        boolean ret = file.createNewFile();                         //创建一个空文件
        System.out.println("父目录文件路径: " + file.getParent());     //得到父目录文件路径
        System.out.println("文件名: " + file.getName());             //得到文件名
        System.out.println("文件路径: " + file.getPath());           //得到文件路径
        System.out.println("绝对路径: " + file.getAbsolutePath());   //得到绝对路径

        System.out.println("==================");

        System.out.println("文件是否存在: " + file.exists());              //判断文件是否存在
        System.out.println("文件是否是一个目录: " + file.isDirectory());    //判断该文件是否是一个目录
        System.out.println("文件是否是一个普通文件: " + file.isFile());      //判断该文件是否是一个普通文件
        
    }

}

注意:getName方法得到的文件名是加扩展名的,文件=前缀+扩展名。扩展名类似 .txt,.java这样的。 并且在构造对象时,文件名要完整。有扩展名的要加上。


2.删除文件操作

有两种,一种是直接删除 delete() 方法,另一种是等JVM运行结束后再删除 deleteOnExit() 方法。比如有多线程执行时,等执行完后再删除。后者的使用举例:比如我们在写word还没保存时,系统就会生成一种临时文件机制。


3.查看文件名,创建,删除目录, 文件重命名

使用list方法可返回当前目录下的所有文件名。前提是该对象是目录,而不是一个类似于.txt记事本这样的文件,这种会返回null。并且在打印时不能直接打印对象,这样会打印出哈希值。要用Arrays.toString() 方法打印。

创建目录有两种,一种是只能创建一级目录 mkdir() 方法,另一种是可以创建多级目录 mkdirs() 方法。

文件重命名使用 renameTo() 方法。

public class test {
    public static void main(String[] args) throws IOException {

        File srcFile = new File("d:/aaa");
        File destFile = new File("d:/bbb");
        //File srcFile = new File("d:/test.txt");
        //File destFile = new File("d:/test2.txt");
        srcFile.renameTo(destFile);  //注意是谁调用谁
        
    }
}

2.文件内容的读写 (Stream流对象)

在Java标准库中,提供的读写文件的流对象,不是一两个类,而是有很多类,虽然这里有很多的类,实际上这些类都可以归结到两个大的类别中。

2.1 字节流
  • 对应着"二进制文件",每次读写的最小单位,都是"字节"。
  • 读 :Reader   
  • 写: Writer
2.2 字符流
  • 对应着文本文件,每次读写的最小单位是"字符",(一个字符对应着一个或多个字节,比如在GBK中,一个中文字符对应两个字节;UTF-8中,一个中文字符对应三个字节)。
  • 字符流本质上是针对字节流进行了一层封装。
  • 读:InputStream
  • 写:OutputStream

2.3 如何判断输入输出?


假设我们把一个数据保存到硬盘中,如果站在硬盘的角度就是输入,如果站在CPU的角度就是输出。

而我们通常所说的输入输出就是站在CPU的角度去看的。

  • 读操作就可以认为是将硬盘上的数据放到CPU中使用。(进入cpu)
  • 写操作就可以认为是通过CPU往硬盘上存储数据。(远离cpu)


2.4 reader读操作 (字符流)

有下面这三种方法:

  1. read(); 无参数:一次只读取一个参数。返回值为整数。
  2. read(char[] cbuf); 一次读取若干个字符,会把参数指定的cbuf数组给填充满。
  3. read(char[] cbuf,int off,int len); 一次读取若干个字符,会把这个数组从off到len范围内填充。就是把数据存到这个字符数组中。

1.read();   

public class test {
    public static void main(String[] args) throws IOException {

        Reader reader = new FileReader("d:/test.txt");

        while(true) {
            int n = reader.read();  //无参
            if(n==-1) break;
            char ch = (char)n;
            System.out.println(ch);
        }
        
    }
}

至于为什么要返回整数而不应该是char型?源码:

翻译为:读取的字符,取值范围为0到65535 (0x00-0xffff)的整数(两个字节的范围),如果已经到达流的结尾,则为-1。即就是每次读取一个两个字节的数据,当读取到-1则表示读取结束。

使用整形一方面是表示-1这样的特殊情况。

还有就是到0到65535是两个字节的范围,我们知道在unicode编码中是一个中文字符对应两个字节,而在UTF-8中,一个中文字符对应三个字节。那要是使用UTF-8不会范围不够吗?

其实在Java标准库内部,对于字符集编码进行了很多的处理工作,如果只使用char,此时使用的字符集固定就是unicode;如果是使用String,就会自动的把每个字符的unicode转换成UTF-8。


2. read(char[] cbuf); 往read里传入一个空的数组,数组用来存储数据。这里的返回值表示实际读取到的字符的个数,与无参的不同,读到末尾,还是返回-1。

public class test {
   
    public static void main(String[] args) throws IOException {
       
        //一次readr读多个字符 
        Reader reader = new FileReader("d:/test.txt");
        while(true) {
            char[] cbuf = new char[1024];   //创建一个空的字符数组
            int n = reader.read(cbuf);      //传入空字符数组
            if(n==-1) {                     //-1表示读取结束
                break;
            }
            System.out.println("字符个数为:"+n);  //此处这个带参的 n 表示读取的字符个数
            for(int i=0;i<n;i++) {
                System.out.println(cbuf[i]);     //打印独读到的数据
            }
        }

        //一个文件使用完后,一定要记得close !!!
        reader.close();
    
    }
    
}

 这里还有一个重要的细节:如果使用Java的Reader方法读取文件后,一定要使用close()方法。主要目的是为了释放空间,更深的来说是释放文件描述符

2.5 文件描述符表

是PCB中的一个属性,其本质上是一个顺序表(数组),一个进程每次打开一个文件,操作系统会为其在这个表里分配一个文件描述符(元素),而这个数组的长度是存在上限的。如果我们编写的代码一直去打开文件,而不去关闭的话,就会使这个表里的元素越来越多,直到把这个数组给占满,后续再尝试打开文件就会出错。会造成文件泄露,类似内存泄漏。

但内存泄漏,Java不用担心,Java中有GC(Garbage Collection)垃圾收集机制。但是文件还是要手动释放关闭的。所以用完文件后一定要记得 手动 close


不过上面代码的代码还是存在一些问题,有可能close方法执行不到,万一代码还没执行到close时抛出个啥异常,就会导致不能close。

解决办法:使用try...finally...  将close方法写到fianlly里,这样无论抛出异常与否,fianlly语句都会执行。

public class test{

    public static void main(String[] args) throws IOException {

        Reader reader = new FileReader("d:/test.txt");

        try{
            while(true) {
                char[] cbuf = new char[1024];   //创建一个空的字符数组
                int n = reader.read(cbuf);      //传入空字符数组
                if(n==-1) {                     //-1表示读取结束
                    break;
                }
                System.out.println("字符个数为:"+n);  //此处这个带参的 n 表示读取的字符个数
                for(int i=0;i<n;i++) {
                    System.out.println(cbuf[i]);     //打印独读到的数据
                }
            }
        }finally {
            //一个文件使用完后,一定要记得close !!!
            reader.close();
        }

    }

}

上面这样写也可以,但是代码不够优雅,改进一下。

public static void main(String[] args) throws IOException {
        try(Reader reader = new FileReader("d:/test.txt")) {
            while(true) {
                char[] arr = new char[1024];
                int n = reader.read(arr);
                if(n==-1) break;
                System.out.println(n);   //n为实际读到的字符个数
                for(int i=0;i<n;i++){
                    System.out.println(arr[i]);
                }
            }
        }
    }

这次我们在try后跟了括号,一种新奇的写法,为啥能跟小括号呢?

这是Java7所提供的try-with-resources机制,会将实现了AutoCloseable接口(或者Closeable接口)的资源定义在try块无论是正常结束或是异常结束,这个资源都会被自动关闭。try小括号里面的部分称为try-with-resources块。虽然我们既没有fianlly,也没有调动close方法。但是只要你使用了这样的语法,编译器在背后就会自动帮我们去生成finally块,并且在里面也会调用关闭资源的close方法。

try的括号中所有实现Closeable的类声明都可以写在里面,流操作都可以这样写。这个语法的目的是()里定义的变量,会在try代码块结束的时候(无论是正常结束还是异常结束),自动调用其中的方法。前提是()里的对象必须要实现Closeable接口所以我们以后在操作流对象时基本都这样写了。


2.6 Writer写操作 (字符流)

同Reader一样,Writer也有多种重载方法。

  • write(int c);   一次写一个字符
  • write(String str);  一次写一个字符串
  • write(char[ ] cbuf);    一次写多个字符 字符数组
  • 后两个值的是从数组/字符串的第offset个字开始写。
  • 上面这些方法最常用的还是write(String str),一次写一个字符串。
public static void main(String[] args) throws IOException {
        try(Writer writer = new FileWriter("d:/test.txt")) {
            writer.write("你好!");
        }
    }

这样写默认情况是每次会覆盖掉之前文件中的内容。如果不想覆盖,而是想写到原来文件内容的末尾,就要在创建对象参数列表里加参数true。

public static void main(String[] args) throws IOException {
        try(Writer writer = new FileWriter("d:/test.txt",true)) {
            writer.write("你好!");
        }
    }

2.7 InputStream (字节流)

用法跟Reader差不多,都是读操作,不过这里是字节流,以字节为单位。只能传入字节byte数组。这里的返回值为实际读到的字节数

public static void main(String[] args) {
        try(InputStream inputStream = new FileInputStream("d:/test.txt")) {
            byte[] bytes = new byte[1024];    //创建空的byte数组
            int n = inputStream.read(bytes);  //传入byte数组
            System.out.println(n);
            for(int i=0;i<n;i++) {
                System.out.printf("%x\n",bytes[i]); //以十六制形式打印
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

2.8 OutputStream (字节流)

用法也是跟Writer差不多,都是写操作。不过这里是字节流,以字节为单位。只能传入字节byte数组。

虽然只能传入byte数组,但是我们可以通过字符串转byte数组。使用getBytes()方法。

public static void main(String[] args) {
        try (OutputStream outputStream = new FileOutputStream("d:/test.txt")) {
            String str = "你好!";
            outputStream.write(str.getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }
}

 同样,默认情况下,这种写操作是会覆盖掉之前文件里的内容,要想不覆盖掉,创建对象的参数中加true。

public static void main(String[] args) {
        try (OutputStream outputStream = new FileOutputStream("d:/test.txt",true)) {
            String str = "你好!";
            outputStream.write(str.getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }
}

 2.9 字节流转字符流

读操作使用Scanner。将InputStream实例对象传入Scanner中。就可以使用Scanner提供的一些方法 (例如.next()等) 读取数据了。

public static void main(String[] args) {
        try (InputStream inputStream = new FileInputStream("d:/test.txt")) {
            //将实例对象传入Scanner
            Scanner sc = new Scanner(inputStream);
            //使用Scanner提供的一些方法读取文件中的数据
            String s = sc.next();
            System.out.println(s);
        } catch (IOException e) {
            e.printStackTrace();
        }
}

写操作使用PrintWriter。也是和Scanner一样,将OutputStream实例对象传入PrintWriter中。

public static void main(String[] args) {
        try (OutputStream outputStream = new FileOutputStream("d:/test.txt")) {
            PrintWriter printWriter = new PrintWriter(outputStream);
            printWriter.println("Hello");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

不过上面这样写,我们会发现最终并没有写成功。原因是存在"缓冲区"。我们这里的写文件实际上是写入硬盘。

PritWriter这样的类,在进行写入的时候不一定是直接写入硬盘,而是先把数据写入到一个由内存构成的"缓冲区"(buffer)。引入缓冲区目的还是为了提高效率。因为把数据写入内存是非常快的,而写入硬盘却是非常慢的。为了提高效率,就会减少写硬盘的操作。这样就会使数据还未写入硬盘,进程就结束了。

解决办法:手动添加一行代码:printWriter.flush();  作用刷新缓冲区

public static void main(String[] args) {
        try (OutputStream outputStream = new FileOutputStream("d:/test.txt")) {
            PrintWriter printWriter = new PrintWriter(outputStream);
            printWriter.println("Hello");

            printWriter.flush();   //加这段代码很重要 不能忽略

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

3.练习题

3.1 扫描指定目录

扫描指定目录,并找到名称中包含指定字符的所有普通文件(不包含目录),并且后续询问用户是否要删除该文件。

public class test {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入一个要扫描的路径:");
        String path = sc.next();
        File file = new File(path);
        //判断路径是否合法
        if(!file.isDirectory()) {
            System.out.println("您输入的路径有误!");
            return;
        }
        //让用户输入一个目标文件名的关键词
        System.out.println("请输入文件的关键词:");
        String key = sc.next();
        //让这个方法进行递归扫描
        scanDir(file,key);
    }

    private static void scanDir(File rootPath, String key) {
        //当前文件的所有子文件
        File[] files = rootPath.listFiles();
        // 判断文件(文件夹)是否为空
        if(files==null) {
            return;
        }else{
            //判断是否是普通文件
            for(File f:files) {
                //输出当前扫描文件的进度
                System.out.println(f.getAbsolutePath());
                if(f.isFile()) {
                    //是普通文件 判断并删除
                    isDel(f,key);
                }else{
                    //不是普通文件(文件夹) 继续递归遍历
                    scanDir(f,key);
                }
            }

        }
    }
    //对普通文件进行删除操作
    private static void isDel(File file,String key) {
        if(file.getName().contains(key)) {
            System.out.println("是否要删除?Y/N");
            Scanner sc = new Scanner(System.in);
            String choice = sc.next();
            if(choice.equals("Y") || choice.equals("y")) {
                boolean bool = file.delete();
                if(bool) {
                    System.out.println("删除成功!");
                }
            }else{
                return;
            }
        }
    }

}

3.2 进行文件的复制

文件内容的复制。

首先会检查源文件是否是一个普通文件,再检查目的路径是否是一个目录。目的路径目录下有重名文件时是否覆盖功能。无重名文件时创建原空文件,并读写数据。

public class test {
    public static void main(String[] args) throws IOException {
        //先让用户输入要复制的源文件地址(仅输入目录)
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入要复制源文件的路径:");
        String sources = sc.next();
        File file = new File(sources);
        //判断文件是否是一个目录(即文件夹)
        if(!file.isFile()) {
            System.out.println("不是一个有效的普通文件!");
            return;
        }
        //让用户输入复制文件的目的地(不包含文件本身,只包含目录)
        System.out.println("请输入要复制文件的目的路径:");
        String destDir = sc.next();
        File file1 = new File(destDir);
        if(!file1.isDirectory()) {
            System.out.println("目的路径有误!");
            return;
        }

        //得到源文件的文件名
        String yuan = file.getName();
        //创建完整的目的文件
        File file2 = new File(destDir+"/"+yuan);
        if(!file.getName().equals(file2.getName())) {
            System.out.println("请检查目的路径输入是否正确:"+file2.getAbsolutePath());
            return;
        }
        //判断目的路径是否有和源文件同名的文件
        if(file2.exists()) {
            // 是否覆盖
            System.out.println(file2.getAbsolutePath());
            System.out.println("该路径下已有重名文件,是否覆盖? Y/N");
            String choice = sc.next();
            if(choice.equals("Y") || choice.equals("y")) {
                //不用创建普通文件 进行覆盖
                copyFile(file,file2);
            }
            return;
        }
        file2.createNewFile();
        //进入复制操作
        copyFile(file,file2);
    }

    private static void copyFile(File sourDir, File destDir) throws IOException {
        //先将目标文件数据读出来,再写入新的文件
        try(OutputStream os = new FileOutputStream(destDir)) {
            try(InputStream is = new FileInputStream(sourDir)) {
                //字节流读 先创建字节数组 再将源文件的数据读到一个临时的数组中 再把这个临时数组中的内容写入新复制的文件中
                while(true) {
                    byte[] bytes = new byte[1024];
                    int n = is.read(bytes);
                    if(n==-1) {
                        break;
                    }
                    //将数据写入新复制的文件中
                    os.write(bytes,0,n);

                }
            }
            os.flush();
        }
        System.out.println("文件复制完成!");

    }
}
3.3 扫描指定目录

扫描指定目录,并找到名称或者内容中包含指定字符的所有普通文件(不包含目录)。

和3.1差不多,再判断普通文件名是否包含关键词的基础上加了一个普通文件内容是否包含关键词。

public class test03 {
    public static void main(String[] args) throws IOException {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入一个要扫描的路径:");
        String path = sc.next();
        File file = new File(path);
        //判断路径是否合法
        if(!file.isDirectory()) {
            System.out.println("您输入的路径有误!");
            return;
        }
        //让用户输入一个目标文件名的关键词
        System.out.println("请输入文件的关键词:");
        String key = sc.next();
        //让这个方法进行递归扫描
        scanDir(file,key);
    }

    private static void scanDir(File rootPath, String key) throws IOException {
        //当前文件的所有子文件
        File[] files = rootPath.listFiles();
        // 判断文件(文件夹)是否为空
        if(files==null) {
            return;
        }else{
            //判断是否是普通文件
            for(File f:files) {
                //输出当前扫描文件的进度
                //System.out.println(f.getAbsolutePath());
                if(f.isFile()) {
                    //是普通文件 进行判断
                    isContains(f,key);
                }else{
                    //不是普通文件(文件夹) 继续递归遍历
                    scanDir(f,key);
                }
            }

        }
    }

    private static void isContains(File f, String key) throws IOException {
        String str = null;
        //字节流转字符流 Scanner
        try (InputStream is = new FileInputStream(f)) {
            //读内容 字节流
            //将InputStream对象传入Scanner中
            Scanner sc = new Scanner(is);
            str = sc.next();
        }

        if(f.getName().contains(key) || str.contains(key)) {
            System.out.println(f.getAbsolutePath());
        }

    }
    
}

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

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

相关文章

使用html2canvas将html转pdf,由于table表的水平和竖直有滚动条导致显示不全(或者有空白)

结果&#xff1a; 业务&#xff1a;将页面右侧的table打印成想要的格式的pdf&#xff0c;首先遇到的问题是table表上下左右都有滚轮而html2canvas相当于屏幕截图&#xff0c;那滚动区域如何显示出来是个问题&#xff1f; gif有点模糊&#xff0c;但是大致功能可以看出 可复制…

基于双级阈值及过零率的语音激活检测(VAD)

语音激活检测&#xff08;Voice Activity Detection, VAD&#xff09;:也称为端点检测&#xff0c;目的就是要找到音频信号的开始和结束位置。 时域方法&#xff1a; 音量&#xff1a;只用音量来进行端点检测&#xff0c;是最简单的方法&#xff0c;但是会对清音造成误判。音…

C#,数值计算——分类与推理Gaumixmod的计算方法与源程序

1 文本格式 using System; using System.Collections.Generic; namespace Legalsoft.Truffer { public class Gaumixmod { private int nn { get; set; } private int kk { get; set; } private int mm { get; set; } private double…

力扣第17题 电话号码的字母组合 c++ 回溯 经典提升题

题目 17. 电话号码的字母组合 中等 相关标签 哈希表 字符串 回溯 给定一个仅包含数字 2-9 的字符串&#xff0c;返回所有它能表示的字母组合。答案可以按 任意顺序 返回。 给出数字到字母的映射如下&#xff08;与电话按键相同&#xff09;。注意 1 不对应任何字母。…

Elasticsearch系列组件:Logstash强大的日志管理和数据分析工具

Elasticsearch 是一个开源的、基于 Lucene 的分布式搜索和分析引擎&#xff0c;设计用于云计算环境中&#xff0c;能够实现实时的、可扩展的搜索、分析和探索全文和结构化数据。它具有高度的可扩展性&#xff0c;可以在短时间内搜索和分析大量数据。 Elasticsearch 不仅仅是一个…

sqlserver系统存储过程添加用户学习

sqlserver有一个系统存储过程sp_adduser&#xff1b;从名字看是添加用户的&#xff1b;操作一下&#xff0c; 从错误提示看还需要先添加一个登录名&#xff0c;再执行一个系统过程sp_addlogin看一下&#xff0c; 执行完之后看一下&#xff0c;安全性-登录名下面有了rabbit&…

【ARM Coresight Debug 系列 -- Linux 断点 BRK 中断使用详细介绍】

文章目录 1.1 ARM BRK 指令1.2 BRK 立即数宏定义介绍1.3 断点异常处理流程1.3.1 el1_sync_handler1.3.2 el1_dbg 跟踪 1.4 debug 异常处理函数注册1.4.1 brk 处理函数的注册 1.1 ARM BRK 指令 ARMv8 架构的 BRK 指令是用于生成一个软件断点的。当处理器执行到 BRK 指令时&…

电脑办公助手之桌面便签,助力高效率办公

在现代办公的快节奏中&#xff0c;大家有应接不暇的工作&#xff0c;每天面对着复杂的工作任务&#xff0c;总感觉时间不够用&#xff0c;而且工作无厘头。对于这种状态&#xff0c;大家可以选择在电脑上安装一款好用的办公便签软件来辅助日常办公。 敬业签是一款专为办公人士…

android--屏幕适配

基础概念 像素密度 dpi &#xff08; √宽^2高^2 &#xff09; / 屏幕大小 手机分辨率 1080 * 1920 1080代表宽 1920代表高 单位为px像素 屏幕大小为英寸 标准的像素密度 mdpi 160dpi dp 密度无关像素 dp与px的转换 density (dpi / 16…

python 之enumerate()函数

文章目录 enumerate() 是 Python 中的一个内置函数&#xff0c;它用于在遍历可迭代对象&#xff08;如列表、元组、字符串等&#xff09;时同时获取每个元素的索引和值。这个函数非常有用&#xff0c;因为它允许您在迭代过程中轻松地访问元素的索引&#xff0c;而不需要手动维护…

基于RuoYi-Flowable-Plus的若依ruoyi-nbcio支持自定义业务表单流程(二)

更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码&#xff1a; https://gitee.com/nbacheng/ruoyi-nbcio 演示地址&#xff1a;RuoYi-Nbcio后台管理系统 之前讲到了流程保存的时候还要看是否是自定义业务流程应用类型&#xff0c;若是保存的时候不再检查是否有关…

常见三维建模软件有哪些?各自的特点是什么?

常见的三维建模软件包括以下这些&#xff1a; 1. 3DS Max 3D Studio Max&#xff0c;简称3DS MAX&#xff0c;是当今世界上销售量最大的三维建模、动画及渲染软件。它的应用范围广泛&#xff0c;包括计算机游戏中的动画制作、影视片的特效制作等。3DS MAX的操作相对容易&#…

幸运的袋子(递归+回溯)

目录 一、题目 二、代码 一、题目 幸运的袋子__牛客网 二、代码 #include <iostream> #include <vector> #include <algorithm> using namespace std;static int _count 0; static int sum 0; static int product 1;void Combination(vector<int>…

JAVA学习(6)-全网最详细~

&#x1f308;write in front&#x1f308; &#x1f9f8;大家好&#xff0c;我是Aileen&#x1f9f8;.希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流. &#x1f194;本文由Aileen_0v0&#x1f9f8; 原创 CSDN首发&#x1f412; 如…

【Proteus仿真】【51单片机】电蒸锅温度控制系统

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真51单片机控制器&#xff0c;使用LCD1602液晶、按键开关、蜂鸣器、DS18B20温度传感器&#xff0c;液位传感器、继电器控制加热保温装置等。 主要功能&#xff1a; 系统运行后&#…

Elasticsearch7.9.3保姆级安装教程

Linux版本Elasticsearch版本(待安装)Kibana版本(待安装)CentOS 77.9.37.9.3 一、下载地址 1、官网下载 打开地址 https://www.elastic.co/cn/downloads/past-releases#elasticsearch&#xff0c;按如图所示选择对应版本即可 2、采用wget下载 为了不必要的麻烦&#xff0c;建…

nginx.3——local的优先级和匹配方式

在http模块有server模块,在server模块才有location模块, location匹配的是uri location 匹配一旦成功&#xff0c;就不向下匹配 一、location的分类&#xff1a; 1.精确匹配 location /test 2.正则匹配 location ^~ :前缀匹配&#xff0c;以什么为开头 location ~ 区…

【RocketMQ系列四】消息示例-简单消息的实现

您好&#xff0c;我是码农飞哥&#xff08;wei158556&#xff09;&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f4aa;&#x1f3fb; 1. Python基础专栏&#xff0c;基础知识一网打尽&#xff0c;9.9元买不了吃亏&#xff0c;买不了上当。 Python从入门到精…

十五届蓝桥选拔赛Scratch-2023.08.20STEMA测评试题解析

2023年8月20日举行的第15届蓝桥杯STEMA测评Scratch编程中级组 T2 飞驰的高铁 具体要求: 1). 点击绿旗,角色、背景如图所示; 2). 按下一次数字1按键之后,画面中的景色持续向左侧水平移动(参照程序演示视频); 3). 按下一次数字2按键之后,程序结束。 评判标准: 5分:…

“岗课赛证”融通的物联网综合实训室建设方案

一、概述 随着5G技术的普及应用和产业经济的革新发展,物联网产业所呈现的广阔前景带来了对创新型技术技能人才的迫切需求。高职院校物联网专业建设也因此转变为面向国家战略性新兴产业发展需求。当前,“岗位课程竞赛证书”融通的培育理念,是高职院校物联网人才培养和专业优化的…