Java--IO基本流

IO流

概述

        生活中,你肯定经历过这样的场景。当你编辑一个文本文件,忘记了`ctrl+s` ,可能文件就白白编辑了。当你电脑上插入一个U盘,可以把一个视频,拷贝到你的电脑硬盘里。那么数据都是在哪些设备上的呢?键盘、内存、硬盘、外接设备等等。

        我们把这种数据的传输,可以看做是一种数据的流动,按照流动的方向,以内存为基准,分为`输入input` 和`输出output` ,即流向内存是输入流,流出内存的输出流。

        Java中I/O操作主要是指使用java.io包下的内容,进行输入、输出操作。输入也叫做读取数据,输出也叫做作写出数据

IO的分类

根据数据的流向分为:输入流和输出流。

输入流 :把数据从`其他设备`上读取到`内存`中的流。

程序 - > 文件

输出流 :把数据从`内存` 中写出到`其他设备`上的流。

文件 - > 程序

格局数据的类型分为:字节流和字符流。

字节流 :以字节为单位,读写数据的流。

字符流 :以字符为单位,读写数据的流。

注意:

纯文本文件:能用Windows自带的记事本打开能读懂的文件

如md和txt

IO流的体系

字节流基本用法

FileOutputStream类

        当你创建一个流对象时,必须传入一个文件路径。该路径下,如果没有这个文件,会创建该文件。如果有这个文件,会清空这个文件的数据。

构造方法:

        public FileOutputStream(File file):创建文件输出流以写入由指定的 File对象表示的文件。

        public FileOutputStream(String name): 创建文件输出流以指定的名称写入文件。

 代码示例:

public class FileOutputStreamConstructor throws IOException {public static void main(String[] args) {// 使用File对象创建流对象File file = new File("a.txt");FileOutputStream fos = new FileOutputStream(file);// 使用文件名称创建流对象FileOutputStream fos = new FileOutputStream("b.txt");}
}
 写出数据的三种方法

写出字节数据 : write(int b) 方法

代码演示:

public class FOSWrite {public static void main(String[] args) throws IOException {// 使用文件名称创建流对象FileOutputStream fos = new FileOutputStream("fos.txt");     // 写出数据fos.write(97); // 写出第1个字节fos.write(98); // 写出第2个字节fos.write(99); // 写出第3个字节// 关闭资源fos.close();}
}
输出结果:
abc

1.创建字节输出流对象细节:

        细节1:参数是字符串表示的路径或者是file对象都是可以的

        细节2:如果文件不存在会创建一个新的文件,但是要保障父级路径是存在的

        细节3:如果文件已经存在,则会清空文件

2.写数据:

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

3.释放资源

        每次使用完流之后都要释放资源(不然文件一直处于占用状态)

写出字节数组:write(byte[] b)
public class FOSWrite {public static void main(String[] args) throws IOException {// 使用文件名称创建流对象FileOutputStream fos = new FileOutputStream("fos.txt");     // 字符串转换为字节数组byte[] b = "黑马程序员".getBytes();// 写出字节数组数据fos.write(b);// 关闭资源fos.close();}
}
输出结果:
黑马程序员

写出指定长度字节数组:write(byte[] b, int off, int len)
public class FOSWrite {public static void main(String[] args) throws IOException {// 使用文件名称创建流对象FileOutputStream fos = new FileOutputStream("fos.txt");     // 字符串转换为字节数组byte[] b = "abcde".getBytes();// 写出从索引2开始,2个字节。索引2是c,两个字节,也就是cd。fos.write(b,2,2);// 关闭资源fos.close();}
}
输出结果:
cd

数据追加续写

        经过以上的演示,每次程序运行,创建输出流对象,都会清空目标文件中的数据。如何保留目标文件中数据,还能继续添加新数据呢?

        public FileOutputStream(File file, boolean append): 创建文件输出流以写入由指定的 File对象表示的文件。  

