java——IO流基础

目录

  • IO流
    • IO流的四大分类:
    • IO流的体系:
    • FileinputStream(文件字节输入流)
    • FileOutputStream(文件字节输出流)
    • 文件复制
    • 资源释放
    • FileReader(文件字符输入流)
    • FileWriter(文件字符输出流)
    • 缓冲流
      • 字节缓冲流
      • 字符缓冲流
    • 原始流、缓冲流的性能分析
      • 测试代码:
      • 测试一:
      • 测试二:
      • 测试三:
      • 测试四:
    • 转换流
      • InputStreamReader (字符输入转换流)
      • OutputStreamWriter(字符输出转换流)
    • 打印流(PrintStream/PrintWriter)
      • 字节打印流
      • 字符打印流
      • PrintStream和Printwriter的区别
      • 重定向输出语句
    • 数据流
      • DataOutputStream(数据输出流)
      • DatalnputStream(数据输入流)
    • 序列化流
      • ObjectOutputStream(对象字节输出流)
      • ObjectinputStream(对象字节输入流)
      • 如果要一次序列化多个对象,怎么做?
    • IO框架

IO流

用于读写数据的数据流 (可以读写磁盘文件,或网络中的数据…)

IO流的四大分类:

  • 字节输入流:以内存为基准,来自磁盘文件/网络中的数据以字节的形式读入到內存中去的流
  • 字节输出流:以内存为基准,把内存中的数据以字节写出到磁盘文件或者网络中去的流。
  • 字符输入流:以内存为基准,来自磁盘文件/网络中的数据以字符的形式读入到内存中去的流。
  • 字符输出流:以内存为基准,把内存中的数据以字符写出到磁盘文件或者网络介质中去的流。

IO流的体系:

20240222-041004-Bf.png

FileinputStream(文件字节输入流)

作用:以内存为基准,可以把磁盘文件中的数据以字节的形式读入到内存中去。
20240222-041225-tI.png

FileOutputStream(文件字节输出流)

作用:以内存为基准,把内存中的数据以字节的形式写出到文件中去。20240222-050152-3K.png

