当前位置: 首页 > news >正文

Java中的File和IO流

File对象

File对象本质是一个文件或文件夹,用于写入和读取文件内容
注意:对于相对路径而言,在单元测试方法中的File是相对于Module,在main中的File是相对于Project

构造器

  1. File(String pathname)
    File file1 = new File("D:\\workspace"); // 对应一个文件夹
    File file2 = new File("D:\\workspace\test.txt"); // 对应一个文件
    
  2. File(String parent, String child)
    File file = new File("D:\\workspace", "test.txt"); // 第一个参数是文件夹,第二个参数可以是文件/文件夹
    
  3. File(File parent, String child)
    File file1 = new File("D:\\workspace");
    File file2 = new File(file1, "test.txt"); // 第一个参数传入一个File对象,且这个对象必须是个文件夹
    

常用方法

获取文件信息

  1. getName():获取文件名称
  2. gePath():获取相对路径
  3. getAbsolutePath():获取文件绝对路径
  4. File getAbsoluteFile():获取绝对路径表示的文件
  5. getParent():获取上层目录路径
  6. length():获取文件所占的字节
  7. lastModified():获取文件最后修改的时间(毫秒数)
  8. exists():判断文件或目录是否存在
  9. isDirectory():是否是一个目录
  10. isFile():是否是一个文件
  11. canRead():是否可读
  12. canWrite():是否可写
  13. isHidden():是否隐藏

遍历文件内部

  1. String[] list():返回目录中最外层的所有子目录及子文件
  2. File[] listFiles():返回目录中最外层的所有子目录及子文件

操作文件

  1. renameTo(File) :重命名(文件移动)
    前提:源文件必须存在,目标文件必须不存在,且目标文件所在文件夹必须存在
    File file1 = new File("hello.txt"); // 假设hello.txt存在
    File file2 = new File("workspace", "world.txt"); // 假设workspace存在,world.txt不存在
    Boolean isSuccess = file1.renameTo(file2); // 是否移动成功
    System.out.println(isSuccess); // 是否成功
    
  2. createNewFile():创建文件,若文件存在,则返回false
    File file = new File("workspace/hello.txt");
    try {System.out.println(file.createNewFile()); // 不存在返回true,文件已存在返回false
    } catch(IOException e) {e.printStackTrace();
    }
    
  3. delete():删除文件或目录,若文件/目录不存在,返回false
    说明:
    ① 对于目录而言,只能删除空目录
    ② 删除不走回收站
  4. mkdir():创建一个目录,如果当前目录的上层目录不存在,则创建失败
    // 前提:只有workspace目录存在
    File file = new File("workspace/test.txt");
    file.mkdir(); // 创建成功
    File file = new File("workspace/a/test.txt"); // a目录和test.txt不存在
    file.mkdir(); // 创建失败
    
  5. mkdirs():创建多级目录,如果当前目录的上层目录也不存在,一并创建
    // 前提:只有workspace目录存在
    File file = new File("workspace/a/test.txt"); // a目录和test.txt不存在
    file.mkdirs(); // 创建成功(a目录和test.txt都被创建)
    

IO流

  1. 按流向划分:输入流、输出流
  2. 按操作数据单位划分:字节流、字符流
  3. 按IO流的角色划分:节点流、处理流
    在这里插入图片描述

IO流的基础类

抽象基类文件流(节点流)缓冲流(处理流)转换流(处理流)数据流(处理流)对象流(处理流)
InputStream(字节流输入流)FileInputStreamBufferedInputStreamInputStreamReaderDataInputStreamObjectInputStream
ouputStream(字节输出流)FileOutputStreamBufferedOutputStreamOutputStreamWriterDataOutputStreamObjectOutputStream
Reader(字符输入流)FileReaderBufferedReader
Writer(字符输出流)FileWriterBufferedWriter
PrintStream(打印流)

