编程语言Java——核心技术篇(五)IO流:数据洪流中的航道设计

 

🌟 你好,我是 励志成为糕手 !
🌌 在代码的宇宙中,我是那个追逐优雅与性能的星际旅人。

✨ 每一行代码都是我种下的星光,在逻辑的土壤里生长成璀璨的银河;
🛠️ 每一个算法都是我绘制的星图,指引着数据流动的最短路径;
🔍 每一次调试都是星际对话,用耐心和智慧解开宇宙的谜题。

🚀 准备好开始我们的星际编码之旅了吗?

续前篇:编程语言Java——核心技术篇(四)集合类详解-CSDN博客

目录

5. IO流

5.1 IO流基本概述

5.1.1 IO流概述

5.1.2 IO流体系

5.2 常用I/O流详解

5.2.1 基础文件流

5.2.2 缓冲流

5.2.3 字符流

5.2.4 高级功能流

5.3 常用I/O流示例

5.3.1 文本文件读取示例

5.3.2 缓冲字符流完整示例(文本处理)

5.3.3 对象序列化与反序列化

5.4 常用I/O流对比

5.4.1 文件读写流对比

5.4.1.1 FileInputStream vs FileReader

5.4.1.2 FileOutputStream vs FileWriter

5.4.2 缓冲流对比

5.4.2.1 BufferedInputStream vs BufferedReader

5.4.2.2 缓冲流性能测试

5.4.3 高级功能流对比

5.4.3.1 DataInputStream vs ObjectInputStream

5.4.3.2 PrintStream vs PrintWriter

5.5 流的选择决策树


5. IO流

5.1 IO流基本概述

5.1.1 IO流概述

I/O流(Input/Output Stream)是Java中用于处理输入输出的抽象概念,它代表数据的流动:

  • 流的方向

    • 输入流(InputStream/Reader):从数据源读取数据到程序

    • 输出流(OutputStream/Writer):从程序写出数据到目的地

  • 数据类型

    • 字节流(Byte Stream):以字节(8bit)为单位,处理二进制数据

      • InputStream/OutputStream及其子类

    • 字符流(Character Stream):以字符(16bit)为单位,处理文本数据

      • Reader/Writer及其子类

5.1.2 IO流体系

这里直接上图吧,这个图里面也画得很清楚了。我们可以看到Java在设计IO流的时候主要考虑了两个维度,一个是流的方向,而另一个就是流的属性了。如果从流的方向来考虑就是输入流和输出流;从流的属性上考虑就是字节流和字符流了。

另外,在每一个不同的流的实现类中从取名上来讲也很好分辨——我们可以把字节流想象成一个类似输出的框架负责输入和输出,in和out分别代表不同方向;字节流就看成字符串,只不过可是多了一层方向的属性,刚好输入就是reader(读),输出就是writer(写)。至于再往下细分可能不同的小类侧重点又有不同,适合不同的数据类型,这个需要在后续写代码的过程中不断积累。

1. 字节流体系

(1) 输入流(InputStream)

java.io.InputStream
├── FileInputStream          // 文件输入流
├── ByteArrayInputStream     // 字节数组输入流
├── PipedInputStream         // 管道输入流
├── FilterInputStream        // 过滤流(装饰器基类)
│   ├── BufferedInputStream  // 缓冲输入流
│   ├── DataInputStream      // 数据输入流(读取基本数据类型)
│   └── PushbackInputStream  // 回退输入流
├── ObjectInputStream        // 对象反序列化流
└── SequenceInputStream      // 序列输入流(合并多个流)

(2) 输出流(OutputStream)

java.io.OutputStream
├── FileOutputStream         // 文件输出流
├── ByteArrayOutputStream    // 字节数组输出流
├── PipedOutputStream        // 管道输出流
├── FilterOutputStream       // 过滤流(装饰器基类)
│   ├── BufferedOutputStream // 缓冲输出流
│   ├── DataOutputStream     // 数据输出流(写入基本数据类型)
│   └── PrintStream          // 打印流
└── ObjectOutputStream       // 对象序列化流

2. 字符流体系

(1) 输入流(Reader)

java.io.Reader
├── InputStreamReader        // 字节到字符的桥接流
│   └── FileReader           // 文件字符输入流(常用)
├── CharArrayReader          // 字符数组输入流
├── PipedReader              // 管道字符输入流
├── FilterReader             // 过滤字符流
│   └── PushbackReader       // 回退字符流
├── BufferedReader           // 缓冲字符输入流(常用)
└── StringReader             // 字符串输入流