文件写入换行符:os.write("/r/n”.getBytes());

文件复制

20240222-143944-i8.png

代码实现:

package cn.kt.FileAndIO;import java.io.*;public class FileCopy {public static void main(String[] args) {InputStream is = null;OutputStream os = null;try {// 需求:复制照片。//1、创建一个字节输入流管道与源文件接通is = new FileInputStream("/Users/mac/Downloads/hzw.jpg");//2、创建一个字节输出流管道与目标文件接通。os = new FileOutputStream("/Users/mac/tao/hzw.jpg");//3、创建一个字节数组,负责转移字节数据。byte[] buffer = new byte[1024];// 1KB.//4、从字节输入流中读取宁节数据,写出去到宁节输出流中。读多少写出去多少。int len;    // 记住每次读取了多少个字节。while ((len = is.read(buffer)) != -1) {os.write(buffer, 0, len);}System.out.println("复制完成!!");} catch (IOException e) {e.printStackTrace();} finally {try {if (os != null) os.close();} catch (IOException e) {e.printStackTrace();}try {if (is != null) is.close();} catch (IOException e) {e.printStackTrace();}}}
}

注意:字节流非常话合做一切文件的复制操作
任何文件的底层都是字节,字节流做复制,是一字不漏的转移完全部字节,只要复制后的文件格式一致就没问题!

资源释放

JDK 7开始提供了更简单的资源释放方案:try-with-resource
20240222-152716-Os.png

代码示例:

package cn.kt.FileAndIO;import java.io.*;/*** 描述: 复制照片。*/
public class FileCopy {public static void main(String[] args) {try (//1、创建一个字节输入流管道与源文件接通InputStream is = new FileInputStream("/Users/mac/Downloads/hzw.jpg");//2、创建一个字节输出流管道与目标文件接通。OutputStream os = new FileOutputStream("/Users/mac/tao/hzw.jpg");// 注意:这里只能放置资源对象。(流对象)// 什么是资源呢?资源都是会实现AutoCloseable接口) {//3、创建一个字节数组,负责转移字节数据。byte[] buffer = new byte[1024];// 1KB.//4、从字节输入流中读取宁节数据,写出去到宁节输出流中。读多少写出去多少。int len;    // 记住每次读取了多少个字节。while ((len = is.read(buffer)) != -1) {os.write(buffer, 0, len);}System.out.println("复制完成!!");} catch (IOException e) {e.printStackTrace();}}
}

代码相对简洁很多

FileReader(文件字符输入流)

作用:以内存为基准,可以把文件中的数据以字符的形式读入到内存中去。

20240222-153237-sE.png

FileWriter(文件字符输出流)

作用:以内存为基准,把内存中的数据以字符的形式写出到文件中去。
20240222-154058-wI.png

字符输出流使用时的注意事项
字符输出流写出数据后,必须刷新流,或者关闭流,写出去的数据才能生效
20240222-154945-pw.png

字节流、字符流的使用场景小结:
字节流适合做一切文件数据的拷贝(音视频,文本);字节流不适合读取中文内容输出。
字符流适合做文本文件的操作(读,写)。

缓冲流

20240222-160144-0G.png

字节缓冲流

提高字节流读写数据的性能
原理:字节缓冲输入流自带了8KB缓冲池;字节缓冲输出流也自带了8KB缓冲池。

20240222-155544-Bg.png
20240222-155840-nI.png

字符缓冲流

  1. BufferedReader(字符缓冲输入流)
    作用:自带8K(8192)的字符缓冲池,可以提高字符输入流读取字符数据的性能。

20240222-160545-Id.png

  1. BufferedWriter(字符缓冲输出流)
    作用:自带8K的字符缓冲池,可以提高字符输出流写字符数据的性能。

20240222-162236-0q.png

原始流、缓冲流的性能分析

测试代码:

package cn.kt.FileAndIO;import java.io.*;/*** Created by tao.* Date: 2024/2/22 16:44* 描述: 观察原始流和缓冲流的性能。*/public class BufferStreamTimeTest {// 复制的视频路径private static final String SRC_FILE = "D:\\resource\\线程池.avi";// 复制到哪个目的地private static final String DEST_FILE = "D:\\";public static void main(String[] args) {// copy01(); // 低级字节流一个一个字节的赋值,慢的简直让人无法忍受,直接淘汰!copy02();// 低级的字节流流按照一个一个字节数组的形式复制,速度较慢!// copy03(); // 缓冲流按照一个一个字节的形式复制,速度较慢,直接淘汰!copy04(); // 缓冲流按照一个一个字节数组的形式复制,速度极快,推荐使用!}private static void copy01() {long startTime = System.currentTimeMillis();try (InputStream is = new FileInputStream(SRC_FILE);OutputStream os = new FileOutputStream(DEST_FILE + "1.avi");) {int b;while ((b = is.read()) != -1) {os.write(b);}} catch (Exception e) {e.printStackTrace();}long endTime = System.currentTimeMillis();System.out.println("低级字节流一个一个字节复制耗时:" + (endTime - startTime) / 1000.0 + "s");}private static void copy02() {long startTime = System.currentTimeMillis();try (InputStream is = new FileInputStream(SRC_FILE);OutputStream os = new FileOutputStream(DEST_FILE + "2.avi");) {byte[] buffer = new byte[1024 * 64];int len;while ((len = is.read(buffer)) != -1) {os.write(buffer, 0, len);}} catch (Exception e) {e.printStackTrace();}long endTime = System.currentTimeMillis();System.out.println("低级字节流使用字节数组复制耗时:" + (endTime - startTime) / 1000.0 + "s");}private static void copy03() {long startTime = System.currentTimeMillis();try (InputStream is = new FileInputStream(SRC_FILE);BufferedInputStream bis = new BufferedInputStream(is);OutputStream os = new FileOutputStream(DEST_FILE + "3.avi");BufferedOutputStream bos = new BufferedOutputStream(os);) {int b;while ((b = bis.read()) != -1) {bos.write(b);}} catch (Exception e) {e.printStackTrace();}long endTime = System.currentTimeMillis();System.out.println("缓冲流一个一个字节复制耗时:" + (endTime - startTime) / 1000.0 + "s");}private static void copy04() {long startTime = System.currentTimeMillis();try (InputStream is = new FileInputStream(SRC_FILE);BufferedInputStream bis = new BufferedInputStream(is, 64 * 1024);OutputStream os = new FileOutputStream(DEST_FILE + "4.avi");BufferedOutputStream bos = new BufferedOutputStream(os, 64 * 1024);) {byte[] buffer = new byte[1024 * 64]; // 32KBint len;while ((len = bis.read(buffer)) != -1) {bos.write(buffer, 0, len);}} catch (Exception e) {e.printStackTrace();}long endTime = System.currentTimeMillis();System.out.println("缓冲流使用字节数组复制耗时:" + (endTime - startTime) / 1000.0 + "s");}
}

测试一:

分别使用原始的字节流,以及字节缓冲流复制一个很大视频(889MB)。
测试步骤:

  1. 使用低级的字节流按照一个一个字节的形式复制文件。
  2. 使用低级的字节流按照字节数组的形式复制文件。
  3. 使用高级的缓冲字节流按照一个一个字节的形式复制文件。
  4. 使用高级的缓冲字节流按照字节数组的形式复制文件。

默认情况测试结果:

  1. 低级流一个字节复制: 慢得简直让人无法忍受
  2. 低级流按照字节数组复制(数组长度1024): 12.117s
  3. 缓冲流一个字节复制: 11.058s
  4. 缓冲流按照字节数组复制(数组长度1024): 2.163s

经过上面的测试,我们可以得出一个结论:默认情况下,采用一次复制1024个字节,缓冲流完胜。

测试二:

但是,缓冲流就一定性能高吗?我们采用一次复制8192个字节试

1. 低级流按照字节数组复制(数组长度8192): 2.535s
2. 缓冲流按照字节数组复制(数组长度8192): 2.088s

经过上面的测试,我们可以得出一个结论:一次读取8192个字节时,低级流和缓冲流性能相当。相差的那几毫秒可以忽略不计。

测试三:

继续把数组变大,看一看缓冲流就一定性能高吗?现在采用一次读取1024*32个字节数据试试(缓冲流底层的字节数组也设成32k)

1. 低级流按照字节数组复制(数组长度32k): 1.128s
2. 缓冲流按照字节数组复制(数组长度32k): 1.133s

测试四:

继续把数组变大,看一看缓冲流就一定性能高吗?现在采用一次读取1024*64个字节数据试试

1. 低级流按照字节数组复制(数组长度64k): 1.039s
2. 缓冲流按照字节数组复制(数组长度64k): 1.151s

此时你会发现,当数组大到一定程度,性能已经提高不了多少了,甚至缓冲流的性能还没有低级流高。
在实际开发中,想提升读写性能就扩大数组大小,大小取决于经验,并且缓冲流的性能不一定就比低级流好。

转换流

解决的问题:不同编码读取出现乱码的问题

  1. 如果代码编码和被读取的文本文件的编码是一致的,使用字符流读取文本文件时不会出现乱码!
  2. 如果代码编码和被读取的文本文件的编码是不一致的,使用字符流读取文本文件时就会出现乱码!
    20240222-174932-ZD.png

InputStreamReader (字符输入转换流)

解决不同编码时,字符流读取文本内容乱码的问题。
解决思路:先获取文件的原始字节流,再将其按真实的字符集编码转成字符输入流,这样字符输入流中的字符就不乱码了。

20240222-175337-6U.png
InputStreamReader也是不能单独使用的,它内部需要封装一个InputStream的子类对象,再指定一个编码表,如果不指定编码表,默认会按照UTF-8形式进行转换。我们可以先准备一个GBK格式的文件,然后使用下面的代码进行读取是不会有乱码的。
代码示例:

public class InputStreamReaderTest {public static void main(String[] args) {try (// 1、得到文件的原始字节流(GBK的字节流形式)// 2、把原始的字节输入流按照指定的字符集编码转换成字符输入流Reader isr = new InputStreamReader(new FileInputStream("io-app2/src/06.txt"), "GBK");//多态写法// 3、把字符输入流包装成缓冲字符输入流BufferedReader br = new BufferedReader(isr);){String line;while ((line = br.readLine()) != null){System.out.println(line);}} catch (Exception e) {e.printStackTrace();}}
}

OutputStreamWriter(字符输出转换流)

作用:可以控制写出去的字符使用什么字符集编码。
解决思路:获取字节输出流,再按照指定的字符集编码将其转换成字符输出流,以后写出去的字符就会用该字符集编码了。

20240222-180125-u2.png

OutputStreamReader也是不能单独使用的,它内部需要封装一个OutputStream的子类对象,再指定一个编码表,如果不指定编码表,默认会按照UTF-8形式进行转换。我们可以先准备一个GBK格式的文件,使用下面代码往文件中写字符数据。
代码示例:

public class OutputStreamWriterTest2 {public static void main(String[] args) {// 指定写出去的字符编码。try (// 1、创建一个文件字节输出流OutputStream os = new FileOutputStream("io-app2/src/out.txt");// 2、把原始的字节输出流,按照指定的字符集编码转换成字符输出转换流。Writer osw = new OutputStreamWriter(os, "GBK");// 3、把字符输出流包装成缓冲字符输出流BufferedWriter bw = new BufferedWriter(osw);){bw.write("我是中国人abc");bw.write("我爱你中国123");} catch (Exception e) {e.printStackTrace();}}
}

打印流(PrintStream/PrintWriter)

20240222-180711-Y6.png

作用:打印流可以实现更方便、更高效的打印数据出去,能实现打印啥出去就是啥出去。

字节打印流

20240222-181147-0W.png

字符打印流

20240222-181749-DR.png

代码示例:

public class PrintTest1 {public static void main(String[] args) {try (// 1、创建一个打印流管道
//                PrintStream ps =
//                        new PrintStream("io-app2/src/itheima08.txt", Charset.forName("GBK"));
//                PrintStream ps =
//                        new PrintStream("io-app2/src/itheima08.txt");PrintWriter ps =new PrintWriter(new FileOutputStream("io-app2/src/itheima08.txt", true));//注意 高级流不支持追加参数 所以想要追加的方式来写 就得先包装一个低级流并声明是追加型写入){ps.print(97);	//文件中显示的就是:97而不是aps.print('a'); //文件中显示的就是:aps.println("我爱你中国abc");	//文件中显示的就是:我爱你中国abcps.println(true);//文件中显示的就是:trueps.println(99.5);//文件中显示的就是99.5ps.write(97); //文件中显示a,发现和前面println方法的区别了吗?println自带换行} catch (Exception e) {e.printStackTrace();}}
}

其实打印流我们一直在使用,只是没有感受到而已。打印流可以实现更加方便,更加高效的写数据的方式。
这里所说的打印其实就是写数据的意思,它和普通的write方法写数据还不太一样,一般会使用打印流特有的方法叫print(数据)或者println(数据),它的特点是打印啥就输出啥,并且内部底层自己封装了缓冲流,所以性能也不差。

PrintStream和Printwriter的区别

  1. 打印数据的功能上是一模一样的:都是使用方便,性能高效(核心优势)
  2. PrintStream继承自字节输出流OutputStream,因此支持写字节数据的方法。
  3. PrintWriter继承自字符输出流Writer,因此支持写字符数据出去。

重定向输出语句

System.out.println()这句话表示打印输出,但是至于为什么能够输出,其实我们一直不清楚。
其实是因为System里面有一个静态变量叫out,out的数据类型就是PrintStream,它就是一个打印流,而且这个打印流的默认输出目的地是控制台,所以我们调用System.out.pirnln()就可以往控制台打印输出任意类型的数据,而且打印啥就输出啥。

而且System还提供了一个方法,可以修改底层的打印流,这样我们就可以重定向打印语句的输出目的地了。示例代码如下:

public class PrintTest2 {public static void main(String[] args) {System.out.println("老骥伏枥");System.out.println("志在千里");try ( PrintStream ps = new PrintStream("io-app2/src/09.txt"); ){// 把系统默认的打印流对象改成自己设置的打印流System.setOut(ps);System.out.println("烈士暮年");	System.out.println("壮心不已");} catch (Exception e) {e.printStackTrace();}}
}

此时打印语句,将往文件中打印数据,而不在控制台。

数据流

20240222-184547-3S.png

我们想把数据和数据的类型一并写到文件中去,读取的时候也将数据和数据类型一并读出来。这就可以用到数据流,有两个DataInputStream和DataOutputStream.

DataOutputStream(数据输出流)

DataOutputStream类,它也是一种包装流,创建DataOutputStream对象时,底层需要依赖于一个原始的OutputStream流对象。然后调用它的wirteXxx方法,写的是特定类型的数据。
20240222-185020-T4.png
示例代码如下:往文件中写整数、小数、布尔类型数据、字符串数据

public class DataOutputStreamTest1 {public static void main(String[] args) {try (// 1、创建一个数据输出流包装低级的字节输出流DataOutputStream dos =new DataOutputStream(new FileOutputStream("io-app2/src/10out.txt"));){dos.writeInt(97);dos.writeDouble(99.5);dos.writeBoolean(true);dos.writeUTF("666");} catch (Exception e) {e.printStackTrace();}}
}
//运行完之后666前面显示的是乱码,但其实不是发生了编码错误,而是一种特定的数据存储方式
//因为本来就不是存给人看的,而是方便下次读取的

DatalnputStream(数据输入流)

DataIntputStream类,它也是一种包装流,用于读取数据输出流输出的数据。创建DataInputStream对象时,底层需要依赖于一个原始的InputStream流对象。然后调用它的readXxx()方法就可以读取特定类型的数据。
20240222-185309-Rg.png

示例代码如下:读取文件中特定类型的数据(整数、小数、字符串等)

public class DataInputStreamTest2 {public static void main(String[] args) {try (DataInputStream dis =new DataInputStream(new FileInputStream("io-app2/src/10out.txt"));//文件是上面数据输出流输出的文件){int i = dis.readInt();System.out.println(i);//97double d = dis.readDouble();System.out.println(d);//99.5boolean b = dis.readBoolean();System.out.println(b);//trueString rs = dis.readUTF();System.out.println(rs);//"666"} catch (Exception e) {e.printStackTrace();}}
}

注意输出的时候读取文件的数据类型要和写入文件的数据类型相同,否则会出问题。

序列化流

20240222-190021-7s.png

序列化流是干什么用的呢? 我们知道字节流是以字节为单位来读写数据、字符流是按照字符为单位来读写数据、而对象流是以对象为单位来读写数据。也就是把对象当做一个整体,可以写一个对象到文件,也可以从文件中把对象读取出来。这里有一个新词 序列化
序列化:意思就是把对象写到文件或者网络中去。(简单记:写对象)
反序列化:意思就是把对象从文件或者网络中读取出来。(简单记:读对象)

ObjectOutputStream(对象字节输出流)

ObjectOutputStream流也是一个包装流,不能单独使用,需要结合原始的字节输出流使用,可以把Java对象进行序列化:把Java对象存入到文件中去。

20240222-190353-Xy.png

代码如下:将一个User对象写到文件中去
第一步:先准备一个User类,必须让其实现Serializable接口。

// 注意:对象如果需要序列化,必须实现序列化接口。
public class User implements Serializable {private String loginName;private String userName;private int age;// transient 这个成员变量将不参与序列化,即某个对象被写到文件后再读取,这个字段就是null了。private transient String passWord;public User() {}public User(String loginName, String userName, int age, String passWord) {this.loginName = loginName;this.userName = userName;this.age = age;this.passWord = passWord;}@Overridepublic String toString() {return "User{" +"loginName='" + loginName + '\'' +", userName='" + userName + '\'' +", age=" + age +", passWord='" + passWord + '\'' +'}';}
}

注意:transient 这个成员变量将不参与序列化,即某个对象被写到文件后再读取,这个字段就是null了。

第二步:再创建ObjectOutputStream流对象,调用writeObject方法对象到文件。

public class Test1ObjectOutputStream {public static void main(String[] args) {try (// 2、创建一个对象字节输出流包装原始的字节 输出流。ObjectOutputStream oos =new ObjectOutputStream(new FileOutputStream("io-app2/src/11out.txt"));){// 1、创建一个Java对象。User u = new User("admin", "张三", 32, "666888xyz");// 3、序列化对象到文件中去oos.writeObject(u);System.out.println("序列化对象成功!!");} catch (Exception e) {e.printStackTrace();}}
}

注意:写到文件中的对象,是不能用记事本打开看的。因为对象本身就不是文本数据,打开是乱码,这里必须用反序列化,自己写代码读。
20240222-190814-WV.png

ObjectinputStream(对象字节输入流)

ObjectInputStream流,它也是一个包装流,不能单独使用,需要结合原始的字节输入流使用,可以读任意的java对象。

20240222-190932-0h.png

接着前面的案例,文件中已经有一个User对象,现在要使用ObjectInputStream读取出来。称之为反序列化。

public class Test2ObjectInputStream {public static void main(String[] args) {try (// 1、创建一个对象字节输入流管道,包装 低级的字节输入流与源文件接通ObjectInputStream ois = new ObjectInputStream(new FileInputStream("io-app2/src/itheima11out.txt"));){User u = (User) ois.readObject();System.out.println(u);} catch (Exception e) {e.printStackTrace();}}
}

如果要一次序列化多个对象,怎么做?

用一个ArrayList集合存储多个对象,然后直接对集合进行序列化即可
注意:ArrayList集合已经实现了序列化接口!

IO框架

为了简化对IO操作,很多技术大牛或者组织提供了一些有关IO流小框架,可以提高IO流的开发效率。

如:

  1. 常用的hutool:https://hutool.cn/docs/#/core/IO/%E6%A6%82%E8%BF%B0
  2. apache开源基金组织提供了一组有关IO流小框架:commons-io

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

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

相关文章

JVM虚拟机结构

虚拟机结构图 从图中看出: JVM虚拟机主要有三大部分组成: 1. 类加载器 2. JVM运行时内存 3. 执行引擎 一、类加载器 类加载器主要用来加载字节码文件(.class)到内存中 二、内存结构 如图:可将内存分为两大部分&…

Linux系统性能分析(top,iostat,free)

top Linux系统中,Top命令主要用于实时运行系统的监控,包括Linux内核管理的进程或者线程的资源占用情况。 这个命令对所有正在运行的进程和系统负荷提供不断更新的概览信息,包括系统负载、CPU利用分布情况、内存使用、每个进程的内容使用情况…

js设计模式:策略模式

作用: 根据不同的条件去进行相应的业务逻辑处理 就好比针对每种情况都制定对应的方案,触发条件就启动某项方案策略 示例: //策略对象const arrangeFun {model1:(value1,value2,value3,value4)>{return ${value1}${value2}${value3}:${value4}},model2:(value1,value2,va…

HubSpot出海营销的优势有哪些?

HubSpot在出海营销方面的优势可以更为详细地分析如下: 全球化功能支持: HubSpot的多语言支持和多地区适配功能,使得企业能够在不同国家和地区进行营销活动,而不必担心语言和文化差异的障碍。 通过全球化的模板和内容管理系统&a…

微信小程序 --- wx.request网络请求封装

网络请求封装 网络请求模块难度较大,如果学习起来感觉吃力,可以直接学习 [请求封装-使用 npm 包发送请求] 以后的模块 01. 为什么要封装 wx.request 小程序大多数 API 都是异步 API,如 wx.request(),wx.login() 等。这类 API 接口…

后端经典面试题合集

目录 1. Java基础1-1. JDK 和 JRE 和 JVM 分别是什么,有什么区别?1-2. 什么是字节码?采用字节码的最大好处是什么? 1. Java基础 1-1. JDK 和 JRE 和 JVM 分别是什么,有什么区别? JDK 是Java开发工具包&am…

实现Slider 滑块组件标记动态变化

实现以上效果&#xff0c;下拉框、slider滑块、按钮都在同一行&#xff0c;设置flex布局后&#xff0c;发现silider滑块最右边的标记数字一直都如下竖着显示&#xff0c;后来通过给源组件的标记区.el-slider__marks-text增加一个宽度后解决该问题。 <template><div>…

基于PID控制器的直流电机位置控制系统simulink建模与仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 1. PID控制器原理 2. 位置控制环 5.完整工程文件 1.课题概述 基于PID控制器的直流电机位置控制系统。直流电机位置控制系统是工业自动化领域中的一个重要应用。为了实现精确的位置控制&#xff0c;常采…

模板注入 [WesternCTF2018]shrine1

打开题目 直接查看源代码 发现注册了一个名为FLAG的config&#xff0c;这里可能有flag&#xff0c; 存在flask-jinja2模板注入&#xff0c; 并且存在黑名单过滤 输入shrine/{{7*7}}验证成功 通过url_for()与globals()函数&#xff0c;绕过黑名单 /shrine/{{url_for.__globa…

线程安全基础

文章目录 概要线程安全的三个体现一 、原子性二 、可见性三 、有序性 小结 概要 什么是线程安全&#xff1f;&#xff1f;&#xff1f; 当多个线程访问某个类时&#xff0c;不管运行时环境采用 何种调度方式 或者这些进程将如何交替执行&#xff0c;并且在主调代码中不需要任…

线性规划--状态转移(打家劫舍)

打家劫舍I 1.题目 2.思路 要解决这个问题&#xff0c;我们可以使用动态规划的方法。我们将问题分为两个子问题&#xff1a;偷窃前n-1家或者偷窃前n-2家。如果我们选择偷窃第n家&#xff0c;那么我们就不能偷窃第n-1家&#xff0c;因为它们是相邻的。所以&#xff0c;我们可以…

UnityWebGL 设置全屏

这是Unity导出Web默认打开的页面尺寸 修改后效果 修改 index.html 文件 1.div元素的id属性值为"unity-container"&#xff0c;宽度和高度都设置为100%&#xff0c;意味着该div元素将占据整个父容器的空间。canvas元素的id属性值为"unity-canvas"&#xff…

网卡本质,网络发展(局域网,广域网概念)

目录 引入 网卡的本质 网络的发展 引入 早期 局域网LAN&#xff08;Local Area Network&#xff09; 广域网WAN&#xff08;Wide Area Network&#xff09; 注意 引入 前面我们已经学习了很多关于linux系统的知识,其中文件系统和线程尤为繁杂 而网络其实也算系统的一部…

嵌入式学习-qt-Day4

嵌入式学习-qt-Day4 一、思维导图 二、作业 1.设计一个界面&#xff1a;显示系统时间&#xff1b;可以设置闹钟&#xff0c;在设置的时间到达后&#xff0c;显示五次字符串&#xff0c;并且语音播报。 Wight.h #ifndef WIDGET_H #define WIDGET_H #include <QWidget>…

Day 1.进程的基本概念、相关命令、函数结口

进程基本概念 一、进程&#xff1a; 程序&#xff1a;存放在外存中的一段数据组成的文件 进程&#xff1a;是一个程序动态执行的过程&#xff0c;包括进程的创建、进程的调度、进程的消亡 二、进程相关的命令 1.top 动态查看当前系统中所有的进程信息&#xff08;根据CPU…

Nginx网络服务二-----(虚拟机和location)

一、HTTP设置 1.设置虚拟主机 1.1Nginx 基于域名---虚拟主机 include /apps/nginx/conf.d/*.conf; 1.2Nginx 基于端口---虚拟主机 在做了域名的基础上&#xff0c;按照以下步骤继续 1.3Nginx 基于IP---虚拟主机 2.server下的root root路径格式 指定文件的路径 url …

Visual Paradigm 工具使用思考

大型项目的管理与实施&#xff0c;需要有高效的管理工具&#xff0c;VP算是不错的&#xff0c;美中不足是界面太死板&#xff0c;使用不便利&#xff0c;对于小型项目按照这个模式来&#xff0c;相当麻烦。 当然肯定会有人觉得不错&#xff0c;需要的&#xff0c;联系我

面试经典150题 -- 二叉树 (总结)

总的地址 : 面试经典 150 题 - 学习计划 - 力扣&#xff08;LeetCode&#xff09;全球极客挚爱的技术成长平台 104 . 二叉树的最大深度 104 . 二叉树的最大深度 递归 : 直接用递归访问 &#xff0c; 访问左孩子 和 右孩子 &#xff0c; 如果 存在 &#xff0c; 深度就1 &…

vue-router 三级路由,路由跳转页面异常白屏或404,或刷新三级路由页面后一级和二级路由菜单丢失

问题描述 情况1. vue-router 定义三级路由&#xff0c;路由跳转了&#xff0c;页面404或者白屏情况2. 点击菜单三级路由后&#xff0c;刷新页面后一级和二级路由菜单丢失 解决方案&#xff1a; 某些时候是因为二级和三级的路由共用router-view&#xff0c;可以使用router-vi…

基于springboot+vue的大创管理系统(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…