说明
① 字符流一般用于读取txt文件,字节流一般用于读取mp3、mp4、jpg等文件
字节流可以用于txt文件的复制,但是用于读取txt文件可能会出现乱码(如果遇到汉字,一个汉字占3个字节,可能读不完整)
缓冲流可以提高文件的读写效率(相当于在文件和内存中间架了一层8kb的缓存区,先从文件中读取到缓存中,最后再一并读入到内存中)
④ 输出流中的flush()方法,可以手动将数据立即写入到磁盘中
转换流可以将字节流转换为字符流,或者将字符流转换为字节流
数据流只可以读写基本数据类型、String类型数据
对象流既可以读写基本数据类型、String类型数据,又可以读写引用类型数据

案例1:将磁盘中的文本文件读入内存中,并打印文件内容(使用字符输入流 FileReader)

File file = new File("hello.txt");
FileReader fr = null;
try {fr = new FileReader(file);char[] cBuffer = new char[5]; // 用于存储批量读出来的字符int len; // 用于存储本次读取出的长度// 开始读入while((len = fr.read(cBuffer)) != -1) {// 遍历本次所有读出的字符for(int i = 0; i < len; i++) {System.out.println(cBuffer[i]);}}
} catch(IOException e) {e.printStackTrace();
} finally {// 关闭字符输入流try {if (fr != null) {fr.close(); }} catch(IOException e) {e.printStackTrace();}
}

案例2:将内存中的文本数据写入到磁盘文件中(使用字符输出流FileWriter)

FileWriter fw = null;
try {File file = new File("world.txt"); // 与目标文件做映射fw = new FileWriter(file); // 覆盖原有文件内容// fw = new FileWriter(file, true); // 在原有文件基础上,追加内容// 开始写入fw.write("这是写入的第一行内容...\n");fw.write("这是写入的第二行内容...\n");fw.write("这是写入的第三行内容...\n");System.out.println("写入成功");
} catch(IOException e) {e.printStackTrace();
} finally {// 关闭字符输出流 try {if (fw != null) {fw.close();}} catch(IOException e) {e.printStackTrace();}
}

案例3:复制某个文本文件中的内容到新文件中(使用节点流)

FileReader fr = null;
FileWriter fw = null;
try {File srcFile = new File("test.txt"); // 映射源文件File destFile = new File("test_copy.txt"); // 映射目标文件fr = new FileReader(srcFile);fw = new FileWriter(destFile);char[] cBuffer = new char[5]; // 存储每次读取出来的字符int len; // 记录每次读取出的字符长度// 开始读取while((len = fr.read(cBuffer)) != -1) {// 开始写入fw.write(cBuffer, 0, len); // 写入cBuffer中从下标0开始的len长度数据}System.out.println("复制成功");
} 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();}
}

案例4:复制jpg文件(使用字节流)

FileInputStream fis = null;
FileOutputStream fos = null;
try {File srcFile = new File("workspace", "screen.jpg");File destFile = new File("workspace", "screen_copy.jpg");fis = new FileInputStream(srcFile);fos = new FileOutputStream(destFile);byte[] bBuffer = new byte[1024]; // 存储每次读取出来的字节int len; // 记录每次读取出来字节的长度// 开始读取while((len = fis.read(bBuffer)) != -1) {// 开始写入fos.write(bBuffer, 0, len);}System.out.println("复制成功");
} catch(IOException e) {e.printStackTrace();
} finally {// 关闭流try {if (fis != null) fis.close();} catch(IOException e) {e.printStackTrace();}try {if (fos != null) fos.close();} catch(IOException e) {e.printStackTrace();}
}

案例5:复制jpg文件(使用字节缓冲流)

说明:关闭处理流会自动关闭内层流

BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {File srcFile = new File("workspace", "screen.jpg");File destFile = new File("workspace", "screen_copy.jpg");FileInputStream fis = new FileInputStream(srcFile);FileOutputStream fos = new FileOutputStream(destFile);bis = new BufferedInputStream(fis); // 将输入流用处理流包裹bos = new BufferedOutputStream(fos); // 将输出流用处理流包裹byte[] bBuffer = new byte[1024];int len;// 使用输入的处理流读取while((len = bis.read(bBuffer)) != -1) {// 使用输出的处理流写入bos.write(bBuffer, 0, len);}System.out.println("复制成功");
} catch(IOException e) {e.printStackTrace();
} finally {// 关闭处理流try {if (bis != null) bis.close();} catch(IOException e) {e.printStackTrace();}try {if (bos != null) bos.close();} catch(IOException e) {e.printStackTrace();}
}