        public FileOutputStream(String name, boolean append): 创建文件输出流以指定的名称写入文件。  

        这两个构造方法,参数中都需要传入一个boolean类型的值,`true` 表示追加数据,`false` 表示清空原有数据。这样创建的输出流对象,就可以指定是否追加续写了,

代码演示:

public class FOSWrite {public static void main(String[] args) throws IOException {// 使用文件名称创建流对象FileOutputStream fos = new FileOutputStream("fos.txt",true);     // 字符串转换为字节数组byte[] b = "abcde".getBytes();// 写出从索引2开始,2个字节。索引2是c,两个字节,也就是cd。fos.write(b);// 关闭资源fos.close();}
}
文件操作前:cd
文件操作后:cdabcde
写出换行

换行符:

        Windows:\r\n

        Linux系统:\n

        Mac: \r

细节:

        在windows系统中,Java对回车换行进行了优化

        虽然完整的是\r\n,但是我们写其中一个\r或者\n,

        java也可以实现换行,因为Java在底层会自动补全

建议:

        不要省略,还是写全

代码演示:

public class FOSWrite {public static void main(String[] args) throws IOException {// 使用文件名称创建流对象FileOutputStream fos = new FileOutputStream("fos.txt");  // 定义字节数组byte[] words = {97,98,99,100,101};// 遍历数组for (int i = 0; i < words.length; i++) {// 写出一个字节fos.write(words[i]);// 写出一个换行, 换行符号转成数组写出fos.write("\r\n".getBytes());}// 关闭资源fos.close();}
}输出结果:
a
b
c
d
e

FileInputStream类

        java.io.FileInputStream 类是文件输入流,从文件中读取字节。

构造方法:        

        FileInputStream(File file): 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的 File对象 file命名。

        FileInputStream(String name): 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的路径名 name命名。  

        当你创建一个流对象时,必须传入一个文件路径。该路径下,如果没有该文件,会抛出FileNotFoundException。

代码演示:

public class FileInputStreamConstructor throws IOException{public static void main(String[] args) {// 使用File对象创建流对象File file = new File("a.txt");FileInputStream fos = new FileInputStream(file);// 使用文件名称创建流对象FileInputStream fos = new FileInputStream("b.txt");}
}

读取字节数据:

字节输入流的细节:

1.创建字节输入流对象

        细节1:如果文件不存在,就直接报错

        Java为什么会这么设计呢?

        输出流:不存在,创建

                把数据写到文件当中

        

        输入流:不存在,则是报错呢?

                读取的时候,数据在文件当中

                所以Java就没有这种无意义的逻辑,文件不存在直接报错

         程序中最重要的是:数据

        

2.写数据

        细节1:一次读一个字节,读出来的是数据在ASCII上对应的数字

        细节2:读到文件末尾了,read方法返回-1

3.释放资源

        细节:每次使用完流之后都要释放资源

read方法

        读一次数据,就移动一次指针指向下一个元素

代码演示:

public class FISRead {public static void main(String[] args) throws IOException{// 使用文件名称创建流对象FileInputStream fis = new FileInputStream("read.txt");// 读取数据,返回一个字节int read = fis.read();System.out.println((char) read);read = fis.read();System.out.println((char) read);read = fis.read();System.out.println((char) read);read = fis.read();System.out.println((char) read);read = fis.read();System.out.println((char) read);// 读取到末尾,返回-1read = fis.read();System.out.println( read);// 关闭资源fis.close();}
}
输出结果:
a
b
c
d
e
-1

循环改进读取方式,代码使用演示:

public class FISRead {public static void main(String[] args) throws IOException{// 使用文件名称创建流对象FileInputStream fis = new FileInputStream("read.txt");// 定义变量,保存数据int b ;// 循环读取while ((b = fis.read())!=-1) {System.out.println((char)b);}// 关闭资源fis.close();}
}
输出结果:
a
b
c
d
e

> 小贴士:

>

> 1. 虽然读取了一个字节,但是会自动提升为int类型。

> 2. 流操作完毕后,必须释放系统资源,调用close方法,千万记得。

使用字节数组读取:read(byte[] b)