(2) 输出流(Writer)

java.io.Writer
├── OutputStreamWriter       // 字符到字节的桥接流
│   └── FileWriter           // 文件字符输出流(常用)
├── CharArrayWriter          // 字符数组输出流
├── PipedWriter              // 管道字符输出流
├── FilterWriter             // 过滤字符流
├── BufferedWriter           // 缓冲字符输出流(常用)
├── PrintWriter              // 打印字符流(常用)
└── StringWriter             // 字符串输出流

 这里只是做一个简单的解释,如果想看详细的解析可以直接尝试看看源码。

5.2 常用I/O流详解

需要注意的是,因为流的运行需要涉及到输入和输出,所以一般需要用try-catch的形式来捕获异常,或者在写代码前就将异常抛出,不然代码会报错。

5.2.1 基础文件流

1. FileInputStream(文件字节输入流)

特点:

  • 用于读取二进制文件

  • 每次读取一个字节(8位)

  • 适合处理图片、音频、视频等非文本文件

构造方法:

FileInputStream(String name)
FileInputStream(File file)

常用方法:

int read()  // 读取单个字节
int read(byte[] b)  // 读取到字节数组
int read(byte[] b, int off, int len)  // 读取到数组指定位置

示例代码:

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;public class FileInputStreamExample {public static void main(String[] args) {FileInputStream fis = null;try {File file = new File("example.txt");fis = new FileInputStream(file);System.out.println("文件大小: " + file.length() + " bytes");int content;while ((content = fis.read()) != -1) {System.out.print((char) content);}} catch (IOException e) {System.err.println("读取文件时发生错误: " + e.getMessage());e.printStackTrace();} finally {if (fis != null) {try {fis.close();} catch (IOException e) {System.err.println("关闭文件流时发生错误: " + e.getMessage());}}}}
}

2. FileOutputStream(文件字节输出流)

特点:

  • 用于写入二进制文件

  • 支持追加模式

  • 必须手动调用flush()或close()确保数据写入

构造方法:

FileOutputStream(String name)
FileOutputStream(String name, boolean append)  // append为true表示追加
FileOutputStream(File file)

常用方法:

void write(int b)  // 写入单个字节
void write(byte[] b)
void write(byte[] b, int off, int len)

示例代码:

import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;public class FileOutputStreamExample {public static void main(String[] args) {// 使用try-with-resources自动关闭资源try (FileOutputStream fos = new FileOutputStream("output.log", true)) { // true表示追加模式String logEntry = "新的日志条目 - " + System.currentTimeMillis() + "\n";// 转换为字节数组写入byte[] bytes = logEntry.getBytes(StandardCharsets.UTF_8);fos.write(bytes);System.out.println("日志写入成功");} catch (IOException e) {System.err.println("写入文件时发生错误: " + e.getMessage());e.printStackTrace();}}
}

5.2.2 缓冲流

1. BufferedInputStream(缓冲字节输入流)

优势:

  • 默认8KB缓冲区(可配置)

  • 减少实际磁盘I/O次数

  • 特别适合大文件读取

典型用法:缓冲流文件复制

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;public class BufferedFileCopy {public static void main(String[] args) {if (args.length < 2) {System.out.println("用法: java BufferedFileCopy <源文件> <目标文件>");return;}String sourceFile = args[0];String destFile = args[1];try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(sourceFile));BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFile))) {byte[] buffer = new byte[8192]; // 8KB缓冲区int bytesRead;while ((bytesRead = bis.read(buffer)) != -1) {bos.write(buffer, 0, bytesRead);}System.out.println("文件复制完成");} catch (IOException e) {System.err.println("文件复制过程中发生错误: " + e.getMessage());e.printStackTrace();// 删除可能不完整的输出文件try {new java.io.File(destFile).delete();} catch (SecurityException se) {System.err.println("无法删除不完整的输出文件: " + se.getMessage());}}}
}

2. BufferedOutputStream(缓冲字节输出流)

注意事项:

  • 必须调用flush()或close()确保数据写出

  • 缓冲区满时自动flush

  • 适合频繁的小数据写入

性能对比:

// 无缓冲写入1万次(耗时约1200ms)
try (FileOutputStream fos = new FileOutputStream("no_buffer.txt")) {for (int i = 0; i < 10_000; i++) {fos.write("line\n".getBytes());}
}// 有缓冲写入1万次(耗时约50ms)
try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("with_buffer.txt"))) {for (int i = 0; i < 10_000; i++) {bos.write("line\n".getBytes());}bos.flush();  // 确保所有数据写出
}

5.2.3 字符流

1. InputStreamReader(字节到字符的桥梁)

核心作用:

  • 将字节流转换为字符流

  • 可指定字符编码(避免乱码)

编码处理示例:

// 读取GBK编码的文本文件
try (InputStreamReader isr = new InputStreamReader(new FileInputStream("gbk_file.txt"), "GBK")) {char[] buffer = new char[1024];int charsRead;while ((charsRead = isr.read(buffer)) != -1) {String text = new String(buffer, 0, charsRead);System.out.print(text);}
}catch{...
}

2. FileReader(文件字符输入流)

本质:

  • InputStreamReader的子类

  • 使用系统默认编码(容易导致跨平台问题)

最佳实践:

// 不推荐(使用默认编码)
FileReader reader = new FileReader("file.txt");// 推荐做法(明确指定编码)
Reader reader = new InputStreamReader(new FileInputStream("file.txt"), StandardCharsets.UTF_8);

3. BufferedReader(带缓冲的字符流)

特有方法:

String readLine()  // 读取整行(去掉换行符)

经典用法:

// 统计文本文件行数
try (BufferedReader br = new BufferedReader(new FileReader("big_text.txt"))) {int lineCount = 0;while (br.readLine() != null) {lineCount++;}System.out.println("总行数: " + lineCount);
}catch{...
}

5.2.4 高级功能流

1. DataInputStream/DataOutputStream(基本数据类型处理)

支持的数据类型:

  • 所有Java基本类型(int, double, boolean等)

  • String(UTF格式)

二进制文件读写示例:

// 写入结构化数据
try (DataOutputStream dos = new DataOutputStream(new FileOutputStream("settings.dat"))) {dos.writeUTF("系统配置");  // 字符串dos.writeInt(1024);      // 整数dos.writeDouble(3.1415); // 浮点数dos.writeBoolean(true);  // 布尔值
}// 读取结构化数据
try (DataInputStream dis = new DataInputStream(new FileInputStream("settings.dat"))) {String title = dis.readUTF();int size = dis.readInt();double value = dis.readDouble();boolean enabled = dis.readBoolean();System.out.printf("%s: size=%d, value=%.2f, enabled=%b",title, size, value, enabled);
}

2. ObjectInputStream/ObjectOutputStream(对象序列化)

序列化要求:

  • 实现Serializable接口

  • 建议添加serialVersionUID

  • transient修饰不序列化的字段

完整示例:

class User implements Serializable {private static final long serialVersionUID = 1L;private String username;private transient String password;  // 不被序列化// 构造方法、getter/setter省略
}// 序列化对象
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("user.dat"))) {User user = new User("admin", "123456");oos.writeObject(user);
}// 反序列化对象
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("user.dat"))) {User user = (User) ois.readObject();System.out.println(user.getUsername());  // 输出: adminSystem.out.println(user.getPassword());  // 输出: null(transient字段)
}

5.3 常用I/O流示例

