Java IO流指的是Java输入输出流,用于处理与文件、网络等设备之间的数据传输。Java提供了InputStream和OutputStream两个抽象类作为所有输入输出流类的基类,以及Reader和Writer两个抽象类作为所有字符输入输出流类的基类。同时,Java还提供了许多具体的输入输出流类和字符输入输出流类,如FileInputStream、FileOutputStream、BufferedInputStream、BufferedOutputStream、InputStreamReader、OutputStreamWriter等。这些类可用于读取文件、写入数据到文件、从网络中读取数据、向网络中写入数据等常见操作。
输出流:程序 -> 文件
输入流:文件 -> 程序
Java IO流主要用于处理与文件、网络等设备之间的数据传输。其具体作用包括:
Java IO流为Java程序处理输入输出提供了丰富而灵活的方式,适用于各种场景和应用。
Java IO流可以分为四种类型:字节输入输出流、字符输入输出流、字节缓冲输入输出流和字符缓冲输入输出流。
此外,Java IO流还可以根据不同的来源和目的地进行分类,如:
使用字节输入流可以读取本地文件中的数据并加载到程序中进行操作。
方法 | 说明 |
---|---|
public int read() | 一次读一个字节数据 |
public int read(byte[] buffer) | 一次读一个字节数组数据 |
//创建对象
FileInputStream fis = new FileInputStream("文件所在路径");
//public int read(),循环读取数据
int b;
while ((b = fis.read()) != -1) {
System.out.print(((char) b));
}
//释放资源
fis.close();
创建字节输入流细节:
如果文件不存在,使用字节输入流会抛出异常并报错。
读取数据细节:
read()
方法将返回-1。释放资源细节:
为了避免持续占用资源,每次使用输入流或输出流后都应该释放其对应的资源。
使用字节输出流可以将程序中的数据写入到本地文件中。
//创建对象
FileOutputStream fos = new FileOutputStream("文件所在路径");
//or
FileOutputStream fos = new FileOutputStream(new File("文件所在路径"));
//or,续写开关,默认为false
FileOutputStream fos = new FileOutputStream("文件所在路径", true);
//写出数据
fos.write(99);
//void write(byte[] b)
fos.write(new byte[]{111, 121, 100, 101, 115});
void write(byte[] b, int off, int len)
fos.write(bytes, 1, 3); //从下标为1开始写入,写入3个
//换行写,使用/r/n
fos.write("rqz\r\n779".getBytes());
//释放数据
fos.close();
创建字节输出流对象细节:
写入数据细节:
字节输出流中的write()
方法参数为整数,但实际上在文件中写入的是该整数所对应的ASCII字符。
释放资源细节:
为了避免持续占用资源,每次使用输入流或输出流后都应该释放其对应的资源。
换行细节:
在Windows操作系统中,Java对回车换行进行了优化。尽管完整的换行符为\r\n,但只需使用其中一个\r或\n也可以实现换行,因为Java会在底层自动补全缺少的字符。
为了避免覆盖先前读取操作的内容,重要的是指定从输入流中读取的字节数长度。如果未指定长度,则可能在字节数组中存在来自上一次读取操作的残留内容,如果字节数组没有被最近的读取操作完全填满,则在下一个写入操作期间会导致意外数据被写入。
// 1. 创建一个字节数组作为缓冲区
byte[] buffer = new byte[1024];
// 2. 创建一个 FileInputStream 对象用于读取文件
FileInputStream fis = new FileInputStream("input.txt");
// 3. 创建一个 FileOutputStream 对象用于写入文件
FileOutputStream fos = new FileOutputStream("output.txt");
// 4. 循环读取文件内容到缓冲区,并将缓冲区中的数据写入到输出文件中
int length;
while ((length = fis.read(buffer)) != -1) {
fos.write(buffer, 0, length);
}
// 5. 关闭输入输出流
fis.close();
fos.close();
该代码通过创建一个字节数组作为缓冲区来提高读写效率,先通过FileInputStream
对象读取input.txt
文件内容到缓冲区中,再通过FileOutputStream
对象将缓冲区中的数据写入到output.txt
文件中。最后关闭输入输出流并输出复制成功消息。
字符输入流(Reader)是Java IO流体系中的一个抽象类,用于读取字符数据。它是所有字符输入流类的基类,提供了一些常用的读取字符的方法,如read()
和readLine()
等。
与字节输入流不同,字符输入流处理的是字符数据,以字符形式进行读写操作。InputStream对象每次读取一个字节,而Reader对象则每次读取一个字符,因此如果需要处理文本文件或其他字符数据,应该使用字符输入流来读取数据。
Java IO流中还提供了许多具体的字符输入流类,如FileReader、InputStreamReader、BufferedReader等,这些类可以根据不同的需求和场景提供更加丰富和灵活的字符输入流读取方式。
方法 | 说明 |
---|---|
public int read() | 读取数据,读到末尾返回-1 |
public int read(char[] cbuf) | 读取多个数据,读到末尾返回-1 |
//public int read()
//1.创建对象并关联本地文件
FileReader frd = new FileReader("文件所在路径");
//2.读取数据 read()
int ch;
while ((ch = frd.read()) != -1) {
//默认显示的是十进制数据,查看中文需要进行char强转
System.out.print((char)ch);
}
//3.释放资源
frd.close();
//public int read(char[] cbuf)
//1.创建对象并关联本地文件
FileReader frd = new FileReader("文件所在路径");
//2.读取数据 read(char[] cbuf)
char[] chars = new char[1024 * 1024 * 5];
int len;
while ((len = frd.read(chars)) != -1) {
//把数组中的数据变成字符串再进行打印
System.out.print(new String(chars, 0, len));
}
//3.释放资源
frd.close();
read()细节:
read(char[] cbuf)细节:
此方法是将数据读取、解码和强转三个步骤合并,并在完成强转后才将字符放入数组中。
字符输出流(Writer)是Java IO流体系中的一个抽象类,用于写入字符数据。它是所有字符输出流类的基类,提供了一些常用的写入字符的方法,如write()
和flush()
等。
与字节输出流不同,字符输出流处理的是字符数据,以字符形式进行读写操作。OutputStream对象每次写入一个字节,而Writer对象则每次写入一个字符,因此如果需要处理文本文件或其他字符数据,应该使用字符输出流来写入数据。
Java IO流中还提供了许多具体的字符输出流类,如FileWriter、OutputStreamWriter、BufferedWriter等,这些类可以根据不同的需求和场景提供更加丰富和灵活的字符输出流写入方式。
方法 | 说明 |
---|---|
void write(int c) | 写出一个字符 |
void write(String str) | 写出一个字符串 |
void write(String str, int off, int len) | 写出一个字符串一部分 |
void write(char[] cbuf) | 写出一个字符数组 |
void write(char[] cbuf, int off, int len) | 写出字符数组一部分 |
public void flush() | 将缓冲区的数据,刷新到本地文件中 |
public void close() | 释放资源/关流 |
//1.创建对象并关联本地文件
FileWriter fwt = new FileWriter("文件所在路径");
//2.写入数据 read(String str)
fwt.write("多学点");
//3.释放资源
fwt.close();
总之,字符输出流工作原理的核心是采用缓冲区技术来提高写入性能,并允许操作者控制何时将数据写入物理设备。
方法 | 说明 |
---|---|
public byte[] getBytes() | 使用默认方式进行编码 |
public byte[] getBytes(String charsetName) | 使用指定方式进行编码 |
//1.默认编码
String str = "rqz搞快点";
byte[] bytes = str.getBytes();
//2.指定编码
String str = "rqz搞快点";
byte[] bytes = str.getBytes("GBK");
方法 | 说明 |
---|---|
String(byte[] bytes) | 使用默认方式进行解码 |
String(byte[] bytes, String charsetName) | 使用指定方式进行解码 |
//1.默认解码
String str = "rqz搞快点";
byte[] bytes = str.getBytes("GBK");
//idea默认使用utf-8进行解码
String s = new String(bytes);
System.out.println(s); //rqz����
//2.指定解码
String str = "rqz搞快点";
byte[] bytes = str.getBytes("GBK");
String s = new String(bytes, "GBK");
System.out.println(s); //rqz搞快点
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Objects;
public class FolderCopyExample {
public static void main(String[] args) {
String sourceFolderPath = "C:\\Users\\Rr\\Desktop\\1";
String targetFolderPath = "C:\\Users\\Rr\\Desktop\\2";
try {
// 创建目标文件夹
new File(targetFolderPath).mkdirs();
// 获取源文件夹对象
File sourceFolder = new File(sourceFolderPath);
// 遍历源文件夹内的所有文件和子文件夹并递归复制它们
copyFolder(sourceFolder, new File(targetFolderPath));
System.out.println("Folder copied successfully.");
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 递归复制文件夹及其内容
*/
private static void copyFolder(File sourceFolder, File destinationFolder) throws IOException {
// 如果源文件夹不存在,则直接退出方法
if (!sourceFolder.exists()) {
return;
}
// 如果目标文件夹不存在,则创建它
if (!destinationFolder.exists()) {
destinationFolder.mkdirs();
}
// 遍历源文件夹中所有的文件和子文件夹
for (File file : Objects.requireNonNull(sourceFolder.listFiles())) {
if (file.isDirectory()) {
// 如果当前文件是一个文件夹,则递归调用copyFolder方法以复制该文件夹及其内容
copyFolder(file, new File(destinationFolder, file.getName()));
} else {
// 如果当前文件不是一个文件夹,则使用Files.copy方法将文件复制到目标文件夹中
Files.copy(file.toPath(), destinationFolder.toPath().resolve(file.getName()));
}
}
}
}
//创建文件对象
FileInputStream fis = new FileInputStream("文件所在路径");
FileOutputStream fos = new FileOutputStream("文件所在路径");
int b;
//读取文件
while ((b = fis.read()) != -1) {
//通过异或操作写入文件
fos.write(b ^ 779);
}
//释放资源
fos.close();
fis.close();
字节缓冲流是Java中用于处理字节数据的一种输入输出流,它可以提供高效的读写操作。字节缓冲流内部维护了一个缓冲区,读写时先将数据存入缓冲区中,当缓冲区满时再将数据一次性写入或者读取出来,这样可以减少实际的I/O操作次数,提高读写操作的效率。Java中的字节缓冲流有两种类型:BufferedInputStream和BufferedOutputStream。
其中BufferedInputStream可以从另一个输入流中读取数据,并将其存储在内部缓冲区中,而BufferedOutputStream则可以将数据写入另一个输出流中,并将其存储在内部缓冲区中,直到缓冲区被填满或者调用了flush()方法才会将数据真正写入输出流中。
底层自带了长度为8192的字节数组缓冲区提高性能
方法 | 说明 |
---|---|
public BufferedInputStream (InputStream is) | 把基本流包装成高级流,提高读取数据的性能 |
方法 | 说明 |
---|---|
public BufferedInputStream (OutputStream os) | 把基本流包装成高级流,提高写出数据的性能 |
//源文件路径
String sourceFile = "源文件路径";
//目标文件路径
String destinationFile = "目标文件路径";
//创建输入输出缓冲流
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(sourceFile));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destinationFile));
//循环读取并写到目标文件
byte[] bytes = new byte[1024];
int bytesRead;
while ((bytesRead = bis.read(bytes)) != -1) {
bos.write(bytes,0,bytesRead);
}
//释放资源
bos.close();
bis.close();
字符缓冲流是Java I/O中的一种流,用于处理字符数据。它继承自Reader和Writer类,可以以缓冲方式读写字符数据,提高输入输出的效率。
与普通的Reader和Writer相比,字符缓冲流具有以下特点:
常用的字符缓冲流有BufferedReader和BufferedWriter。其中,BufferedReader主要用于从字符输入流中读取文本数据,而BufferedWriter则用于向字符输出流中写入文本数据。
底层自带了长度为8192的字符数组缓冲区提高性能,一个字符为2个字节
方法 | 说明 |
---|---|
public BufferedReader (Reader r) | 把基本流包装成高级流 |
public String readLine() | 读取一行数据,如果没有数据可读了,会返回null |
//获取基本流对象
FileReader fileReader = new FileReader("example.txt");
//把基本流包装成高级流
BufferedReader bufferedReader = new BufferedReader(fileReader);
//接收每一行数据
String line;
//循环读取每一行数据,如果没有数据可读了,会返回null
while ((line = bufferedReader.readLine()) != null) {
System.out.println(line);
}
//释放资源
bufferedReader.close();
方法 | 说明 |
---|---|
public BufferedWriter (Reader r) | 把基本流包装成高级流 |
public String newLine() | 跨平台的换行 |
//获取基本流对象
FileWriter fileWriter = new FileWriter("example.txt");
//把基本流包装成高级流
BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
//字符串文本
String text = "Hello, world!\nThis is an example.\n";
//写入数据
bufferedWriter.write(text);
//换行(可跨平台)
bufferedWriter.newLine();
//释放资源
bufferedWriter.close();
Java转换流是Java I/O库中的一种流,在字节流和字符流之间进行转换。它主要用于处理字符数据与字节数据之间的转换,是Reader和Writer类的一种包装。转换流可以将字节流转换为字符流,也可以将字符流转换为字节流。
转换流有两种类型:InputStreamReader和OutputStreamWriter。其中,InputStreamReader用于将字节输入流转换为字符输入流,而OutputStreamWriter则用于将字符输出流转换为字节输出流。转换时,需要指定字符编码,例如UTF-8或GBK等。
使用转换流的主要优点是可以同时处理字节流和字符流,并且可以在不同编码方式之间转换数据,方便进行跨平台开发和国际化处理。常见的应用场景包括读取和写入文本文件、处理网络数据和操作数据库等。
FileReader为JDK11后的InputStreamReader替代方案
//创建转换流对象并指定字符集编码
FileReader fr = new FileReader("文件所在路径", Charset.forName("GBK"));
//读取数据
int data;
while ((data = fr.read()) != -1) {
System.out.print((char) data);
}
//释放资源
fr.close();
FileWriter fw = new FileWriter("文件所在路径", Charset.forName("GBK"));
fw.write("rqz多学点");
fw.close();
//利用字作流读取文件中的数据,每次读一整行,而且不能出现乱码
//获取字节文件对象
FileInputStream fis = new FileInputStream("example.txt");
//通过转换流将字节文件对象转换为字符文件对象,并指定字符编码
InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
//创建字符缓冲流
BufferedReader br = new BufferedReader(isr);
//循环读取数据
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
//释放资源
br.close();
Java序列化流是Java I/O库中的一种流,用于将对象转换为字节流以便进行存储或传输。序列化流可以将一个包含数据的对象转换为二进制格式的字节数组,方便在网络上进行传输或者在文件中进行存储。
使用序列化流的主要优点是方便实现对象的持久化,即在程序结束后仍然能够保留对象状态和数据。同时,序列化流还可以用于实现远程方法调用(RMI)和分布式应用程序等。
Java提供了两个主要的序列化流:ObjectInputStream和ObjectOutputStream。其中,ObjectOutputStream用于将对象写入输出流中,而ObjectInputStream则用于从输入流中读取对象。在使用这些流时,需要注意对象必须实现Serializable接口,否则会抛出NotSerializableException异常。
import java.io.*;
public class SerializableExample {
public static void main(String[] args) throws IOException, ClassNotFoundException {
// 将对象写入文件,
FileOutputStream fos = new FileOutputStream("文件所在路径");
//创建序列化流对象/对象操作输出流
ObjectOutputStream oos = new ObjectOutputStream(fos);
//创建对象
Person person = new Person("Tom", 20);
//写出数据
oos.writeObject(person);
//释放资源
oos.close();
// 从文件中读取对象
FileInputStream fis = new FileInputStream("文件所在路径");
//创建反序列化流对象/对象操作输入流
ObjectInputStream ois = new ObjectInputStream(fis);
Person newPerson = (Person) ois.readObject();
System.out.println(newPerson);
ois.close();
}
}
// 实现Serializable接口的类
class Person implements Serializable {
//为了确保反序列化时能够正确地载入对象,建议显示声明serialVersionUID。
private static final long serialVersionUID = 1L;
private String name;
//transient瞬态关键字,不会把当前属性序列化到本地文件中
private transient int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
}
import java.io.*;
import java.util.ArrayList;
public class SerializableExample {
public static void main(String[] args) throws IOException, ClassNotFoundException {
// 将多个对象写入文件
FileOutputStream fos = new FileOutputStream("example.ser");
//创建序列化流对象/对象操作输出流
ObjectOutputStream oos = new ObjectOutputStream(fos);
//创建ArrayList对象,将所有对象放在ArrayList内
ArrayList<Person> personList = new ArrayList<>();
personList.add(new Person("Tom", 20));
personList.add(new Person("Jerry", 22));
personList.add(new Person("Alice", 18));
//写出ArrayList
oos.writeObject(personList);
//释放资源
oos.close();
// 从文件中读取多个对象
FileInputStream fis = new FileInputStream("example.ser");
ObjectInputStream ois = new ObjectInputStream(fis);
ArrayList<Person> newPersonList = (ArrayList<Person>) ois.readObject();
for (Person person : newPersonList) {
System.out.println(person);
}
ois.close();
}
}
// 实现Serializable接口的类
class Person implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
}
Java字节打印流是Java I/O库中的一种流,它可以将数据转换为字节,并输出到指定输出流中。字节打印流主要用于向文件或网络等数据通道写入文本或二进制数据。
Java提供了两种主要的字节打印流:PrintStream和PrintWriter。其中,PrintStream是处理字节流的打印流,而PrintWriter则是处理字符流的打印流。
使用字节打印流的主要优点是简化了输出操作,可以直接输出各种类型的数据,包括字符串、整数、浮点数等,同时可以自动进行格式化。另外,字节打印流还提供了一些特殊功能,例如自动刷新、自定义分隔符等。
需要注意的是,在使用字节打印流时,必须显式指定输出流对象,否则会抛出NullPointerException异常。同时,在使用完毕后,需要关闭打印流。
字节流底层没有缓冲区,开不开自动刷新都一样
//创建字节打印流,并指定字符集
PrintStream ps = new PrintStream("文件所在路径", "GBk");
//写入字符串,并换行
ps.println("Hello World!");
//写入字符串,格式化输出
ps.printf("My name is %s, I'm %d years old.", "Tom", 20);
//释放资源
ps.close();
Java字符打印流是Java I/O库中的一种流,它可以将数据转换为字符,并输出到指定输出流中。字符打印流主要用于向文件或网络等数据通道写入文本或字符数据。
Java提供了两种主要的字符打印流:PrintWriter和PrintStream。其中,PrintWriter是处理字符流的打印流,而PrintStream则是处理字节流的打印流。
使用字符打印流的主要优点是简化了输出操作,可以直接输出各种类型的数据,包括字符串、整数、浮点数等,同时可以自动进行格式化。另外,字符打印流还提供了一些特殊功能,例如自动刷新、自定义分隔符等。
需要注意的是,在使用字符打印流时,必须显式指定输出流对象,否则会抛出NullPointerException异常。同时,在使用完毕后,需要关闭打印流。
字符流底层有缓冲区,想要自动刷新需要开启
//创建文件对象
FileWriter fw = new FileWriter("example.txt");
//创建字符打印流对象,开启自动刷新
PrintWriter pw = new PrintWriter(fw, true);
//写入字符串,并换行
pw.println("Hello World!");
//写入字符串,格式化输出
pw.printf("My name is %s, I'm %d years old.", "Tom", 20);
//释放资源
pw.close();
Java解压缩流是Java I/O库中的一种流,用于解压已经压缩过的数据。可以使用解压缩流来读取压缩文件,并将其中的数据解压缩后输出到目标数据通道中。
Java提供了两种主要的解压缩流:InflaterInputStream和GZIPInputStream。其中,InflaterInputStream是通用的解压缩流,可以处理各种常见的压缩格式,例如Zip、Gzip、Deflate等;而GZIPInputStream则专门用于处理Gzip压缩格式。
使用解压缩流的主要优点是简化了解压缩操作,可以直接从压缩文件中读取数据,同时可以自动进行解压缩。另外,解压缩流还提供了一些特殊功能,例如自动跳过头部信息、自定义缓冲区大小等。
需要注意的是,在使用解压缩流时,必须显式指定输入流对象,否则会抛出NullPointerException异常。同时,在使用完毕后,需要关闭流。
Commons-io是一个开源的Java库,提供了一系列实用类和方法,用于处理常见的输入输出(I/O)操作。这个库可以大大简化I/O编程任务,例如读写文件、拷贝文件、处理字节和字符流等。Commons-io还提供了许多方便的工具方法,例如比较文件内容、查找文件、解析URL等。它是Apache Commons项目的一部分,可以被广泛应用于Java开发中。
Commons-io提供了众多实用方法,下面列举其中一些常用的方法:
这些方法都提供了高度的可定制性和灵活性,可以满足不同场景的需求。
Hutool是一个开源的Java工具库,提供了丰富的工具类和方法,包括字符串处理、日期时间处理、文件操作、加密解密、网络请求、XML/JSON解析等常见功能。Hutool致力于简化Java开发过程中的常用操作,提高开发效率。它的设计理念是易用、可靠、高效,并且提供了简洁易懂的API文档和示例代码,方便开发者上手使用。Hutool也是国内比较受欢迎的Java工具库之一。
Hutool提供了众多实用方法,下面列举其中一些常用的方法:
这些方法都提供了高度的可定制性和灵活性,可以满足不同场景的需求。Hutool还提供了其他许多实用的工具类和方法,包括集合操作、XML解析、正则表达式等,可以大大简化Java开发过程中的编码工作。