        每次读取b的长度个字节到数组中,返回读取到的有效字节个数,读取到末尾时,返回`-1`

代码演示:

public class FISRead {public static void main(String[] args) throws IOException{// 使用文件名称创建流对象.FileInputStream fis = new FileInputStream("read.txt"); // 文件中为abcde// 定义变量,作为有效个数int len ;// 定义字节数组,作为装字节数据的容器   byte[] b = new byte[2];// 循环读取while (( len= fis.read(b))!=-1) {// 每次读取后,把数组变成字符串打印System.out.println(new String(b));}// 关闭资源fis.close();}
}输出结果:
ab
cd
ed

        错误数据`d`,是由于最后一次读取时,只读取一个字节`e`,数组中,上次读取的数据没有被完全替换,所以要通过`len` ,获取有效的字节,代码使用演示:

public class FISRead {public static void main(String[] args) throws IOException{// 使用文件名称创建流对象.FileInputStream fis = new FileInputStream("read.txt"); // 文件中为abcde// 定义变量,作为有效个数int len ;// 定义字节数组,作为装字节数据的容器   byte[] b = new byte[2];// 循环读取while (( len= fis.read(b))!=-1) {// 每次读取后,把数组的有效字节部分,变成字符串打印System.out.println(new String(b,0,len));//  len 每次读取的有效字节个数}// 关闭资源fis.close();}
}输出结果:
ab
cd
e

> 小贴士:

>

> 使用数组读取,每次读取多个字节,减少了系统间的IO操作次数,从而提高了读写的效率,建议开发中使用。

练习:小文件拷贝
        FileOutputStream fos = new FileOutputStream("a.txt");FileInputStream fis = new FileInputStream("b.txt");byte[] bytes = new byte[1024];int len;long start = System.currentTimeMillis();while((len = fis.read(bytes)) != -1) {fos.write(bytes, 0, len);}fos.close();fis.close();//统计拷贝时间long end = System.currentTimeMillis();System.out.println("拷贝时间:" + (end - start) + "ms");

> 小贴士:

>

> 流的关闭原则:先开后关,后开先关。

字符集

字符集(GBK)

字符集(Unicode)

为什么会有乱码

原因1:

        读取数据时未读完整个汉字

原因2:

        编码和解码时的方式不一样

如何不产生乱码?

1、不要用字节流读取文本文件

2、编码解码时使用同一个码表,同一个编码方式

扩展:

疑问:字节流读取中文会乱码,但是为什么拷贝不会乱码呢?

因为拷贝时,数据源没有丢失,用记事本(采用对应的解码方式)打开不会出现乱码

Java中的编码和解码

字符流

字符流的底层其实就是字节流

字符流=字节流+字符集

特点:

        输入流:一次读一个字节。遇到中文时,一次读多个字节

        输出流:底层会把数据按照指定的编码方式进行编码,变成字节再写到文件中

使用场景

        对于出纯文本文件进行读写操作

FileReader

无参read()代码演示 

        FileReader fileReader = new FileReader("a.txt");//读取数据read()//字符流的底层也是字节流,默认也是一个字节一个字节的读取的//如果遇到中文就会一次读取多个,GBK一次读两个字节,UTF-8一次读3个字节//read()细节//在读取之后,方法的底层还会进行解码并转成十进制//  最终把这个十进制作为返回值//  这个十进制的数据也表示在字符集上的数字//  英文:文件里面二进制数据  0110 0001//          read()方法进行读取,转成十进制97//  中文:文件里面二进制数据  11100110 10110001 10001001//          read()方法进行读取,转成十进制27721//  我想看到中文汉字,就是把这些十进制数据,再进行强转就行了int ch = 0;while ((ch = fileReader.read()) != -1) {System.out.print((char)ch);}fileReader.close();

有参read()代码演示