5.3.1 文本文件读取示例

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;public class TextFileReader {public static void main(String[] args) {Path filePath = Paths.get("poem.txt");// 方法1:传统方式(JDK1.7之前)System.out.println("=== 传统读取方式 ===");BufferedReader br = null;try {br = new BufferedReader(new FileReader(filePath.toFile()));String line;while ((line = br.readLine()) != null) {System.out.println(line);}} catch (IOException e) {System.err.println("读取文件时发生错误: " + e.getMessage());} finally {if (br != null) {try {br.close();} catch (IOException e) {System.err.println("关闭流时发生错误: " + e.getMessage());}}}// 方法2:try-with-resources方式(推荐)System.out.println("\n=== 现代读取方式 ===");try (BufferedReader reader = Files.newBufferedReader(filePath, StandardCharsets.UTF_8)) {reader.lines().forEach(System.out::println);} catch (IOException e) {System.err.println("读取文件时发生错误: " + e.getMessage());e.printStackTrace();}}
}

5.3.2 缓冲字符流完整示例(文本处理)

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;public class BufferedTextProcessor {public static void main(String[] args) {Path inputFile = Paths.get("input.txt");Path outputFile = Paths.get("output_uppercase.txt");// 处理文本文件(转换为大写)processTextFile(inputFile, outputFile);// 读取文件到ListList<String> lines = readLinesFromFile(inputFile);System.out.println("读取到 " + lines.size() + " 行文本");}/*** 使用缓冲字符流处理文本文件*/private static void processTextFile(Path input, Path output) {try (BufferedReader reader = Files.newBufferedReader(input, StandardCharsets.UTF_8);BufferedWriter writer = Files.newBufferedWriter(output, StandardCharsets.UTF_8)) {String line;int lineCount = 0;while ((line = reader.readLine()) != null) {// 处理每一行(这里转换为大写)String processedLine = line.toUpperCase();// 写入处理后的行writer.write(processedLine);writer.newLine(); // 写入系统相关的换行符lineCount++;// 每处理100行输出进度if (lineCount % 100 == 0) {System.out.println("已处理 " + lineCount + " 行");}}// 确保所有数据写出writer.flush();System.out.println("文件处理完成,共处理 " + lineCount + " 行");} catch (IOException e) {System.err.println("文本处理失败: " + e.getMessage());e.printStackTrace();}}/*** 使用缓冲流读取文件到List*/private static List<String> readLinesFromFile(Path file) {List<String> lines = new ArrayList<>();try (BufferedReader reader = Files.newBufferedReader(file, StandardCharsets.UTF_8)) {String line;while ((line = reader.readLine()) != null) {lines.add(line);}} catch (IOException e) {System.err.println("读取文件失败: " + e.getMessage());e.printStackTrace();}return lines;}
}

5.3.3 对象序列化与反序列化

import java.io.*;
import java.util.ArrayList;
import java.util.List;class Student implements Serializable {private static final long serialVersionUID = 1L;private String name;private transient String password; // 不被序列化private int age;public Student(String name, String password, int age) {this.name = name;this.password = password;this.age = age;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", password='" + password + '\'' +", age=" + age +'}';}
}public class ObjectSerializationDemo {public static void main(String[] args) {List<Student> students = new ArrayList<>();students.add(new Student("张三", "zhang123", 20));students.add(new Student("李四", "li456", 22));// 序列化String filename = "students.dat";try (ObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(filename)))) {oos.writeObject(students);System.out.println("对象序列化完成");} catch (IOException e) {System.err.println("序列化过程中发生错误: " + e.getMessage());e.printStackTrace();}// 反序列化try (ObjectInputStream ois = new ObjectInputStream(new BufferedInputStream(new FileInputStream(filename)))) {@SuppressWarnings("unchecked")List<Student> deserialized = (List<Student>) ois.readObject();System.out.println("\n反序列化结果:");deserialized.forEach(System.out::println);} catch (IOException | ClassNotFoundException e) {System.err.println("反序列化过程中发生错误: " + e.getMessage());e.printStackTrace();}}
}

ps:这里做一个补充,可能很多人会不明白序列化和反序列化是什么意思。

序列化(Serialization)‌:
将对象的状态信息转换为可存储(如文件、数据库)或可传输(如网络通信)的标准化格式,常见形式包括二进制字节流、JSON、XML等。其本质是解决对象在跨平台、跨语言或持久化场景下的数据交换问题。‌‌

反序列化(Deserialization)‌:
将序列化后的数据重新解析并恢复为内存中的对象,确保程序能继续操作原始数据结构。例如从网络接收的JSON数据还原为程序中的类实例。‌‌

5.4 常用I/O流对比

5.4.1 文件读写流对比

5.4.1.1 FileInputStream vs FileReader

相同点

  • 都用于文件读取

  • 都是低级流(直接连接数据源)

不同点

特性FileInputStreamFileReader
数据类型字节(8bit)字符(16bit)
处理内容二进制文件(图片、视频等)文本文件
编码处理无编码转换自动按系统默认编码/指定编码转换
读取方法read()返回0-255的intread()返回0-65535的int(Unicode)
5.4.1.2 FileOutputStream vs FileWriter

相同点

  • 都用于文件写入

  • 都是低级流

不同点

特性FileOutputStreamFileWriter
数据类型字节字符
写入内容二进制数据文本数据
编码处理直接写入字节字符→字节转换(可指定编码)
构造参数可追加写入(append=true)可追加写入(append=true)

5.4.2 缓冲流对比

5.4.2.1 BufferedInputStream vs BufferedReader

性能对比

  • 缓冲流比非缓冲流快8-10倍(减少实际I/O操作次数)

  • BufferedReader特有readLine()方法

示例对比

// 使用BufferedInputStream读取
try (InputStream is = new BufferedInputStream(new FileInputStream("largefile.bin"), 8192)) { // 8KB缓冲区byte[] buffer = new byte[1024];int bytesRead;while ((bytesRead = is.read(buffer)) != -1) {// 处理数据}
}// 使用BufferedReader读取文本
try (BufferedReader br = new BufferedReader(new FileReader("text.txt"), 16384)) { // 16KB缓冲区String line;while ((line = br.readLine()) != null) { // 按行读取System.out.println(line);}
}
5.4.2.2 缓冲流性能测试
// 测试无缓冲 vs 有缓冲的复制速度
long start = System.nanoTime();
try (InputStream is = new FileInputStream("1GBfile.zip");OutputStream os = new FileOutputStream("copy.zip")) {byte[] buffer = new byte[8192];int bytesRead;while ((bytesRead = is.read(buffer)) != -1) {os.write(buffer, 0, bytesRead);}
}
long end = System.nanoTime();
System.out.println("无缓冲耗时: " + (end-start)/1_000_000 + "ms");start = System.nanoTime();
try (InputStream is = new BufferedInputStream(new FileInputStream("1GBfile.zip"));OutputStream os = new BufferedOutputStream(new FileOutputStream("copy.zip"))) {byte[] buffer = new byte[8192];int bytesRead;while ((bytesRead = is.read(buffer)) != -1) {os.write(buffer, 0, bytesRead);}
}
end = System.nanoTime();
System.out.println("缓冲流耗时: " + (end-start)/1_000_000 + "ms");

典型结果:

无缓冲耗时: 4523ms

缓冲流耗时: 587ms

5.4.3 高级功能流对比

5.4.3.1 DataInputStream vs ObjectInputStream

特性

DataInputStream

ObjectInputStream

主要用途

读取基本数据类型

对象反序列化

读取方法

readInt(), readDouble()等

readObject()

数据格式

简单二进制格式

Java序列化协议

版本兼容

无版本概念

使用serialVersionUID

典型用途

自定义二进制协议

Java对象持久化

示例:

// DataInputStream读取结构化二进制数据
try (DataInputStream dis = new DataInputStream(new FileInputStream("data.bin"))) {int version = dis.readInt();String name = dis.readUTF();double price = dis.readDouble();boolean inStock = dis.readBoolean();
}// ObjectInputStream读取对象
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("product.ser"))) {Product p = (Product) ois.readObject();System.out.println(p);
}
5.4.3.2 PrintStream vs PrintWriter

特性

PrintStream

PrintWriter

继承体系

FilterOutputStream子类

Writer子类

输出目标

字节流

字符流

自动刷新

可配置(autoFlush)

可配置(autoFlush)

异常处理

设置错误标志(无异常抛出)

可获取IO异常

方法

print(), println(), printf()

相同方法集

示例:

// PrintStream使用(System.out就是PrintStream)
try (PrintStream ps = new PrintStream(new FileOutputStream("log.txt"), true, "UTF-8")) {ps.println("错误日志:");ps.printf("时间: %tF %<tT%n", new Date());ps.println("温度: " + 25.6);
}// PrintWriter使用
try (PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter("report.txt")))) {pw.println("=== 测试报告 ===");pw.println("通过用例: " + 42);pw.println("失败用例: " + 3);pw.printf("通过率: %.2f%%%n", 42.0/45*100);
}

 这个就当一个扩展吧,因为感觉这个流和平时用的System.out.print()挺像的。