案例6:复制文本文件(使用字符缓冲流)

说明:BufferReader增加了readLine()方法,可以一次性读取一行数据,但是换行不能读出来

BufferedReader br = null;
BufferedWriter bw = null;
try {br = new BufferedReader(new FileReader(new File("workspace", "hello.txt"))); // 包裹字符输入流bw = new BufferedWriter(new FileWriter(new File("workspace", "hello_copy.txt"))); // 包裹字符输出流String data = null; // 存储本次读取出的一行数据while((data = br.readLine()) != null) {bw.write(data);bw.newLine(); // 换行}System.out.println("复制成功");
} catch(IOException e) {e.printStackTrace();
} finally {try {if (br != null) br.close();} catch(IOException e) {e.printStackTrace();}try {if (bw != null) bw.close();} catch(IOException e) {e.printStackTrace();}
}

案例7:将GBK类型的文件转为UTF-8类型的文件(使用转换流)

InputStreamReader isr = null;
OutputStreamWriter osw = null;
try {File srcFile = new File("workspace", "hello_GBK.txt");File destFile = new File("workspace", "hello_UTF8.txt");isr = new InputStreamReader(new FileInputStream(srcFile), "GBK");osw = new OutputStreamWriter(new FileOutputStream(destFile), "UTF-8");char[] cBuffer = new char[5];int len;while((len = isr.read(cBuffer)) != -1) {String s = new String(cBuffer, 0, len);osw.write(s);}System.out.println("转换成功");
} catch(IOException e) {e.printStackTrace();
} finally {try {if (isr != null) isr.close();} catch(IOException e) {e.printStackTrace();}try {if (osw!= null) osw.close();} catch(IOException e) {e.printStackTrace();}
}

案例8:将Java对象存储在本地文件中,并从本地文件中把Java对象读取到内存中(使用对象流)

对象的序列化机制:允许把内存中的Java对象转换成二进制流,从而允许把这种二进制流永久的保存在磁盘上,或者通过网络将这种二进制流传输到另一个网络节点,当其他程序获取到了这种二进制流,就可以恢复成原来的Java对象
序列化:将Java对象转成二进制流的过程(ObjectOutputStream)
反序列化:将二进制流恢复成Java对象的过程(ObjectInputStream)

  1. 声明Person类和Account类
    注意:
    ① 自定义的类必须实现Serializable接口才能被序列化,并且需要声明static final long serialVersionUID(serialVersionUID是用于标识类的,如果不声明serialVersionUID,则当类改变时,serialVersionUID会自动改变)
    ② 自定义类中的各个属性也必须是可序列化的,比如本例中的Account
    ③ 类中的属性如果加上transient(瞬时的)或者static(属于类,跟对象无关)修饰,则这些属性不会被序列化,会以默认值保存到文件中
    public class Person implements Serializable{private static final long serialVersionUID = 1L;private String name;private int age;private Account account;public Person() {}public Person(String name, int age, Account account) {this.name = name;this.age = age;this.account = account;}// ... setter、getter、toString等方法省略
    }
    class Account implements Serializable{private static final long serialVersionUID = 2L;private double balance;public Account() {}public Account(double balance) {this.balance = balance;}// ... setter、getter、toString等方法省略
    }
    
  2. 将Java对象存储在本地文件中(序列化过程)
    ObjectOutputStream oos = null;
    try {// 创建文件对象和对象流File file = new File("object.dat");oos = new ObjectOutputStream(new FileOutputStream(file));// 开始序列化写入oos.writeObject(new Person("a", 18, new Account(1000)));oos.writeUTF("这是一段字符串");System.out.println("写入完成");
    } catch(IOException e) {e.printStackTrace();
    } finally {// 关闭对象流try {if (oos != null) {oos.close();}} catch(IOException e) {e.printStackTrace();}
    }
  3. 从本地文件中把Java对象读取到内存中(反序列化过程)
    ObjectInputStream ois = null;
    try {// 创建文件对象和对象流File file = new File("object.dat");ois = new ObjectInputStream(new FileInputStream(file));// 开始反序列化读入Person p = (Person)ois.readObject();System.out.println(p);String s = (String)ois.readUTF();System.out.println(s);System.out.println("读取完成");
    } catch(IOException | ClassNotFoundException e) {	e.printStackTrace();
    } finally {// 关闭对象流try {if (ois != null) {ois.close();}} catch(IOException e) {e.printStackTrace();}
    }
    