        FileReader fileReader = new FileReader("a.txt");int len;char[] chars = new char[1024];while((len=fileReader.read(chars))!=-1){System.out.println(new String(chars,0,len));}fileReader.close();

注意:

        无参的ch表示拿到的字符的十进制

        有参的len表示读取到字符的个数

FileWriter

基本写出数据

`write(int b)` 方法,每次可以写出一个字符数据,代码使用演示:

        FileWriter fw = new FileWriter("fw.txt");     // 写出数据fw.write(97); // 写出第1个字符fw.write('b'); // 写出第2个字符fw.write('C'); // 写出第3个字符fw.write(30000); // 写出第4个字符,中文编码表中30000对应一个汉字。/*【注意】关闭资源时,与FileOutputStream不同。如果不关闭,数据只是保存到缓冲区,并未保存到文件。*/// fw.close();输出结果:
abC田

> 小贴士:

>

> 1. 虽然参数为int类型四个字节,但是只会保留一个字符的信息写出。

> 2. 未调用close方法,数据只是保存到了缓冲区,并未写出到文件中。

关闭和刷新

因为内置缓冲区的原因,如果不关闭输出流,无法写出字符到文件中。但是关闭的流对象,是无法继续写出数据的。如果我们既想写出数据,又想继续使用流,就需要`flush` 方法了。

* `flush` :刷新缓冲区,流对象可以继续使用。

* `close `:先刷新缓冲区,然后通知系统释放资源。流对象不可以再被使用了。

代码演示:

public class FWWrite {public static void main(String[] args) throws IOException {// 使用文件名称创建流对象FileWriter fw = new FileWriter("fw.txt");// 写出数据,通过flushfw.write('刷'); // 写出第1个字符fw.flush();fw.write('新'); // 继续写出第2个字符,写出成功fw.flush();// 写出数据,通过closefw.write('关'); // 写出第1个字符fw.close();fw.write('闭'); // 继续写出第2个字符,【报错】java.io.IOException: Stream closedfw.close();}
}

> 小贴士:即便是flush方法写出了数据,操作的最后还是要调用close方法,释放系统资源。

写出其他数据

1. **写出字符数组** :`write(char[] cbuf)` 和 `write(char[] cbuf, int off, int len)` ,每次可以写出字符数组中的数据,用法类似FileOutputStream,代码使用演示:

public class FWWrite {public static void main(String[] args) throws IOException {// 使用文件名称创建流对象FileWriter fw = new FileWriter("fw.txt");     // 字符串转换为字节数组char[] chars = "黑马程序员".toCharArray();// 写出字符数组fw.write(chars); // 黑马程序员// 写出从索引2开始,2个字节。索引2是'程',两个字节,也就是'程序'。fw.write(b,2,2); // 程序// 关闭资源fos.close();}
}

2. **写出字符串**:`write(String str)` 和 `write(String str, int off, int len)` ,每次可以写出字符串中的数据,更为方便,代码使用演示:

public class FWWrite {public static void main(String[] args) throws IOException {// 使用文件名称创建流对象FileWriter fw = new FileWriter("fw.txt");     // 字符串String msg = "黑马程序员";// 写出字符数组fw.write(msg); //黑马程序员// 写出从索引2开始,2个字节。索引2是'程',两个字节,也就是'程序'。fw.write(msg,2,2);	// 程序// 关闭资源fos.close();}
}

续写和换行
public class FWWrite {public static void main(String[] args) throws IOException {// 使用文件名称创建流对象,可以续写数据FileWriter fw = new FileWriter("fw.txt",true);     // 写出字符串fw.write("黑马");// 写出换行fw.write("\r\n");// 写出字符串fw.write("程序员");// 关闭资源fw.close();}
}
输出结果:
黑马
程序员

> 小贴士:字符流,只能操作文本文件,不能操作图片,视频等非文本文件。

>

> 当我们单纯读或者写文本文件时  使用字符流 其他情况使用字节流

字符流综合练习

练习1:拷贝