5.5 流的选择决策树

一样的,建议放大看,几乎涵盖了所有的应用场景。对于不同场景的敏感性是在不断地敲代码中提升的,与其去死记硬背,不如先面对问题,然后针对不同的问题再去寻求答案,找到最适配的方法;这样效率才会大大提升!

🌟 我是 励志成为糕手 ,感谢你与我共度这段技术时光!

✨ 如果这篇文章为你带来了启发:
✅ 【收藏】关键知识点,打造你的技术武器库
💡 【评论】留下思考轨迹,与同行者碰撞智慧火花
🚀 【关注】持续获取前沿技术解析与实战干货

🌌 技术探索永无止境,让我们继续在代码的宇宙中:
• 用优雅的算法绘制星图
• 以严谨的逻辑搭建桥梁
• 让创新的思维照亮前路

🛰️ 下期预告:《编程语言Java——核心技术篇(六)解剖Java反射:从Class对象到方法调用的魔鬼细节》
📡 保持连接,我们下次太空见!

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

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

相关文章

基于FPGA的16QAM软解调+卷积编码Viterbi译码通信系统,包含帧同步,信道,误码统计,可设置SNR

目录 1.引言 2.算法仿真效果 3.算法涉及理论知识概要 3.1 16QAM调制软解调原理 3.2 帧同步 3.3 卷积编码&#xff0c;维特比译码 4.Verilog程序接口 5.参考文献 6.完整算法代码文件获得 1.引言 基于FPGA的16QAM软解调卷积编码Viterbi译码通信系统开发,包含帧同步,高斯…