标准输入流:System.in

案例:从键盘输入,并转成大写输出

BufferedReader br = null;
System.out.print("请输入(输入exit退出程序):");
try {// 这里使用BufferedReader,可以调用readLine()来读取输入的一整行数据。// 因为System.in是字节数据,所以需要使用转换流把字节流转换为字符流br = new BufferedReader(new InputStreamReader(System.in));String line;while((line = br.readLine()) != null) {if (line.equalsIgnoreCase("exit")) {break;}System.out.println(line.toUpperCase());System.out.print("请输入(输入exit退出程序):");}
} catch(IOException e) {e.printStackTrace();
} finally {try {if (br != null) {br.close();}} catch(IOException e) {e.printStackTrace();}
}

标准输出流:System.out

说明:System.out默认将内容打印到控制台中

案例:修改System.out默认行为,使用System.out输出到某个txt文件中

PrintStream ps = null;
try {ps = new PrintStream(new FileOutputStream(new File(""test.txt")));ps.println("这是写入的第一行数据");ps.println("这是写入的第二行数据");// 修改System.out的默认输出方式:输出到test.txt中System.setOut(ps);System.out.println("这是写入的第三行数据");
} catch(FileNotFoundException e) {e.printStackTrace();
} finally {if (ps != null){ps.close();}
}

相关文章:

Java中的File和IO流

File对象 File对象本质是一个文件或文件夹&#xff0c;用于写入和读取文件内容 注意&#xff1a;对于相对路径而言&#xff0c;在单元测试方法中的File是相对于Module&#xff0c;在main中的File是相对于Project 构造器 File(String pathname)File file1 new File("D:…...

ls命令实操笔记

ls命令&#xff1a;全称list&#xff0c;显示文件的文件名与相关属性。&#xff08;目前工作目录所含之文件及子目录&#xff09; 4567 45678 7891 a1b2 a2b3c abcd Abcd acde aD7E bcde 通过ls浏览上述文件所在的目录&#xff0c;实现以下需求&#xff1a; 浏览含…...

线段数--算法

线段树是常用来维护 区间信息 的数据结构 线段树可以在 O(logN) 的时间复杂度内实现 单点修改区间修改区间查询 区间求和求区间最大值求区间最小值 简单介绍一下线段树 线段树是一个将区间内的数不断细分的一种数据结构&#xff0c;也就是一个完全二叉树&#xff0c;用每一…...

JS的DOM操作和事件监听综合练习 (具备三种功能的轮播图案例)

下面是是对dom操作的一个综合练习 下面代码是html的基本骨架&#xff08;没有任何的功能&#xff09;&#xff1a; <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <meta name"viewport" c…...

低温存储开关机问题

问题&#xff1a; 某消费电子产品在进行可靠性实验室&#xff0c;在低温-30C存储两个小时后&#xff0c;上电不开机。在常温25C时&#xff0c;开关机正常。 分析&#xff1a; 1、接串口抓log信息&#xff0c;从打印信息可以看出uboot可以起来&#xff0c;在跑kernel时&#x…...

mysql系列1—mysql架构和协议介绍

背景&#xff1a; 本文开始整理mysql相关的文章&#xff0c;用于收集数据库相关内容&#xff1b;包括mysql架构和存储方式、索引结构和查询优化、数据库锁等内容。思考如何根据具体的业务给出最优的分表规划和表设计、字段选择和索引设计、优化的SQL语句&#xff0c;以及数据库…...

设计模式——模板模式

定义与基本概念 模板模式&#xff08;Template Pattern&#xff09;是一种行为设计模式。它在一个抽象类中定义了一个操作的算法骨架&#xff0c;将一些步骤的实现延迟到具体子类中。这个抽象类就像是一个模板&#xff0c;定义了执行某个流程的基本框架&#xff0c;而具体的细…...

CV22_语义分割基础

1. 常见的分割类型 在计算机视觉领域&#xff0c;根据不同的应用场景和需求&#xff0c;分割任务可以分为几种主要类型。以下是几种常见的分割类型&#xff1a; 语义分割&#xff08;Semantic Segmentation&#xff09;&#xff1a; 语义分割的目标是将图像中的每个像素分配到…...

Dubbo源码解析-Dubbo的线程模型(九)

一、Dubbo线程模型 首先明确一个基本概念&#xff1a;IO 线程和业务线程的区别 IO 线程&#xff1a;配置在netty 连接点的用于处理网络数据的线程&#xff0c;主要处理编解码等直接与网络数据 打交道的事件。 业务线程&#xff1a;用于处理具体业务逻辑的线程&#xff0c;可以…...

【Canvas与标志】圆角三角形生化危险警示标志

【成图】 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head><title>圆角三角形生化危险警示标志 Draft1</title><style type&qu…...

解决Dcat Admin laravel框架登录报错问题,(blocked:mixed-content)

前言 在使用 Dcat Admin 后台登录时&#xff0c;发生 error 报错&#xff1a;(blocked:mixed-content) xhr VM484:1&#xff0c;浏览器拦截 其实这是浏览器在 HTTPS 页面中尝试加载 HTTP 资源&#xff0c;导致浏览器阻止了这些不安全的请求。 解决 在 .env 文件中添加或修改 AD…...

(三)Sping Boot学习——升级jdk1.8-jdk18

1.修改系统环境变量。 2.idea中修改配置。 3.项目setting中设置修改 4.更新后还要重新下载依赖mvn clean install &#xff0c;并且记住reload 项目。同时查看java -version查看一下jdk版本。...

语言模型中的多模态链式推理

神经网络的公式推导 简介摘要引言多模态思维链推理的挑战多模态CoT框架多模态CoT模型架构细节编码模块融合模块解码模块 实验结果运行代码补充细节安装包下载Flan-T5数据集准备rougenltkall-MiniLM-L6-v2运行 简介 本文主要对2023一篇论文《Multimodal Chain-of-Thought Reason…...

SCons:下一代构建工具,如何用 Python 驱动高效构建?

在现代软件开发中&#xff0c;构建工具是开发流程中不可或缺的一环。无论是小型项目还是跨平台的复杂工程&#xff0c;选择一个高效、灵活的工具都能显著提高开发效率和代码质量。SCons&#xff0c;一个以 Python 为基础的构建工具&#xff0c;通过自动化依赖管理、灵活的扩展性…...

springboot 整合 rabbitMQ (延迟队列)

前言&#xff1a; 延迟队列是一个内部有序的数据结构&#xff0c;其主要功能体现在其延时特性上。这种队列存储的元素都设定了特定的处理时间&#xff0c;意味着它们需要在规定的时间点或者延迟之后才能被取出并进行相应的处理。简而言之&#xff0c;延时队列被设计用于存放那…...

ES 基本使用与二次封装

概述 基本了解 Elasticsearch 是一个开源的分布式搜索和分析引擎&#xff0c;基于 Apache Lucene 构建。它提供了对海量数据的快速全文搜索、结构化搜索和分析功能&#xff0c;是目前流行的大数据处理工具之一。主要特点即高效搜索、分布式存储、拓展性强 核心功能 全文搜索:…...

分割一切2.0,SAM2详解

&#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f916;编程探索专栏&#xff1a;点击&#xff01; ⏰️创作时间&#xff1a;2024年11月24日20点03分 神秘男子影, 秘而不宣藏。 泣意深不见, 男子自持重, 子夜独自沉。 论文链接 点击开启你的论文编程之旅…...

Spring AI Fluent API:与AI模型通信的流畅体验

引言 随着人工智能&#xff08;AI&#xff09;技术的飞速发展&#xff0c;越来越多的应用场景开始融入AI技术以提升用户体验和系统效率。在Java开发中&#xff0c;与AI模型通信成为了一个重要而常见的需求。为了满足这一需求&#xff0c;Spring AI引入了ChatClient&#xff0c…...

基于python的长津湖评论数据分析与可视化,使用是svm情感分析建模

引言 研究背景及意义 上世纪初开始&#xff0c;中国电影就以自己独有的姿态登上了世界电影史的舞台。中国电影作为国家文化和思想观念的反映与延伸&#xff0c;能够增强文化自信&#xff0c;在文化输出方面有着极其重要的作用1[1]。 改革开放以来&#xff0c;随着生产力的提高…...

Lucene(2):Springboot整合全文检索引擎TermInSetQuery应用实例附源码

前言 本章代码已分享至Gitee: https://gitee.com/lengcz/springbootlucene01 接上文。Lucene(1):Springboot整合全文检索引擎Lucene常规入门附源码 如何在指定范围内查询。从lucene 7 开始&#xff0c;filter 被弃用&#xff0c;导致无法进行调节过滤。 TermInSetQuery 指定…...

浅谈 React Hooks

React Hooks 是 React 16.8 引入的一组 API&#xff0c;用于在函数组件中使用 state 和其他 React 特性&#xff08;例如生命周期方法、context 等&#xff09;。Hooks 通过简洁的函数接口&#xff0c;解决了状态与 UI 的高度解耦&#xff0c;通过函数式编程范式实现更灵活 Rea…...

【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】

1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件&#xff08;System Property Definition File&#xff09;&#xff0c;用于声明和管理 Bluetooth 模块相…...

VTK如何让部分单位不可见

最近遇到一个需求&#xff0c;需要让一个vtkDataSet中的部分单元不可见&#xff0c;查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行&#xff0c;是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示&#xff0c;主要是最后一个参数&#xff0c;透明度…...

浅谈不同二分算法的查找情况

二分算法原理比较简单&#xff0c;但是实际的算法模板却有很多&#xff0c;这一切都源于二分查找问题中的复杂情况和二分算法的边界处理&#xff0c;以下是博主对一些二分算法查找的情况分析。 需要说明的是&#xff0c;以下二分算法都是基于有序序列为升序有序的情况&#xf…...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词

Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵&#xff0c;其中每行&#xff0c;每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid&#xff0c;其中有多少个 3 3 的 “幻方” 子矩阵&am…...

Mac下Android Studio扫描根目录卡死问题记录

环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中&#xff0c;提示一个依赖外部头文件的cpp源文件需要同步&#xff0c;点…...

GC1808高性能24位立体声音频ADC芯片解析

1. 芯片概述 GC1808是一款24位立体声音频模数转换器&#xff08;ADC&#xff09;&#xff0c;支持8kHz~96kHz采样率&#xff0c;集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器&#xff0c;适用于高保真音频采集场景。 2. 核心特性 高精度&#xff1a;24位分辨率&#xff0c…...

Docker 本地安装 mysql 数据库

Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker &#xff1b;并安装。 基础操作不再赘述。 打开 macOS 终端&#xff0c;开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...

JVM 内存结构 详解

内存结构 运行时数据区&#xff1a; Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器&#xff1a; ​ 线程私有&#xff0c;程序控制流的指示器&#xff0c;分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 ​ 每个线程都有一个程序计数…...

音视频——I2S 协议详解

I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议&#xff0c;专门用于在数字音频设备之间传输数字音频数据。它由飞利浦&#xff08;Philips&#xff09;公司开发&#xff0c;以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...