注:一般处理流比节点流的效率快,但是并不是处理流越多越好。
节点流类型
| 类型 | 字符流 | 字节流 |
| — | — | — |
| File(文件) | | |
| Memory,Array | CharArrayReader、CharArrayWriter | ByteArrayInputStream、ByteArrayOutputStream |
| Memory,String | StringReader、StringWriter | -------- |
| Pipe(管道) | PipedReader、PipedWriter | PipedInputStream、PipedOutputStream |
节点流就是一根管道直接插到数据源上面,直接读数据源里面的数据,或者是直接往数据源里面写入数据。典型的节点流是文件流:文件的字节输入流(FileInputStream),文件的字节输出流(FileOutputStream),文件的字符输入流(FileReader),文件的字符输出流(FileWriter)。
处理流类型
| 处理类型 | 字符流 | 字节流 |
| — | — | — |
| Buffffering | BufffferedReader、BufffferedWriter | BufffferedInputStream、BufffferedOutputStream |
| Filtering | FilterReader、FilterWriter | FilterInputStream,FilterOutputStream |
| Converting between,bytes and chaacter | InputStreamReader、OutputStreamWriter | ---------- |
| Object Serialization | -------- | ObjectInputStream、ObjectOutputStream |
| Data conversion | ---------- | DataInputStream、DataOutputStream |
| Counting | LineNumberReader | LineNumberInputStream |
| Peeking ahead | PusbackReader | PushbackInputStream |
| Printing | PrintWriter | PrintStream |
处理流是包在别的流上面的流,相当于是包到别的管道上面的管道。
🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲分割线🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲
InputStream的基本使用
通过对源码的分析我们能知道inputStream
的一些功能函数的作用和使用方法。
1.
int read() throws IOException
读取一个字节并以整数的形式返回(0~255),如果返回-1就说明已经到了输入流的末尾。
2.
int read(byte[] buffer) throws IOException
读取一系列字节并存储到一个数组buffer ,返回实际读取的字节数,如果读取前已到输入流的末尾,则返回-1。
3.
int read(byte[] buffer,int offset,int length) throws IOException
读取length个字节
并存储到一个字节数组buffer,从length位置开始
返回实际读取的字节数,如果读取前以到输入流的末尾返回-1.
4.
void close() throws IOException
关闭流释放内存资源 .
5.
long skip(long n) throws IOException
跳过n个字节不读,返回实际跳过的字节数
方法1和方法2的区别
方法1中的read()就是表示一个个字节的读取,而方法2中的read(buffer)则是先把一定长度的字节放在buffer的数组里面然后在读取。这就好比用不同大小的桶来进行取水。
案例
【演示:使用 FileInputStream
流来读取 FileInputStream.java
文件的内容】
import java.io.IOException;
public class zj_bit {
public static void main(String[] args) throws IOException {
FileInputStream fileInputStream = null;
try {
String pathName =“E:\IO-stream\src\ceshi.TXT”;
File file = new File(pathName);
fileInputStream = new FileInputStream(file);
byte[] buffer = new byte[100];
int len ;
while ( (len = fileInputStream.read(buffer)) != -1 ){
String print = new String(buffer,0,len);
System.out.println(print);
}
} finally {
fileInputStream.close();
}
}
}
结果:
hello铁甲小宝
//输出出来的文本内容。
🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲分割线🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲
OutputStream的基本使用
通过对OutputStream源码的查看我们也能知道其中的一下功能函数。
1.
void write(int b) throws IOException
向输出流中写入一个字节数据,该字节数据为参数b的低8位 。
2.
void write(byte[] b) throws IOException
将一个字节类型的数组中的数据写入输出流 。
3.
void write(byte[] b,int off,int len) throws IOException
将一个字节类型的数组中的从指定位置(off)开始的len个字节写入到输出流 。
4.
void close() throws IOException
关闭流释放内存资源
5.
void flush() throws IOException
将输出流中缓冲的数据全部写出到目的地。
案例
【使用FileOutputStream流复制一个文件】
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class outputStream_copy {
public static void main(String[] args) throws IOException {
FileInputStream fi = null;
FileOutputStream fo = null;
try {
String pathName1 = “E:\IO-stream\src\ceshi.TXT”;
String pathName2 = “E:\IO-stream\src\ceshi2.TXT”;
File file = new File(pathName1);//处理流
File file1 = new File(pathName2);
fi = new FileInputStream(file);
fo = new FileOutputStream(file1);
byte[] buffer = new byte[100];
int len;
while((len = fi.read(buffer)) != -1){
fo.write(buffer,0,len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
fi.close();
fo.close();
}
}
}
结果:
FileInputStream和FileOutputStream这两个流都是字节流,都是以一个字节为单位进行输入和输出的。所以对于占用2个字节存储空间的字符来说读取出来时就会显示成乱码。
🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲分割线🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲
Reader的基本使用方法和InputStream是相同的,同理Writer的基本使用方法和OutputStream是一样的。
FileReader和FileWriter这两个流都是字符流,都是以一个字符为单位进行输入和输出的。所以读取和写
入占用2个字节的字符时都可以正常地显示出来,以上是以File(文件)这个类型为例对节点流进行了讲
解,所谓的节点流指定就是直接把输入流或输出插入到数据源上,直接往数据源里面写入数据或读取数
据。
🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲分割线🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲
缓冲流(Buffffering)
缓冲流的作用?
使用缓冲数组以后,整体的读取,写入效率提升很大。降低了CPU通过内存访问硬盘的次数。提高效率,降低磁盘损耗。
缓冲流的常用方法
BufferedReader(Reader in)
BufferedReader(Reader in,int sz) //sz 为自定义缓冲区的大小
BufferedWriter(Writer out)
BufferedWriter(Writer out,int sz)
BufferedInputStream(InputStream in)
BufferedInputStream(InputStream in,int size)
BufferedOutputStream(InputStream in)
BufferedOutputStream(InputStream in,int size)
我们能把缓冲流比作一个桶在取水的时候是在桶满的时候才会将桶提出来,而缓冲流则也是如此。使用缓冲流我们能减少对硬盘的访问,进而保护硬盘。
注意:
这里需要注意的是,所有的缓冲流都没有任何的读取,写入文件能力,这里都需要对应的输入流和输出流
来提供对应的能力。
在创建缓冲流流对象时,需要传入对应的输入流对象和输出流对象。底层就是提供了一个默认大小的缓冲
数组,用于提高效率。
案例
【使用BufferedReader
和BufferedWriter
对文件的复制】
import java.io.*;
public class BufferTest {
public static void main(String[] args) throws IOException {
buffercopy(“E:\IO-stream\src\ceshi.TXT”,“E:\IO-stream\src\ceshi1.TXT”);
}
public static void buffercopy(String pathName1,String pathName2) throws IOException {
BufferedReader br = null;
BufferedWriter bw = null;
try {
br = new BufferedReader(new FileReader(new File(pathName1)));
bw = new BufferedWriter(new FileWriter(new File(pathName2) ));
char[] buffer = new char[1024];
int len;
while ((len = br.read(buffer)) != -1){
bw.write(String.valueOf(buffer),0,len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
br.close();
bw.close();
}
}
}
结果在上一个案例我们能看到。
🌳🌳🌳🌳🌳🌳🌳🌳🌳🌳🌳🌳🌳🌳分界线🌳🌳🌳🌳🌳🌳🌳🌳🌳🌳🌳🌳🌳🌳
转换流
转换流的作用?
提供字节流与字符流之间的转换
转换流的使用
InputStreamReader:将一个字节流的输入流转换为字符流的输入流。
InputStreamReader 需要和 InputStream “套接” 。
OutputStreamWriter:将一个字符流的输出流转换为字节流的输出流。
OutputStreamWriter 需要和 OutputStream “套接” 。
转换流非常的有用,它可以把一个字节流转换成一个字符流,转换流有两种,一种叫
InputStreamReader,另一种叫OutputStreamWriter。InputStream是字节流,Reader是字符流,
InputStreamReader就是把InputStream转换成Reader。OutputStream是字节流,Writer是字符流,
OutputStreamWriter就是把OutputStream转换成Writer。把OutputStream转换成Writer之后就可以
一个字符一个字符地通过管道写入数据了,而且还可以写入字符串。我们如果用一个FileOutputStream
流往文件里面写东西,得要一个字节一个字节地写进去,但是如果我们在FileOutputStream流上面套上
一个字符转换流,那我们就可以一个字符串一个字符串地写进去。
案例
import java.io.*;
public class TestTransform2{
public static void main(String args[]){
try{
InputStreamReader isr = new InputStreamReader(System.in);
//System.in这里的in是一个标准的输入流,用来接收从键盘输入的数据
BufferedReader br = new BufferedReader(isr);
String s = null;
s = br.readLine();//使用readLine()方法把读取到的一行字符串保存到字符串 变量s中去
while(s != null){
System.out.println(s.toUpperCase());//把保存在内存s中的字符串打 印出来
s = br.readLine();//在循环体内继续接收从键盘的输入
if(s.equalsIgnoreCase(“exit”)){
//只要输入exit循环就结束,就会退出
break;
}
}
}catch(Exception e){
e.printStackTrace();
}
}
}
in本身就是一个InputStream,就是一个标准的输入流
,所以这里首先是用in这个流作为节点流直接与数据源链接,数据源里面的数据等待着用户在DOS窗口下从键盘输入。
用户从键盘输入数据后,首先通过in流传递到包在它的ist
流,这个流是一个转换流,可以把字节流转换为字符流,这样数据再通过isr
流以后变成了字符流传递到包在它外部的br
流,使用br
流是为了把数据存储到内存里面时可以使用br
里面的readLine()
方法,readLine()
方法是每次读取一行的数据,这样可以比较快地把冲DOS窗口输入的数据写入到内存里面的s标记的那块区域里面去,在DOS窗口输入的数据最
必看视频!获取2024年最新Java开发全套学习资料 备注Java
终是存储在内存里面的s那块区域中。需要看到s里面装的内容时就可以把s里面装的内容打印出来就可以看得到了。
🌳🌳🌳🌳🌳🌳🌳🌳🌳🌳🌳🌳🌳🌳分界线🌳🌳🌳🌳🌳🌳🌳🌳🌳🌳🌳🌳🌳🌳
数据流
什么是数据流?
一组有序,有起点和终点的字节的数据序列。包括输入流和输出流。
DataInputStream 和 DataOutputStream
DataInputStream 和 DataOutputStream 分别继承自InputStream 和 OutputStream , 它属于处理流,需要分别“套接”在InputStream 和 OutputStream类型的节点流上。
DataInputStream 和 DataOutputStream 提供了可以存取与机器无关的Java原始类型数据(int,double等)的方法。
DataInputStream 和 DataOutputStream 的构造方法:
DataInputStream (InputStream in)
DataOutputStream (OutputStream out)
案例
import java.io.*;
public class TestDataStream {
public static void main(String[] args) {
ByteArrayOutputStream baos = new ByteArrayOutputStream(); //节点流,一根管道连着内存,往内存里写数据
DataOutputStream dos = new DataOutputStream(baos);//处理流封装一层
try {
dos.writeDouble(Math.random());//随机数
dos.writeBoolean(true);//写入布尔类型数据
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());//转换成字节数组
System.out.println(bais.available());
DataInputStream dis = new DataInputStream(bais);//封装一层DataInputStream管道
System.out.println(dis.readDouble());//先写的先读,读出double
System.out.println(dis.readBoolean());//读出布尔类型
dos.close(); dis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
🌳🌳🌳🌳🌳🌳🌳🌳🌳🌳🌳🌳🌳🌳分界线🌳🌳🌳🌳🌳🌳🌳🌳🌳🌳🌳🌳🌳🌳
打印流
什么是打印流?
java.io.PrintStream extends OutputStream,作用是为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式
总目录展示
该笔记共八个节点(由浅入深),分为三大模块。
高性能。 秒杀涉及大量的并发读和并发写,因此支持高并发访问这点非常关键。该笔记将从设计数据的动静分离方案、热点的发现与隔离、请求的削峰与分层过滤、服务端的极致优化这4个方面重点介绍。
一致性。 秒杀中商品减库存的实现方式同样关键。可想而知,有限数量的商品在同一时刻被很多倍的请求同时来减库存,减库存又分为“拍下减库存”“付款减库存”以及预扣等几种,在大并发更新的过程中都要保证数据的准确性,其难度可想而知。因此,将用一个节点来专门讲解如何设计秒杀减库存方案。
高可用。 虽然介绍了很多极致的优化思路,但现实中总难免出现一些我们考虑不到的情况,所以要保证系统的高可用和正确性,还要设计一个PlanB来兜底,以便在最坏情况发生时仍然能够从容应对。笔记的最后,将带你思考可以从哪些环节来设计兜底方案。
篇幅有限,无法一个模块一个模块详细的展示(这些要点都收集在了这份《高并发秒杀顶级教程》里),麻烦各位转发一下(可以帮助更多的人看到哟!)
由于内容太多,这里只截取部分的内容。
); dis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
🌳🌳🌳🌳🌳🌳🌳🌳🌳🌳🌳🌳🌳🌳分界线🌳🌳🌳🌳🌳🌳🌳🌳🌳🌳🌳🌳🌳🌳
打印流
什么是打印流?
java.io.PrintStream extends OutputStream,作用是为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式
总目录展示
该笔记共八个节点(由浅入深),分为三大模块。
高性能。 秒杀涉及大量的并发读和并发写,因此支持高并发访问这点非常关键。该笔记将从设计数据的动静分离方案、热点的发现与隔离、请求的削峰与分层过滤、服务端的极致优化这4个方面重点介绍。
一致性。 秒杀中商品减库存的实现方式同样关键。可想而知,有限数量的商品在同一时刻被很多倍的请求同时来减库存,减库存又分为“拍下减库存”“付款减库存”以及预扣等几种,在大并发更新的过程中都要保证数据的准确性,其难度可想而知。因此,将用一个节点来专门讲解如何设计秒杀减库存方案。
高可用。 虽然介绍了很多极致的优化思路,但现实中总难免出现一些我们考虑不到的情况,所以要保证系统的高可用和正确性,还要设计一个PlanB来兜底,以便在最坏情况发生时仍然能够从容应对。笔记的最后,将带你思考可以从哪些环节来设计兜底方案。
篇幅有限,无法一个模块一个模块详细的展示(这些要点都收集在了这份《高并发秒杀顶级教程》里),麻烦各位转发一下(可以帮助更多的人看到哟!)
[外链图片转存中…(img-9QECEsBf-1716450408473)]
[外链图片转存中…(img-NjEcuCXw-1716450408474)]
由于内容太多,这里只截取部分的内容。