Python数据分析基础(二)

一、Numpy 常用函数分类概览函数类别常用函数基本数学函数np.sum(x)、np.sqrt(x)、np.exp(x)、np.log(x)、np.sin(x)、np.abs(x)、np.power(a, b)、np.round(x, n) 等统计函数np.mean(x)、np.median(x)、np.std(x)、np.var(x)、np.min(x)、np.max(x)、np.percentile(x, q) 等比…

Colab中如何临时使用udocker(以MinIO为例)

本文主要是想记录一下自己在Colab中用udocker启动一个MinIO的容器的过程。 1. 命令行配置环境 由于目前没有用到GPU&#xff0c;所以我选择的是CPU的环境。(内存12G)然后就可以在命令行里安装udocker了&#xff0c;并配置minio的环境 # 由于minio需要做两个端口映射&#xff0c…

rt-thread 5.2.1 基于at-start-f437开发过程记录

基于rt-thread 5.2.1 bsp/at/at32f437-start进行开发&#xff0c;记录详细过程&#xff0c;包括中间遇到的各种坑。 at32f437-start原理图 自己设计的电路板主要换了一块小封装的同系列芯片, 目标是移植opENer。 1. 开发环境 env长时间不用&#xff0c;有点忘了。这次新下载…

EMCCD相机与电可调变焦透镜的同步控制系统设计与实现

EMCCD相机与电可调变焦透镜的同步控制系统设计与实现 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家&#xff0c;觉得好请收藏。点击跳转到网站。 摘要 本文详细介绍了基于Python的EMCCD相机&#xff0…

前缀和-560.和为k的子数组-力扣(LeetCode)

一、题目解析1.子数组是数组中元素的连续非空序列2.nums[i]范围为[-1000,1000]&#xff0c;存在负数3.由于2的题目条件&#xff0c;该题不能用双指针算法&#xff0c;不具备单调性 二、算法原理解法1&#xff1a;暴力解法->枚举 O(N^2)固定一个值&#xff0c;向后枚举数组和…

解决企业微信收集表没有图片、文件组件,不能收集图片的问题

问题&#xff1a; 企业微信里面的收集表功能&#xff0c;有一个图片收集的收集表&#xff0c;但是插入的组件没有收集图片的组件&#xff1f; 原因&#xff1a; 大概率是微盘未启用 解决方法&#xff1a; 1、登陆企业微信管理后台 企业微信 2、访问微盘页面&#xff0c;…

认识单片机

《认识单片机》课程内容 一、课程导入 在我们的日常生活中&#xff0c;有很多看似普通却充满智慧的小物件。比如家里的智能电饭煲&#xff0c;它能精准地控制煮饭的时间和温度&#xff0c;让米饭煮得香喷喷的&#xff1b;还有楼道里的声控灯&#xff0c;当有人走过发出声音时&a…

数据结构(2)顺序表算法题

一、移除元素1、题目描述2、算法分析 思路1&#xff1a;查找val值对应的下标pos&#xff0c;执行删除pos位置数据的操作。该方法时间复杂度为O&#xff08;n^2&#xff09;&#xff0c;因此不建议使用。思路2&#xff1a;创建新数组&#xff08;空间大小与原数组一致&#xff0…

汽车电子架构

本文试图从Analog Devices官网中的汽车解决方案视角带读者构建起汽车电子的总体架构图&#xff0c;为国内热爱和从事汽车电子行业的伙伴们贡献一份力量。 一 、汽车电子架构总览 整个汽车电子包括四个部分&#xff1a;车身电子&#xff08;Body Electronics&#xff09;、座舱与…