        需求:拷贝一个文件夹,考虑子文件夹

public class Test01 {public static void main(String[] args) throws IOException {//拷贝一个文件夹,考虑子文件夹//1.创建对象表示数据源File src = new File("D:\\aaa\\src");//2.创建对象表示目的地File dest = new File("D:\\aaa\\dest");//3.调用方法开始拷贝copydir(src,dest);}/** 作用:拷贝文件夹* 参数一:数据源* 参数二:目的地** */private static void copydir(File src, File dest) throws IOException {dest.mkdirs();//递归//1.进入数据源File[] files = src.listFiles();//2.遍历数组for (File file : files) {if(file.isFile()){//3.判断文件,拷贝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 {//4.判断文件夹,递归copydir(file, new File(dest,file.getName()));}}}
}

练习2:文件加密

        需求:为了保证文件的安全性,就需要对原始文件进行加密存储,再使用的时候再对其进行解密处理。

        加密原理:对原始文件中的每一个字节数据进行更改,然后将更改以后的数据存储到新的文件夹中

        解密原理:读取加密之后的文件,按照加密的规则反向操作,变成原始文件

public class Test02 {public static void main(String[] args) throws IOException {/*为了保证文件的安全性,就需要对原始文件进行加密存储,再使用的时候再对其进行解密处理。加密原理:对原始文件中的每一个字节数据进行更改,然后将更改以后的数据存储到新的文件中。解密原理:读取加密之后的文件,按照加密的规则反向操作,变成原始文件。^ : 异或两边相同:false两边不同:true0:false1:true100:110010010: 10101100100^ 0001010__________1101110^ 0001010__________1100100*/}public static void encryptionAndReduction(File src, File dest) throws IOException {FileInputStream fis = new FileInputStream(src);FileOutputStream fos = new FileOutputStream(dest);int b;while ((b = fis.read()) != -1) {fos.write(b ^ 2);}//4.释放资源fos.close();fis.close();}}

练习3:修改文件中的数据

文本文件中有以下的数据:

        2-1-9-4-7-8

将文件中的数据进行排序,变成以下的数据:

        1-2-4-7-8-9

public class test {public static void main(String[] args) throws IOException {//读取数据FileReader fileReader =new FileReader("a.txt");StringBuilder stringBuilder=new StringBuilder();int ch;while ((ch=fileReader.read())!=-1){stringBuilder.append((char)ch);}fileReader.close();//排序String str=stringBuilder.toString();String[] str1=str.split("-");ArrayList<Integer> list=new ArrayList<>();for (String s : str1) {int i=Integer.parseInt(s);list.add(i);}Collections.sort(list);System.out.println(list);//写出FileWriter fileWriter=new FileWriter("b.txt");for (int i = 0; i < list.size(); i++) {if(i==list.size()-1){fileWriter.write(list.get(i)+"");}else {fileWriter.write(list.get(i)+"-");}}fileWriter.close();}
}

简化写法

        //排序Integer[] integers = Arrays.stream(stringBuilder.toString().split("-")).map(Integer::parseInt).sorted().toArray(Integer[]::new);System.out.println();//写出FileWriter fileWriter = new FileWriter("b.txt");String s = Arrays.toString(integers).replace(", ","-");String result = s.substring(1, s.length() - 1);System.out.println(result);fileWriter.write(result);fileWriter.close();

细节1:

        文件中的数据不要换行

细节2:bom头

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

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

相关文章

汇总binder相关一些常见面试题-安卓系统常见面试题

背景&#xff1a; 国庆前有几个学员朋友在群里讨论了几个binder相关的面试题&#xff0c;讨论较为激烈&#xff0c;这里马哥统一整理一下列出来了&#xff0c;并且也补充了几个&#xff0c;大家有兴趣的可以尝试做一下&#xff0c;后续方便每个学员进行查缺补漏。后续会进行整…

JSP(Java Server Pages)基础使用三(表单传参)

表单传参 1.这次学习的是我们在网络上使用次数相对来说很多的jsp的使用方式&#xff0c;表单传参是运用了form表单的post方法来讲表单中的数据传递给action页面,action的作用是跳转就类似a标签&#xff0c;当然action不只可以是页面&#xff0c;还可以是后端类&#xff0c;用来…

如何解决 Photoshop 中的“暂存盘已满”错误

好久没有用Photoshop了&#xff0c;今天想自己修个图&#xff0c;就启动了一下PS&#xff0c;结果出现一个对话框“不能初始化Photoshop&#xff0c;因为暂存盘已经满”。我一直存在C盘焦虑&#xff0c;常年C盘显示都是红色的。上网一查&#xff0c;发现PS启动时暂存盘的空间是…

最新BurpSuite2024.9专业中英文开箱即用版下载

1、工具介绍 本版本更新介绍 此版本对 Burp Intruder 进行了重大改进&#xff0c;包括自定义 Bambda HTTP 匹配和替换规则以及对扫描 SOAP 端点的支持。我们还进行了其他改进和错误修复。 Burp Intruder 的精简布局我们对 Burp Intruder 进行了重大升级。现在&#xff0c;您可…

原文翻译:Make Skeleton-based Action Recognition Model Smaller, Faster and Better

全网没找到一个完整的翻译&#xff0c;用chatgpt翻译如下&#xff0c;可能有的地方不够准确&#xff0c;推荐结合原文对照着看更。 摘要 尽管基于骨架的动作识别在近年来取得了巨大的成功&#xff0c;但大多数现有方法可能面临模型规模庞大和执行速度缓慢的问题。为了解决这个…

国庆节快乐前端(HTML+CSS+JavaScript+BootStrap.min.css)

一、效果展示 二、制作缘由 最近&#xff0c;到了国庆节&#xff0c;自己呆在学校当守校人&#xff0c;太无聊了&#xff0c;顺便做一个小demo帮祖国目前庆生&#xff01;&#xff01;&#xff01; 三、项目目录结构 四、准备工作 (1)新建好对应的文件目录 为了方便&#xff…

【MyBatis 源码拆解系列】JVM 级别缓存能力设计:MyBatis 的一、二级缓存如何设计?

欢迎关注公众号 【11来了】 &#xff0c;持续 MyBatis 源码系列内容&#xff01; 在我后台回复 「资料」 可领取编程高频电子书&#xff01; 在我后台回复「面试」可领取硬核面试笔记&#xff01; 文章导读地址&#xff1a;点击查看文章导读&#xff01; 感谢你的关注&#xff…

Linux内核对连接的组织和全连接队列

一、Linux内核的组织形式 1.1 描述“连接”的结构 TCP协议的特点是面向连接&#xff0c;一个服务端可能会被多个客户端连接&#xff0c;那这些连接也一定会被操作系统组织起来&#xff0c;接下来我们谈一谈在Linux内核中是如何管理这些连接的。 既然要管理这些连接&#xff0c…

vue3中el-input在form表单按下回车刷新页面

摘要&#xff1a; 在input框中点击回车之后不是调用我写的回车事件&#xff0c;而是刷新页面&#xff01; 如果表单中只有一个input 框则按下回车会直接关闭表单 所以导致刷新页面 再写一个input 表单 &#xff0c;并设置style“display:none” <ElInput style"display…

SkyWalking 高可用

生产环境中,后端应用需要支持高吞吐量并且支持高可用来保证服务的稳定,因此需要高可用集群管理。 集群方案 Skywalking集群是将 skywalking oap 作为一个服务注册到nacos上,只要skywalking oap服务没有全部宕机,保证有一个skywalking oap在运行,就可以提供服务。 高可用…

鸿蒙应用开发前置学习-TypeScript

注意&#xff1a;博主有个鸿蒙专栏&#xff0c;里面从上到下有关于鸿蒙next的教学文档&#xff0c;大家感兴趣可以学习下 如果大家觉得博主文章写的好的话&#xff0c;可以点下关注&#xff0c;博主会一直更新鸿蒙next相关知识 专栏地址: https://blog.csdn.net/qq_56760790/…

数据安全新攻略!4大神技在手,固态硬盘数据恢复秒变Easy Mode

现在咱们都离不开电脑和手机了&#xff0c;里面存了好多重要的东西&#xff0c;比如学习资料、工作文件&#xff0c;还有照片、视频这些宝贵的记忆。但是有时候数据可能会不小心弄丢或者删掉&#xff0c;特别是在固态硬盘上的数据&#xff0c;要是没了&#xff0c;想找回来比老…

Sui主网升级至V1.34.2

Sui主网现已升级至V1.34.2版本&#xff0c;同时协议升级至60版本。其他升级要点如下所示&#xff1a; 协议 #19014: 在验证Groth16 zk-proof时对无效公共输入进行快速判断。添加了一个新的Move函数flatten&#xff0c;可将向量中的向量展平成单个向量&#xff0c;这在新协议…

爬虫——爬取小音乐网站

爬虫有几部分功能&#xff1f;&#xff1f;&#xff1f; 1.发请求&#xff0c;获得网页源码 #1.和2是在一步的 发请求成功了之后就能直接获得网页源码 2.解析我们想要的数据 3.按照需求保存 注意&#xff1a;开始爬虫前&#xff0c;需要给其封装 headers {User-…

计算机网络:计算机网络体系结构 —— OSI 模型 与 TCP/IP 模型

文章目录 计算机网络体系结构OSI 参考模型TCP/IP 参考模型分层的必要性物理层的主要问题数据链路层的主要问题网络层的主要问题运输层的主要问题应用层的主要问题 分层思想的处理方法发送请求路由器转发接受请求发送响应接收响应 计算机网络体系结构 计算机网络体系结构是指将…

12.Velodyne16线激光雷达在ROS下的仿真(使用 URDF 描述和 Gazebo 插件来模拟 Velodyne 激光扫描仪)

1 下载VLP16的模型描述文件 在这个网站上进行下载&#xff1a; Bitbuckethttps://bitbucket.org/DataspeedInc/velodyne_simulator/src/master/ 使用 URDF 描述和 Gazebo 插件来模拟 Velodyne 激光扫描仪&#xff01; 下图是一个官方给的效果。 URDF with colored meshe…

嵌入式外设应用(代码)

文章目录 1. 工业自动化2. 智能家居设备3. 汽车电子4. 生命体征监测仪5. 物联网应用嵌入式外设应用广泛,有很多应用领域: 1. 工业自动化 应用场景:使用传感器监测设备状态,控制电机的启动和停止。 示例代码: #include <stdio.h> #include <stdbool.h>// 模…

Android 日志打印频率过高排查的一些技巧

最近项目快到 sop 阶段了&#xff0c;看到最近的一个新的任务&#xff0c;提示应用打印频率每秒超过 100 行/秒&#xff0c;需要优化一下。 那这样看起来需要删减一点日志&#xff0c;是不是先要找一下我们的应用打印了多少。 当然如果项目是自己维护的&#xff0c;那肯定是知…

java中创建不可变集合

一.应用场景 二.创建不可变集合的书写格式&#xff08;List&#xff0c;Set&#xff0c;Map) List集合 package com.njau.d9_immutable;import java.util.Iterator; import java.util.List;/*** 创建不可变集合:List.of()方法* "张三","李四","王五…

Let‘s Encrypt 的几个常用命令

Lets Encrypt 是免费的 ssl 证书提供商&#xff0c;在当前纷纷收费的形式下&#xff0c;这是一个良心厂家&#xff0c;虽然使用起来略微繁琐。坚决抵制某 cxxn 站&#xff0c;竟然开始有辣么多收费的东西。这里记录几个常用的命令&#xff08;使用环境Ubuntu 24&#xff09;&am…