Java IO 流
文件
概念
- 文件:保存数据的地方

-
流: 数据在数据源(文件)和程序(内存)之间经历的路径
-
输入流:数据从数据源(文件)到程序内存的路径
-
输出流:数据从程序(内存)到数据源的路径
常用的文件操作
创建文件对象相关构造器和方法,相关方法
new File(String pathname) //根据路径构建一个File对象
new File(File parent,String child) //根据父目录文件 + 子路径构建
new File(String parent,String child) //根据父目录 + 子路径构建
代码实例
package javaio;
import org.junit.jupiter.api.Test;
import java.io.File;
import java.io.IOException;
public class CreateFile {
// 方式一:new File(String pathname)
@Test
public void createFile01() throws IOException {
String filePath = ".\\file1.txt";
File file = new File(filePath);
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("file1, 文件创建成功");
}
// 方式二:new File(File parent,String child) //根据父目录文件 + 子路径构建
@Test
public void createFile02() throws IOException {
File parentFile = new File(".\\");
String fileName = "file2.txt";
// 此时还在内容中
File file = new File(parentFile, fileName);
try {
// 实际创建完成在此处
file.createNewFile();
System.out.println("file2, 文件创建成功");
} catch (IOException e) {
e.printStackTrace();
}
}
// 方式三:new File(String parent,String child) //根据父目录 + 子路径构建
@Test
public void createFile03() throws IOException {
String fileName = "file3.txt";
String path = ".\\";
// 此时还在内容中
File file = new File(path, fileName);
try {
// 实际创建完成在此处
file.createNewFile();
System.out.println("file3, 文件创建成功");
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
}
}
获取文件的相关信息
getName、getAbsolutePath、getParent、length、exitsts、isFile、isDirectory
package javaio;
import org.junit.jupiter.api.Test;
import java.io.File;
public class GetFileInfo {
@Test
public void getFileInfo() {
// 先创建文件对象
File file = new File(".\\file3.txt");
System.out.println("文件名称: " + file.getName());
System.out.println("绝对路径: " + file.getAbsolutePath());
System.out.println("父目录 : " + file.getParent());
System.out.println("文件大小(字节) : " + file.length());
System.out.println("是否存在 : " + file.isFile());
System.out.println("是否是目录 : " + file.isDirectory());
}
public static void main(String[] args) {
}
}
目录的操作和文件删除
mkdir 创建一级目录,mkdirs 创建多级目录,delete 删除空目录或文件,在 Java中目录也被当成文件
package javaio;
import org.junit.jupiter.api.Test;
import java.io.File;
public class Directory {
@Test
public void deleteFile() {
String filePath = ".\\file4.txt";
File file = new File(filePath);
if (file.exists()) {
if (file.delete()) {
System.out.println("文件删除成功");
} else {
System.out.println("文件没有删除成功");
}
} else {
System.out.println("文件不存在");
}
}
// 删除当前路径下的 abc 目录
@Test
public void deleteDirec() {
String filePath = ".\\abc";
File file = new File(filePath);
if (file.exists()) {
if (file.delete()) {
System.out.println("目录删除成功");
} else {
System.out.println("目录没有删除成功");
}
} else {
System.out.println("目录不存在");
}
}
@Test
public void operateDirec() {
String filePath = ".\\a\\b\\c";
File file = new File(filePath);
if (file.exists()) {
System.out.println("目录存在");
} else {
//if(file.mkdir()) 创建一级目录
if(file.mkdirs()){ // 创建多级目录
System.out.println("目录创建成功");
}else{
System.out.println("目录创建失败");
}
}
}
public static void main(String[] args) {
}
}
IO流原理及流的分类
Java IO流原理
- I/O是Input/Output的缩写,I/O技术是非常实用的技术,用于处理数据传输。如读/写文件,网络通讯等。
- Java程序中,对于数据的输入/输出操作以”流(stream)”的方式进行。
- java.io包下提供了各种“流”类和接口,用以获取不同种类的数据,并通过方法输入或输出数据

- 输入 input: 读取外部数据 (磁盘、光盘等存储设备的数据)到程序(内存)中。
- 输出output: 将程序(内存) 数据输出到磁盘、光盘等存储设备中
流的分类
按操作数据单位不同分为: 字节流(8 bit)二进制文件【声音,视频,word 文件】,字符流(按字符)【文本文件】
按数据流的流向不同分为:输入流,输出流
按流的角色的不同分为: 节点流,处理流/包装流
| (抽象基类) | 字节流 | 字符流 |
|---|---|---|
| 输入流 | lnputStream | Reader |
| 输出流 | OutputStream | Writer |

数据就相当于这里的物品,外卖小哥充当输入和输出流的作用,从用户那里派送物品到物流中心,也将物流中心的物品派送给用户
- Java的IO流共涉及40多个类,实际上非常规则,都是从如上 4 个抽象基类派生的
- 由这四个类派生出来的子类名称都是以其父类名作为子类名后缀
IO 流体系—常用的类
InputStream 抽象类是所有类字节输入流的超类
InputStream 常用子类:
- FileInputStream:文件输入流
- BufferedInputStream:缓冲字节输入流
- ObjectInputStream:对象字节输入流
输入流
InputStream 字节输入流: 是所有类字节输入流的超类

1、FileInputStream 文件输入流[字节流]
构造方法摘要
| 方法 | 方法描述 |
|---|---|
| FileInputStream(File file) | 通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的 File对象file指定。 |
| FileInput Stream(FileDescriptor fdObj) | 通过使用文件描述符fdObj创建一个 FileInputStrean,该文件描述符表示到文件系统中某个实际文件的现有连接。 |
| FileInput Stream(String name) | 通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名name指定。 |
方法摘要
| 方法 | 方法描述 |
|---|---|
| int available() | 返回下一次对此输入流调用的方法可以不受阻塞地从此输入流读取(或跳过)的估计剩余字节数。 |
| void close() | 关闭此文件输入流并释放与此流有关的所有系统资源。 |
| protect void finalize() | 确保在不再引用文件输入流时调用其close方法。 |
| FileChannel getChannel() | 返回与此文件输入流有关的唯一FileChannel对象。 |
| FileDescriptor getFD() | 返回表示到文件系统中实际文件的连接的FileDescriptor 对象,该文件系统正被此FileIngutStream使用。 |
| int read() | 从此输入流中读取一个数据字节。 |
| int read (byte[] b) | 从此输入流中将最多 b.length个字节的数据读入一个 byte 数组中。 |
| int read (byte[] b, int off,int len) | 从此输入流中将最多len个字节的数据读入一个 byte 数组中。 |
| long skip (long n) | 从输入流中跳过并丢弃n个字节的数据。 |
FileInputStream
package javaio.inputstream;
import org.junit.jupiter.api.Test;
import java.io.FileInputStream;
import java.io.IOException;
/**
* 字节输入流 FileInputStream 每次读取单个字节,效率较低
* 注意读取的时候使用 readByte(byte[] b)
*/
public class FileInputStream_ {
@Test
public void readFile01() {
String filePath = ".//file3.txt";
//String filePath = "E:\\QQ file receive\\2084289117\\FileRecv\\myi.txt";
FileInputStream fileInputStream = null;
int readData = 0;
try {
// 创建 fileInputStream 流对象,用于读取文件内容
fileInputStream = new FileInputStream(filePath);
// 从该输入流读取一个字节的数据,如果没有输入可以用,此方法将阻止
// 如果返回 -1, 表示读取完毕
while ((readData = fileInputStream.read()) != -1) {
System.out.print((char) readData); // 转换成 char 显示
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 关闭文件流释放资源, 注意捕获异常
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Test
public void readFile02() {
String filePath = ".//file3.txt";
//String filePath = "E:\\QQ file receive\\2084289117\\FileRecv\\myi.txt";
FileInputStream fileInputStream = null;
int readLen = 0;
// 一次读取8个字节
byte[] buffer = new byte[8];
try {
//创建FileInputStream对象,用于读取文件
fileInputStream = new FileInputStream(filePath);
// 从该输入流读取最多b.length字节的数据到字节数组。此方法将阻塞,直到某些输入、
// 如果返同-1,表示读取完毕
// 如果读取正常,返回实际读取的字节数
while ((readLen = fileInputStream.read(buffer)) != -1) {
System.out.println(new String(buffer, 0, readLen)); // 转换成 string 显示
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 关闭文件流释放资源, 注意捕获异常
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
}
}
2、FileOutputStream 文件输出流
FileOutputStream 代码示例
@Test
public void getProperties01() throws IOException{
String filePath = ".\\mysql.properties";
BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath));
String line = "";
while ((line = bufferedReader.readLine()) != null) {
String[] split = line.split("=");
System.out.println(split[0] + " : " + split[1]);
}
}
package javaio.outputstream;
import org.junit.jupiter.api.Test;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
public class FileOutStream01 {
/**
* 将数据写到文件中,如果文件不存在,则创建文件
*/
@Test
public void writeFile() {
String filePath = ".\\file5.txt";
FileOutputStream fileOutputStream = null;
try {
// 这种创建方式,当写入内容时,会覆盖原来的内容
//fileOutputStream = new FileOutputStream(filePath);
// 这种创建方式,当写入内容时,会追加到文件的结尾
fileOutputStream = new FileOutputStream(filePath, true);
// 方式一,写单个字符
fileOutputStream.write('a');
// 方式二: 写入一个字符串,转为 Bytes 数组
// String.getBytes() ==> 可以将一个字符串转为字节数组
fileOutputStream.write("多个字节".getBytes(StandardCharsets.UTF_8));
// 方式三:
String str = "Java fileOutputStream";
fileOutputStream.write(str.getBytes(), 0, str.length());
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
}
}
-
将一个文件拷贝到另外一个目录,并在新的文件中添加内容
package javaio.outputstream; import java.io.*; import java.nio.charset.StandardCharsets; public class FileCopy { public static void main(String[] args) { // 完成文件拷贝,将路径 D:\Desktop\微信图片_20220311171525.jpg // 图片拷贝到当前目录下 // 思路分析 // 1、 创建文件输入流, 将文件读入到程序 /// 在完成程序时,应该是读取部分数据,就写入到指定的文件,这里使用循环 // 2、 创建文件的输出流,将读取到的文件数据写入到指定的位置 String srcFilePath = "E:\\myi.txt"; String destFilePath = "E:\\jedis\\myi.txt"; // 当前目录下 FileInputStream fileInputStream = null; FileOutputStream fileOutputStream = null; try { fileInputStream = new FileInputStream(srcFilePath); fileOutputStream = new FileOutputStream(destFilePath); byte[] buffer = new byte[1024]; int readLine = 0; String str = " NCOLS 1050" + "\n" + " NROWS 1050" + "\n" + " XLLCORNER -5245000" + "\n" + " YLLCORNER -5245000" + "\n" + " CELLSIZE 10000" + "\n" + " NODATA_VALUE 0" + "\n"; fileOutputStream.write(str.getBytes(StandardCharsets.UTF_8)); while ((readLine = fileInputStream.read(buffer)) != -1) { // 读取到数据之后,就写入到文件中,一边读一边写 // 一定要使用此方法 fileOutputStream.write(buffer, 0, readLine); } System.out.println("文件拷贝成功"); } catch (IOException e) { e.printStackTrace(); } finally { // 关闭输入和输出流释放资源 try { if (fileInputStream != null) { fileInputStream.close(); } if (fileOutputStream != null) { fileOutputStream.close(); } } catch (IOException e) { e.printStackTrace(); } } } }
3、FileReader 字符输入流
FileReader 和 FileWriter是字符流,即按照字符来操作io
java.lang.Object
java.io.Reader
java.io.InputStreamReader
java.io.FileReader
FileReader相关方法:
-
new FileReader(File/String)
-
read: 每次读取单个字符,返回该字符,如果到文件未尾返回 -1
-
read(char[]): 批量读取多个字符到数组,返回读取到的字符数,如果到文件末尾返回-1
-
相关APl:
new String(char[] ); 将char[]转换成String
new String(char[] , off, len);将char[] 的指定部分转换成String
-
package javaio.reader_;
import org.junit.jupiter.api.Test;
import java.io.FileReader;
import java.io.IOException;
public class FileReader_ {
// 单个字符读取文件
@Test
public void readFile01() {
String filePath = "E:\\jedis\\file2___.txt";
FileReader fileReader = null;
int data = 0;
try {
// 循环读取,使用 read 方法
fileReader = new FileReader(filePath);
// 单个字符的读取
while ((data = fileReader.read()) != -1) {
System.out.println((char) data);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fileReader != null) {
fileReader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
// 使用字符数组读取
@Test
public void readFile02() {
String filePath = "E:\\jedis\\file2___.txt";
FileReader fileReader = null;
int readLine = 0;
char[] buffer = new char[8];
try {
// 循环读取,使用 read 方法
fileReader = new FileReader(filePath);
// 使用read(buffer), 返回的是实际读取到的字符数
while ((readLine = fileReader.read(buffer)) != -1) {
System.out.println(new String(buffer, 0, readLine));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fileReader != null) {
fileReader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
}
}
4、FileWriter 字符输出流
java.lang.Object
java.io.Writer
java.io.OutputStreamWriter
java.io.FileWriter
- new FileWriter(File/String): 覆盖模式,相当于流的指针在首端
- new FileWriter(File/String, true): 追加模式,相当于流的指针在尾端
- write(int): 写入单个字符
- write(char[] ): 写入指定数组
- write(char[], off, len): 写入指定数组的指定部分
- write(string):写入整个字符串
- write(string, off, len):写入字符串的指定部分
相关APl: String类: toCharArray:将String转换成char[]
注意:
FileWriter使用后,必须要关闭(close)或刷新(flush),否则写入不到指定的文件!
package javaio.writer;
import org.junit.jupiter.api.Test;
import java.io.FileWriter;
import java.io.IOException;
public class FileWriter_ {
@Test
public void fileWrite01() {
String filePath = ".\\note.txt";
FileWriter fileWriter = null;
try {
// 采用的是覆盖写入
//3) write(int): 写入单个字符
fileWriter = new FileWriter(filePath);
fileWriter.write("J");
char[] chars = {'J', 'a', 'v', 'a'};
//4) write(char[] ): 写入指定数组
fileWriter.write(chars);
//5) write(char[], off, len): 写入指定数组的指定部分
fileWriter.write("AAAAAAAA".toCharArray(), 0, 4);
//6) write(string): 写入整个字符串
fileWriter.write("Java IO流文件写入");
//7) write(string, off, len): 写入字符串的指定部分
fileWriter.write("北京上海广州深圳", 0, 4);
// 在数据量大的情况下,可以循环写入
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
// 对应 FileWriter 一定要关闭流,或者 flush 才能真正的把数据写入到文件中
fileWriter.flush();
// close() 相当于 flush() + 关闭
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.println("文件写入完成");
}
public static void main(String[] args) {
}
}
节点流和处理流
基本介绍
-
结点流可以从一个特定的数据源读写数据,如 FileReader、FileWriter

其他的节点流

-
处理流(包装流)是“连接”在已存在的流(节点流或处理流)之上,为程序提供更为强大的读写功能,如 BufferedReader、BufferedWriter,它们采用了装饰器模式



-
节点流和处理流的区别和联系
-
节点流是底层流/低级流,直接跟数据源相接。
-
处理流(包装流)包装节点流,既可以消除不同节点流的实现差异,也可以提供更方便方法来完成输入输出。
-
处理流(也叫包装流)对节点流进行包装,使用了修饰器设计模式,
-
-
处理流的功能主要体现在以下两个方面:
- 性能的提高:主要以增加缓冲的方式来提高输入输出的效率。
- 操作的便捷:处理流可能提供了一系列便捷的方法来一次输入输出大批量的数据,使
用更加灵活方便
处理流 BufferedReader 和 BufferWriter
BufferedReader 和 BufferWriter 属于字符流,是按照字符来读取数据的,关闭时,只需要关闭外层流即可,最好处理的是文本文件。
BufferedReader 代码示例
package javaio.reader_;
import org.junit.jupiter.api.Test;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class BufferedReader_ {
@Test
public void bufferRead() throws IOException {
String filePath = ".\\myi.txt";
// 创建 Bufer
BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath));
// 存放每一行的读取结果
String line;
// bufferedReader.readLine() 按行读取, 如果读取到文件结尾则返回 null
while ((line = bufferedReader.readLine()) != null) {
System.out.println(line);
}
// 关闭流 调用的是 new FileReader(filePath) 这个实例
//public void close() throws IOException {
// synchronized (lock) {
// if (in == null)
// return;
// try {
// in.close();
// } finally {
// in = null;
// cb = null;
// }
// }
//}
bufferedReader.close();
}
public static void main(String[] args) {
}
}
BufferedWriter 代码示例
package javaio.writer;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class BufferedWriter_ {
public static void main(String[] args) throws IOException {
String filePath = ".\\myi__.txt";
// 创建 Bufer
// 如果是 new FileWriter(filePath, true) 表示以追加的方式写入
// 如果是 new FileWriter(filePath) 表示以覆盖的方式写入
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath, true));
bufferedWriter.write("Hello, Java");
// 插入和系统相关的一个换行符
bufferedWriter.newLine();
bufferedWriter.write("Hello, Java");
// 插入换行符
bufferedWriter.newLine();
bufferedWriter.write("Hello, Java");
bufferedWriter.newLine();
bufferedWriter.write("Hello, Java");
bufferedWriter.close();
}
}
BufferedReader 和 BufferWriter 相结合的文件复制示例
package javaio.reader_;
import java.io.*;
public class BufferedCopy_ {
public static void main(String[] args) {
//String srcFilePath = "E:\\jedis\\myi.txt";
//String destFilePath = "E:\\jedis\\myi_modified.txt";
String srcFilePath = "E:\\jedis\\copyImage.jpg";
String destFilePath = "E:\\jedis\\copyImage——————.jpg";
BufferedReader bufferedReader = null;
BufferedWriter bufferedWriter = null;
//1. BufferedReader 和 BufferedWriter 是按照字符操作的
//2. 不要去操作二进制文件[声音,视频,图片,word 文档],可能造成文件损坏
String line = "";
try {
bufferedReader = new BufferedReader(new FileReader(srcFilePath));
bufferedWriter = new BufferedWriter(new FileWriter(destFilePath));
// readLine() 读取一行内容,但是没有换行符
while ((line = bufferedReader.readLine()) != null){
// 每读取一行就写入
// 每读取一行,就写入
line = line.trim();
bufferedWriter.write(line);
// 插入换行符
bufferedWriter.newLine();
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if (bufferedReader != null){
bufferedReader.close();
}
if(bufferedWriter != null){
bufferedWriter.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
处理流 BufferedInputStream 和 BufferedOutputStream
BufferedInputStream 是字节流,在创建 BufferedInputStream 时,会创建一个内部缓冲区数组。
BufferedOutputStream 是字节流,在创建 BufferedOutputStream 时,实现缓冲的输出流,可以将多个字节写入底层的输出流中,而不必对每次字节写入调用底层系统。
图片文件拷贝示例
package javaio.reader_;
import java.io.*;
/**
* BufferedInputStream 和 BufferedOutputStream的使用
*
* 字节流既可以操作二进制文件也可以操作文本文件
*/
public class BufferedCopy02_ {
public static void main(String[] args) {
//String srcFilePath = ".\\copyImage.jpg";
//String destFilePath = ".\\kaolaxiong.jpg";
String srcFilePath = "D:\\Desktop\\对比3.psd";
String destFilePath = ".\\对比3.psd";
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
byte[] buffer = new byte[1024];
int readLen = 0;
try {
bis = new BufferedInputStream(new FileInputStream(srcFilePath));
bos = new BufferedOutputStream(new FileOutputStream(destFilePath));
// 当返回 -1 表示文件读取完毕
while ((readLen = bis.read(buffer)) != -1){
bos.write(buffer, 0 ,readLen);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 关闭外层的处理流即可,底层会关闭节点流
try {
if(bis != null){
bis.close();
}
if(bos != null){
bos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
处理流 ObjectlnputStream 和 ObjectOutputStream
有一个需求
1.将int num = 100这个int数据保存到文件中,注意不是100 数字,而是int 100,并且,能够从文件中直接恢复int 100
2.将Dog dog = new Dog(“小黄”,3)这个 dog对象保存到文件中,并且能够从文件恢复.3.上面的要求,就是能够将基本数据类型或者对象进行序列化和反序列化操作
序列化和反序列化
-
序列化就是在保存数据时,保存数据的值和数据类型
-
反序列化就是在恢复数据时,恢复数据的值和数据类型
-
需要让某个对象支持序列化机制,则必须让其类是可序列化的,为了让某个类是可序列化的,该
类必须实现如下两个接口之一:Serializable // 这是一个标记接口,没有方法
Externalizable // 该接口有两个方法需要实现
基本介绍
ObjectInputStream 类的继承结构
java.lang.Object
java.io.InputStream
java.io.ObjectInputStream

ObjectOutputStream 类的继承结构
java.lang.Object
java.io.OutputStream
java.io.ObjectOutputStream

- 功能: 提供了对基本类型或对象类型的序列化和反序列化的方法
- ObjectOutputStream 提供序列化功能
- ObjectlnputStream 提供反序列化功能
Master 类的定义
package javaio.inputstream;
import java.io.Serializable;
public class Master implements Serializable {
}
Dog 类的序列化
package javaio.inputstream;
import java.io.Serializable;
public class Dog implements Serializable {
// serialVersionUID 序列化的版本号,可以提高序列化的兼容性
public static final long serialVersionUID = 1L;
private String name;
private int age;
private Master master = new Master();
// 无法序列化 static 和 transient
private static String nation;
private transient String color;
public Dog(String name, int age, String color, String nation) {
this.name = name;
this.age = age;
this.color = color;
Dog.nation = nation;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
", color='" + color + '\'' +
", nation='" + nation + " " + master +
'}';
}
}
ObjectOutputStream 类的代码示例
package javaio.outputstream;
import javaio.inputstream.Dog;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class ObjectOutputStream_ {
public static void main(String[] args) {
// 序列化之后,保存的文本格式为二进制格式,这里的 .dat 是自己指定的
String filePath = ".\\my.dat";
ObjectOutputStream objectOutputStream = null;
try {
objectOutputStream = new ObjectOutputStream(new FileOutputStream(filePath));
objectOutputStream.writeInt(100);
objectOutputStream.writeBoolean(true);
objectOutputStream.writeChar('a');
objectOutputStream.writeDouble(9.2d);
objectOutputStream.writeUTF("Java IO 流");
Dog dog = new Dog("哈士奇", 3, "白色", "日本");
objectOutputStream.writeObject(dog);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
objectOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
ObjectInputStream 的代码举例
package javaio.inputstream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class ObjectInputStream_ {
public static void main(String[] args) throws IOException, ClassNotFoundException {
String filePath = ".\\my.dat";
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(filePath));
System.out.println(objectInputStream.readInt());
System.out.println(objectInputStream.readBoolean());
System.out.println(objectInputStream.readChar());
System.out.println(objectInputStream.readDouble());
System.out.println(objectInputStream.readUTF());
Object object = objectInputStream.readObject();
System.out.println("运行类型 : " + object.getClass());
System.out.println("真实的数据内容 : " + object);
// 1. 我们希望调用 Dog 的方法,需要向下转型
// 2. 需要我们将 Dog 类的定义,拷贝到可以引用的位置
System.out.println(((Dog) object).getName());
objectInputStream.close();
}
}
注意事项和细节说明
-
读写顺序要一致
-
要求实现序列化或反序列化对象,需要实现Serializable
-
序列化的类中建议添加 SerialVersionUID, 为了提高版本的兼容性一
public static final long serialVersionUID = 1L; -
序列化对象时,默认将里面所有属性都进行序列化,但除了static 或 transient 修饰的成员
-
序列化对象时,要求里面属性的类型也需要实现序列化接口
-
序列化具备可继承性,也就是如果某类已经实现了序列化,则它的所有子类也已经默认实现了序列化
标准输入输出流 System.in 和 System.out
| 类型 | 默认设备 | |
|---|---|---|
| System.in 标准输入 | InputStream | 键盘 |
| System.out 标准输出 | PrintStream | 显示器 |
代码举例
package javaio.standard;
import java.util.Scanner;
public class InputAndOutput {
public static void main(String[] args) {
// System 类 public final static InputStream in = null;
// System.in 编译类型 InputStream
// System.in 运行类型 BufferedInputStream
// 标准输入表示键盘
// class java.io.BufferedInputStream
System.out.println(System.in.getClass());
// System.out 编译类型 PrintStream
// System.out 运行类型 PrintStream
// class java.io.PrintStream
// System.out 表示标准输出 显示器
System.out.println(System.out.getClass());
Scanner scanner = new Scanner(System.in);
String next = scanner.next();
}
}
转换流 InputStreamReader 和 OutputStreamWriter

介绍
- InputStreamReader: Reader的子类,可以将 InputStream(字节流)包装(转换)成Reader(字符流)
- OutputStreamWriter: Writer的子类,实现将OutputStream(字节流) 包装(转换)成Writer(字符流)
- 当处理纯文本数据时,如果使用字符流效率更高,并且可以有效解决中文问题,所以建议将字节流转换成字符流
- 可以在使用时指定编码格式(比如utf-8, gbk , gb2312, ISO8859-1等)


代码举例
InputStreamReader 的代码示例
package javaio.transformation;
import java.io.*;
public class InputStreamReader_ {
public static void main(String[] args) throws IOException {
// 将字节流转换为 字符流, 注意 file3.txt 中的文件编码格式为 GBK编码
String filePath = ".\\file3.txt";
// 1. 把 FileInputStream 转成 InputStreamReader, 并指定 gbk 编码
//InputStreamReader isr = new InputStreamReader(new FileInputStream(filePath), "gbk");
// 2. 把 InputStreamReader 传入 BufferedReader
//BufferedReader bufferedReader = new BufferedReader(isr);
/**
* 将 1 和 2 写到一起
*/
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(
new FileInputStream(filePath), "gbk")
);
// 3. 读取
String line = bufferedReader.readLine();
System.out.println("读取到的内容 : " + line);
// 4. 资源释放
bufferedReader.close();
}
}
OutputStreamWriter 代码示例
package javaio.transformation;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
/**
* OutputStreamWriter 的使用
*/
public class OutputStreamWriter_ {
public static void main(String[] args) throws IOException {
// 把 FileOutputStream 字节流,转成字符流,OutputStreamWriter
// 指定处理的编码 gbk/utf-8/utf8
String filePath = ".\\gbk编码文件.txt";
//String charSet = "gbk";
String charSet = "utf-8";
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(filePath), charSet);
osw.write("Hi, Java 编程");
osw.close();
System.out.println("按照编码方式保存文件");
}
}
打印流 PrintStream 和 PrintWriter
打印流只有输出流,没有输入流

示例代码
package javaio.printstream;
import java.io.IOException;
import java.io.PrintStream;
public class PrintStream_ {
public static void main(String[] args) throws IOException {
PrintStream out = System.out;
// 在默认情况下, PrintStream 输出数据的位置是,标准数据,即显示器
//public void print(String s) {
// if (s == null) {
// s = "null";
// }
// write(s);
//}
out.print("Java EE");
// 以为 print的底层调用的是 write
out.write("Java 后端开发".getBytes());
out.close();
// 我们可以修改打印流输出的设备
// 修改到文件中
System.setOut(new PrintStream(".\\修改打印位置.txt"));
System.out.println("打印到哪里了呢?");
}
}

package javaio.printstream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
public class PrintWriter_ {
public static void main(String[] args) throws IOException {
// PrintWriter printWriter = new PrintWriter(System.out);
PrintWriter printWriter = new PrintWriter(new FileWriter(".\\printWriter.txt"));
printWriter.print("北京你好");
// 此时才会将数据写入文件中
printWriter.close();
}
}
Properties 类

有一个需求,如下一个配置文件 mysqI.properties
ip=192.168.0.13
user=root
pwd=12345
请问编程读取ip.user 和 pwd的值是多少 [实现代码见下文]
Properties 类对文件的要求
-
专门用于读写配置文件的集合类
配置文件的格式:
键 = 值
键 = 值 -
注意:键值对不需要有空格,值不需要用引号一起来。默认类型是 String
-
Properties的常见方法
-
load:加载配置文件的键值对到Properties对象
-
list:将数据显示到指定设备
-
getProperty(key):根据键获取值
-
setProperty(key, value):设置键值对到Properties对象
-
store:将Properties中的键值对存储到配置文件, 在idea中,保存信息到配置文件,如果含有中文,会存储为unicode码
http://tool.chinaz.com/tools/unicode.aspx unicode码查询工具
-
package javaio.properties;
import org.junit.jupiter.api.Test;
import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;
public class Properties_ {
@Test
public void getProperties01() throws IOException{
String filePath = ".\\mysql.properties";
BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath));
String line = "";
while ((line = bufferedReader.readLine()) != null) {
String[] split = line.split("=");
System.out.println(split[0] + " : " + split[1]);
}
}
/**
* 使用 Properties 读取 properties 文件
*/
@Test
public void getProperties02() throws IOException{
// 1. 创建 Properties 实例对象
Properties properties = new Properties();
// 2. 加载指定配置文件
properties.load(new FileReader(".\\mysql.properties"));
// 3. 把 k-v 键值对打印到控制台
properties.list(System.out);
// 4. 根据 key 获取对应的值
String user = properties.getProperty("user");
String pwd = properties.getProperty("pwd");
System.out.println("user = " + user);
System.out.println("pwd = " + pwd);
}
/**
* 使用 Properties 修改 properties 文件内容
*
* public
* class Properties extends Hashtable<Object,Object> {
*
* Properties 继承了 Hashtable
*
*
*/
@Test
public void getProperties03() throws IOException{
// 1. 创建 Properties 实例对象
Properties properties = new Properties();
// 2.如果 key 存在则是修改,没有就是添加
properties.setProperty("charset", "utf8");
properties.setProperty("user", "隔壁老王");
properties.setProperty("pwd", "fadsfdsafhdafadsj");
/**
* public synchronized V put(K key, V value) {
* // Make sure the value is not null
* if (value == null) {
* throw new NullPointerException();
* }
*
* // Makes sure the key is not already in the hashtable.
* Entry<?,?> tab[] = table;
* int hash = key.hashCode();
* int index = (hash & 0x7FFFFFFF) % tab.length;
* @SuppressWarnings("unchecked")
* Entry<K, V> entry = (Entry<K,V>)tab[index];
* for(; entry != null ; entry = entry.next) {
* if ((entry.hash == hash) && entry.key.equals(key)) {
* V old = entry.value;
* entry.value = value;
* return old;
* }
* }
*
* addEntry(hash, key, value, index);
* return null;
* }
*/
properties.store(new FileOutputStream(".\\mysql___.properties"), "首行的注释信息");
System.out.println("保存配置文件成功");
}
public static void main(String[] args) throws IOException {
}
}

被折叠的 条评论
为什么被折叠?