pycharm 2025 专业版下载安装教程【附安装包】

安装之前&#xff0c;请确保已经关闭所有安全软件&#xff08;如杀毒软件、防火墙等&#xff09;安装包 &#x1f447;链接&#xff1a;https://pan.xunlei.com/s/VOU-5_L1KOH5j3zDaaCh-Z28A1# 提取码&#xff1a;6bjy下载 PyCharm2025专业版 安装包 并 进行解压运行 pycharm-2…

在 Java 世界里让对象“旅行”:序列化与反序列化

Java 生态里关于 JSON 的序列化与反序列化&#xff08;以下简称“序列化”&#xff09;是一个久经考验的话题&#xff0c;却常因框架繁多、配置琐碎而让初学者望而却步。本文将围绕一段极简的 JsonUtils 工具类展开&#xff0c;以 FastJSON 与 Jackson 两大主流实现为例&#x…

High Speed SelectIO Wizard ip使用记录

本次实验的目的是通过VU9P开发板的6个TG接口&#xff0c;采用固定连接的方式&#xff0c;即X和X-维度互联&#xff0c;其框图如下所示&#xff1a;IP参数配置通过调用High Speed SelectIO Wizard来实现数据通路&#xff0c;High Speed SelectIO Wizard ip有24对数据通道&#x…

Execel文档批量替换标签实现方案

问题背景需求&#xff1a;俺现网班级作为维度&#xff0c;批量导出每个班级学员的数据&#xff0c;excel的个数在1k左右&#xff0c;每一张表的人数在90左右。导出总耗时在10小时左右。代码编写完成并导出现网数据后&#xff0c;发现导出的标题错了。解决方案1.通过修改代码&am…

SpringBoot配置多数据源多数据库

Springboot支持配置多数据源。默认情况&#xff0c;在yml文件中只会配置一个数据库。如果涉及到操作多个数据库的情况&#xff0c;在同实例中&#xff08;即同一个ip地址下的不同数据库&#xff09;&#xff0c;可以采用数据库名点数据库表的方式&#xff0c;实现跨库表的操作。…

Rocky9.4部署Zabbix7

一、配置安装源 rpm -Uvh https://repo.zabbix.com/zabbix/7.0/rocky/9/x86_64/zabbix-release-7.0-5.el9.noarch.rpm ​ yum clean all 二、安装Zabbix server&#xff0c;Web前端&#xff0c;agent yum install zabbix-server-mysql zabbix-web-mysql zabbix-nginx-conf z…

【Java】对象类型转换(ClassCastException)异常:从底层原理到架构级防御,老司机的实战经验

在开发中&#xff0c;ClassCastException&#xff08;类转换异常&#xff09;就像一颗隐藏的定时炸弹&#xff0c;常常在代码运行到类型转换逻辑时突然爆发。线上排查问题时&#xff0c;这类异常往往因为类型关系复杂而难以定位。多数开发者习惯于在转换前加个instanceof判断就…

探路者:用 AI 面试加速人才集结,为户外爱好者带来更专业的服务

作为深耕户外用品领域的知名品牌&#xff0c;探路者已构建起覆盖全国的销售服务网络&#xff0c;上千品种的产品矩阵更是为品牌在市场中站稳脚跟提供了有力支撑。对探路者来说&#xff0c;要持续为户外爱好者带来专业且贴心的体验&#xff0c;专业人才是核心支撑。然而&#xf…

LeetCode——面试题 05.01 插入

通过万岁&#xff01;&#xff01;&#xff01; 题目&#xff1a;一共会给四个数&#xff0c;分别是N、M、i、j&#xff0c;然后希望我们把N和M抓怒换为2进制以后&#xff0c;将M的二进制放在i到j之间的区域&#xff0c;如果M的二进制长度小于i-j1&#xff0c;则前面补0即可。最…

前端设计中如何在鼠标悬浮时同步修改块内样式

虽然只是一个小问题&#xff0c;但这个解决问题的过程也深化了自己对盒子模型的理解问题缘起正在写一个登录注册的小窗口&#xff0c;想要在鼠标悬浮阶段让按钮和文字都变色&#xff0c;但是发现实操的时候按钮和文字没办法同时变色鼠标悬停前鼠标悬停后问题分析仔细分析了下该…