- VisualStudio2022插件的安装及使用-编程手把手系列文章
- pprof-在现网场景怎么用
- C#实现的下拉多选框,下拉多选树,多级节点
- 【学习笔记】基础数据结构:猫树
流是一个抽象的概念,代表了数据的无结构化传递。流的本质是数据在不同设备之间的传输。在 Java 中,数据的读取和写入都是以流的方式进行的 。
在 Java 中,根据数据流向的不同,可以将流分为输入(Input)流和输出(Output)流。根据单位的不同,可以将流分为字节流和字符流。根据等级的不同,可以将流分为节点流和处理流 。
输入流用于将数据从控制台、文件、网络等外部设备输入应用程序进程中 。
输出流用于将应用程序进程中的数据输出到控制台、文件、显示器等中 。
字节流:字节流是以字节(1byte=8bit)为单位对数据进行读写操作的,也就是说,字节流进行一次读取或者写入都是以 8bit 为单位进行的,因此主要用于处理二进制据。在 Java 中使用 InputStream、OutputStream 处理字节数据,其中 InputStream 用于字节流输入,OutputStream 用于字节流输出 。
字符流:字符流以字符为单位对数据进行读写操作,一次读取或写入都是以 16bit 为单位进行的。Java 中的字符采用 Unicode 编码,一个字符占用 2 字节。字符流主要用于处理文本数据的读写,在处理过程中需要进行字符集的转化。在 Java 中使用 Reader、Writer 处理字符数据,其中 Reader 用于字符流输入,Writer 用于字符流输出 。
InputStream 字节输入流是一个抽象类,其子类包括:
InputStream 类的所有方法在遇到错误时都会抛出 IOExcepiion 异常。InputStream 用于以字节形式将数据读入应用程序中,常用的方法及其作用如表所示 。
方法 | 作用 |
---|---|
int read() | 从输入流读取8字节数据并将其转换成一个0-255的整数,返回值为读取的总字节数,遇到数据流的末尾则返回-1 |
int read(byte[] b) | 从输入流中读取最大长度为len字节的数据并保存到b字节数组中,遇到数据流的末尾则返回-1 |
int read(byte[] b, int off, int len) | 以输入流中的off位置为开始位置读取最大长度为len字节的数据,并将其保存到b字节数组中 |
void close() | 关闭输入流 |
int available() | 返回可以从输入流中读取的位数 |
skip(long n) | 从输入流跳过n字节 |
一段基于 FileInputStream 读取文件的代码如下:
public static void main(string[] args) throws IoException {
String path = "file_dir/";
String fileName = "File-Test.txt";
// 1:定义待读取的文件
File file = new File(path, fileName);
// 2:从文件中读取数据到 FileInputStream
FileInputStream fileInputStream = new FileInputStream(file);
byte[] bytes = new byte[fileInputstream.available()];
int n = 0;
// 3:从FileInputstream中不断循环读取字节数据并写入bytes,直到遇到数据流结尾时
while ((n = fileInputstream.read(bytes)) != -1) {
// 4:将byte[]转化为字符串
String s = new String(bytes);
System.out.printIn(s);
}
// 5:关闭输入文件流
fileInputStream.close();
}
OutputStream 字节输出流是一个抽象类,其子类包括:
OutputStream 类的所有方法在遇到错误时都会抛出 IOException 异常。OutputStream 用于以字节形式将数据输出到目标设备,常用的方法及其作用如表所示 。
方法 | 作用 |
---|---|
int write() | 将指定字节的数据写入输出流 |
int write(byte[] b) | 将指定字节数组的内容写入输出流 |
int write(byte[] b, int off, int len) | 将指定的字节数组从off位置开始的len字节的内容写入输出流 |
close() | 关闭数据流 |
flush() | 刷新输出流,强行将缓冲区的内容写入输出流 |
基于 FileOutputStream 读取文件的一段代码如下 。
public static void main(String[] args) throws IOException {
String path = "file_dir/";
String fileName = "File-Test.txt";
// 1:定义待写入的文件
File file = new File(path, fileName);
// 2:定义FileOutputStream
FileOutputStream fileOutputStream = new FileOutputStream(file, false);
// 3:将数据写入FileOutputStream
fileOutputStream.write("hello FileOutputStream new " .getBytes());
// 4:关闭FileOutputStream
fileOutputStream.close();
}
Reader 类是所有字符流输入类的父类,用于以字符形式将数据读取到应用程序中,其子类包括:
Reader 类常用方法如下 。
方法 | 作用 |
---|---|
int read() | 从输入流中读取一个字符并转化为 0-65535 的整数,当读取到流的末尾时返回-1 |
int read(char[] buf) | 从输入流中读取若干个字符并保存到参数buf指定的字符数组中,当读取到流的末尾时返回-1 |
int read(char[] buf, int off, int len) | 以输入流中的off位置为开始位置读取最大长度为len字节的数据并将其保存到buf字符数组中,当读取到流的末尾时返回-1 |
基于 BufferedReader 读取文件的一段代码如下:
public static void main(string[] args) throws Exception {
String path = "file_dir.mov";
//1:创建FileReader
FileReader fileReader = new FileReader(path);
//2:基于FileReader创建BufferedReader
BufferedReader bufferedReader = new BufferedReader(fileReader);
//3:定义一个strLine,表示BufferedReader读取的结果
String strLine = "";
//4:调用readLine方法将缓冲区中的数据读取为字符串
//当readLine返回-1时,表示已经读取到文件末尾了
while((strLine = bufferedReader.readLine()) != null) {
System.out.println(strLine);
}
//5:关团fileReader
fileReader.close();
//6:关闭bufferedReader
bufferedReader.close();
}
Writer 类是所有字符流输出类的父类,用于以字符形式将数据写出到外部设备,其子类包括:
Writer 类常用方法如下 。
方法 | 作用 |
---|---|
void write(int c) | 向输出流中写入一个字符 |
void write(char[] cbuf) | 将字符数组cbuf中的字符写入输出流中 |
void write(char[] cbuf,int off, int len) | 将字符数组cbuf中从off位置开始获取长度为len的字符并写入输出流中 |
void write(String str) | 将字符串写入输出流 |
void write(String str,int off, int len) | 将字符串中的部分字符写入输出流 |
append(char c) | 将字符c追加到输出流 |
append(charSequence csq) | 将参数csq指定的字符序列追加到输出流 |
append(charSequence csq, int start, int end) | 将参数csq指定的字符序列的子序列追加到输出流 |
基于 BufferedWriter 将字符串写入文件中的一段代码如下:
public static void main(String[] args) throws Exception {
//1:定义一个FileWriter
String path = "File-Test.txt";
FileWriter writer = new FileWriter(path);
//2:基于FileWriter定义一个BufferWriter
BufferedWriter bufferedWriter = new BufferedWriter(writer)
//3:调用BufferedWriter的write方法将字符串写入BufferedWriter
bufferedWriter.write("write by str");
//4:关闭BufferedWriter
bufferedWriter.close();
//5:关闭FileWriter
writer.close();
}
节点流是低级流,直接与数据源相接,对数据源上的流进行读写.
处理流是高级流,采用修饰器模式对节点流进行了封装,不直接与数据源相连,主用于消除不同节点流的实现差异,提供更方便的方法来完成数据的输入和输出.
例如,FileInputStream、FileOutputStream、FileReader、FileWriter 属于节点流;BufferInputStream、BufferOutputStream、BufferReader、BufferWriter 属于处理流.
相对于节点流,处理流有如下特性:
操作系统可以利用虚拟内存实现将一个文件或者文件的一部分“映射”到内存中。然后,这个文件就可被当作内存数据来访问,比传统的文件要快得多,这种技术就是内存映射文件技术.
内存映射文件技术的一个关键优势是操作系统负责真正的文件读写,应用程序只需处理内存数据,就可以实现非常快速的 IO 操作。在写入过程中,即使应用程序在将数据写人内存后进程出错退出,操作系统仍然会将内存映射文件中的数据写入文件系统。另一个更突出的优势是共享内存,即内存映射文件可被多个进程同时访问,起到低时延共享内存的作用.
Java 中的 java.nio 包支持内存映射文件,具体使用方式是通过 MappedByteBuffer 读写内存,而且内存映射文件技术涉及的内存在 Java 的堆空间之外,这也是其效率高的一个原因.
在 Java 中将一个文件映射到内存并操作共分为如下三步:
从文件中获得一个通道(channel) 。
RandomAccessFile raf = new RandomAccessFile(filePath, "rw");
FileChannel fc= raf.getChannel();
调用 FileChannel 的 map 方法将文件映射到虚拟内存 。
MappedByteBuffer buffer = channel.map(mode, 0, length);
mode 参数用于指定映射模式,支持的模式有如下三种:
调用 MappedByteBuffer 的 put(byte[] src) 向内存映射文件中写入数据,调用 get(int index) 获取文件中对应索引的数据,以字节形式返回 。
public static void main(String[] args) throws Exception {
//1:定义文件流
String path = "file_path/File-Test.txt";
RandomAccessFile raf = new RandomAccessFile(path,"rw");
//2:获取FileChannel
FileChannel fc = raf.getChannel();
//3:定义MappedByteBuffer
int start = 0:
int len = 1024;
//调用map函数的过程其实就是磁盘文件到内存数据的映射过程
//对Filechannel调用map函数后,应用程序可以像使用内存一样使用该文件
MappedByteBuffer mbb = fc.map(FileChannel.MapMode.PRIVATE, start, len);
//4:进行MappedByteBuffer数据的输入,分别在内存映射文件中写入如下字符串
mbb.put("12345".getBytes());
mbb.put("6789".getBytes());
mbb,put("wanglei".getBytes());
//读取第9个字符,结果为"w"
System.out.println((char)mbb.get(9));
//5:MappedByteBuffer数据的读取:读取所有数据
for (int i = start; i < mbb.position(); i++) {
System.out.println((char)mbb.get(i));
}
}
最后此篇关于JavaIO流详解的文章就讲到这里了,如果你想了解更多关于JavaIO流详解的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
这个问题在这里已经有了答案: Why filter() after flatMap() is "not completely" lazy in Java streams? (8 个答案) 关闭 6
我正在创建一个应用程序来从 Instagram 收集数据。我正在寻找像 Twitter 流 API 这样的流 API,这样我就可以自动实时收集数据而无需发送请求。 Instagram 有类似的 API
我正在使用 Apache Commons 在 Google App Engine 中上传一个 .docx 文件,如此链接中所述 File upload servlet .上传时,我还想使用 Apach
我尝试使用 DynamoDB 流和 AWS 提供的 Java DynamoDB 流 Kinesis 适配器捕获 DynamoDB 表更改。我正在 Scala 应用程序中使用 AWS Java 开发工具
我目前有一个采用 H.264 编码的 IP 摄像机流式视频 (RTSP)。 我想使用 FFmpeg 将此 H.264 编码流转换为另一个 RTSP 流,但 MPEG-2 编码。我该怎么做?我应该使用哪
Redis 流是否受益于集群模式?假设您有 10 个流,它们是分布在整个集群中还是都分布在同一节点上?我计划使用 Redis 流来实现真正的高吞吐量(200 万条消息/秒),所以我担心这种规模的 Re
这件事困扰了我一段时间。 所以我有一个 Product 类,它有一个 Image 列表(该列表可能为空)。 我想做 product.getImages().stream().filter(...) 但
是否可以使用 具有持久存储的 Redis 流 还是流仅限于内存数据? 我知道可以将 Redis 与核心数据结构的持久存储一起使用,但我已经能够理解是否也可以使用 Redis 中的流的持久存储。 最佳答
我开始学习 Elixir 并遇到了一个我无法轻松解决的挑战。 我正在尝试创建一个函数,该函数接受一个 Enumerable.t 并返回另一个 Enumerable.t ,其中包含下 n 个项目。它与
我试图从 readLine 调用创建一个无限的字符串流: import java.io.{BufferedReader, InputStreamReader} val in = new Buffere
你能帮我使用 Java 8 流 API 编写以下代码吗? SuperUser superUser = db.getSuperUser; for (final Client client : super
我正在尝试服用补品routeguide tutorial,并将客户端变成rocket服务器。我只是接受响应并将gRPC转换为字符串。 service RouteGuide { rpc GetF
流程代码可以是run here. 使用 flow,我有一个函数,它接受一个键值对对象并获取它的值 - 它获取的值应该是字符串、数字或 bool 值。 type ValueType = string
如果我有一个函数返回一个包含数据库信息的对象或一个空对象,如下所示: getThingFromDB: async function(id:string):Promise{ const from
我正在尝试使用javascript api和FB.ui将ogg音频文件发布到流中, 但是我不知道该怎么做。 这是我给FB.ui的电话: FB.ui( { method: '
我正在尝试删除工作区(或克隆它以使其看起来像父工作区,但我似乎两者都做不到)。但是,当我尝试时,我收到此消息:无法删除工作区 test_workspace,因为它有一个非空的默认组。 据我所知,这意味
可以使用 Stream|Map 来完成此操作,这样我就不需要将结果放入外部 HashMap 中,而是使用 .collect(Collectors.toMap(...)); 收集结果? Map rep
当我们从集合列表中获取 Stream 时,幕后到底发生了什么?我发现很多博客都说Stream不存储任何数据。如果这是真的,请考虑代码片段: List list = new ArrayList(); l
我对流及其工作方式不熟悉,我正在尝试获取列表中添加的特定对象的出现次数。 我找到了一种使用Collections来做到这一点的方法。其过程如下: for (int i = 0; i p.conten
我希望将一个 map 列表转换为另一个分组的 map 列表。 所以我有以下 map 列表 - List [{ "accId":"1", "accName":"TestAcc1", "accNumber
我是一名优秀的程序员,十分优秀!