Java I/O系统概述
-
什么是流?
流是Java I/O的基础。
当程序需要 写入数据 的时候,就会开启一个通向目的地设备的流。这时候我们就可以想象数据好像在这其中“流”动一样。
流的两个最基本的特性:一是它含有 流质 ,二是它有 方向 。 -
流的分类:
-
按方向分:
输入流: 从数据源读取数据到程序中。只能从中读取数据,而不能向其写入数据。
(io包中的输入流都继承自抽象类InputStream或Reader)输入流:从数据源读取数据到程序中。只能从中读取数据,而不能向其写入数据。 (io包中的输入流都继承自抽象类InputStream或Reader)
输出流: 将数据从程序写入数据目的地。只能从中写入数据,而不能从中读取数据。
(io包中的输出流都继承自抽象类OutputStream或Writer) -
按照处理数据的最小单位分:
字节流: 字节流是以byte为最小单位进行数据传送。(io包中的字节流都继承自抽象类InputStream或OutputStream。)
字符流: 字符流是以char为最小单位进行数据传送。(io包中的字符流都继承自抽象类Reader或者Writer。) -
按照流的功能分:
节点流: 节点流是可以直接从/向一个特定的数据源(例如磁盘文件、内存、网络)读/写数据的流。节点流也称低级流。
处理流: 处理流不直接连接到设备,而是连接在已存在的流(节点流或处理流)之上,通过对数据的处理为程序提供更强大的读写功能。处理流也称高级流。
-
-
所有的IO操作都由以下步骤构成:
- 建立流。根据数据源和具体的操作(是读取还是写入)选择流,然后建立流。通过流的建立,创建内存到数据源之间的数据通道,以传输数据。
- 操作流。将数据读取到内存,或将内存中的数据写入数据源。
- 关闭流。流操作结束后,释放所有与该流相关联的系统资源。
文件类
java.io包中的File类提供了管理磁盘文件和目录的基本功能。我们可以将一个File对象看成是代表一个文件或目录的名称和位置的字符串。File类有四个构造方法:
- public File(String pathname)。创建一个与指定路径名关联的File对象。
- public File(String parent, String child)。使用指定参数创建一个File对象。参数parent代表一个目录,参数child代表在parent中的子目录或文件。
- public File(File parent, String child)。与上一个构造器相同,除了目录是用一个File对象而不是一个字符串来表示。
- public File(URI uri)。使用给定的java.net.URI对象创建一个File对象。URI是统一资源标识符,一个文件的URI是“file:///目录/文件名”格式。
方法 | 描述 |
---|---|
boolean canWrite() | 判断文件是否可写 |
boolean canRead() | 判断文件是否可读 |
boolean createNewFile() | 创建一个新文件 |
boolean delete() | 删除文件对象代表的文件或目录。删除目录时必须保证此目录为空,否则无法删除 |
boolean exists() | 判断文件或目录是否存在 |
String getAbsolutePath() | 获得文件绝对路径 |
boolean isFile() | 判断是否是文件 |
boolean isDirectory() | 判断是否是目录 |
long lastModified() | 获得文件最后一次修改时间 |
long length() | 得到文件长度 |
String[] list() | 返回包含目录中所含文件的文件名的字符串数组 |
File[] listFiles() | 返回该目录中java.io.File对象数组 |
boolean mkdir() | 创建目录 |
字节流
低级字节流
字节流中的主要低级流,根据其输入和输出的设备或数据源,分为三类:
- 对二进制文件进行读写操作的FileInputStream和FileOutputStream类,其数据源是磁盘文件。
- 对内存缓冲区中的字节数组进行读写操作的ByteArrayInputStream和ByteArrayOutputStream类,其数据源是内存中的字节数组。
- 对线程管道进行读写操作的PipedInputStream和PipedOutputStream类,其数据源是线程管道。
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
String fromPath = "C:" + File.separatorChar +"1" + File.separatorChar + "MainEnter.java";
File file = new File(fromPath);
String toPath = "C:" + File.separatorChar +"2" + File.separatorChar + "MainEnter.java";
File file02 = new File(toPath);
//判断文件是否存在
if(file.exists()) {
//无论文件是什么类型的文件,都可以采用字节流
//推荐:对于字节码文件,或者图片,或音频,视频等等文件,我们读取时,一般采用字节流
//而文本文件,采用字符流
FileInputStream in = null;
FileOutputStream out = null;
byte[] data = new byte[1024];//定义一个数据缓冲区
try {
in = new FileInputStream(file);//针对该文件,创建一个对应字节输入流
int lenth = 0;//代表单次读取内容的长度
while((lenth = in.read(data)) != -1) {
out.write(data,0,lenth);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {//关流
try {
in.close();
out.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
高级字节流
高级字节流对低级字节流进行了封装,并有许多功能的扩展。高级字节流根据其功能分为三大类:
- 过滤流类: 过滤流类提供了额外的功能,在将数据实际写入到输出流之前对输出进行预处理,或者在读取数据之后对输入进行后期处理。过滤流类都是抽象类FilterInputStream 和 FilterOutputStream的子类。
- 缓冲流:包括BufferedInputStream 和 BufferedOutputStream,这两个类实现了带缓冲的过滤流。
- 数据流:包括DataInputStream 和 DataOutputStream,可以用与计算机无关的格式读写Java的基本数据类型以及String对象。
- 计数:包括LineNumberInputStream类,允许在翻译行结束符的基础上,维护一个计数器,该计数器表明正在读取的是哪一行。
- 推回输入流:包括PushbackInputStream类,代表一个流允许从流中读取数据,然后在需要时推回该流。
- 打印输出流:包括PrintStream类,允许将基本类型数据打印输出到字符串流中,带有自动刷新功能。
- 对象流: 包括ObjectInputStream和ObjectOutputStream,允许直接对对象执行读写操作。
- 合并: SequenceInputStream类可以实现两个文件的合并操作,它从两个低级流中读取数据字节,当到达流的末尾时从一个流转到另一个流 ,从而实现合并操作。
高级字节流之—缓冲流:
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
String fromPath = "C:" + File.separatorChar + "1" + File.separatorChar + "MainEnter.java";
File file = new File(fromPath);
String toPath = "C:" + File.separatorChar + "2" + File.separatorChar + "MainEnter.java";
File file02 = new File(toPath);
// 判断文件是否存在
if (file.exists()) {
// 定义低级流
FileInputStream in = null;
FileOutputStream out = null;
// 定义高级流
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
// 实例化低级流
in = new FileInputStream(file);
out = new FileOutputStream(file02);
// 实例化高级流
bis = new BufferedInputStream(in);
bos = new BufferedOutputStream(out);
// 读写文件
byte[] data = new byte[1024];
int lenth = 0;
while ((lenth = bis.read(data)) != -1) {
bos.write(data, 0, lenth);
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
} finally {
try {
bos.flush();// 向文件中,写入数据
in.close();
out.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
高级字节流之数据流:
数据输入流允许应用程序以与机器无关方式,从底层输入流中读取 Java 基本数据类型,与机器无关的方式,就是用JAVA的方式
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
String[] names = { "张帅", "徐帅", "袁帅", "胡帅", "帅胡" };// 名字
int[] age = { 20, 18, 29, 19, 91 };// 年龄
boolean[] marry = { true, false, true, true, false };// 结没结婚
// 将上面的这些数据,写入到文件中
String fromPath = "C:" + File.separatorChar + "2" + File.separatorChar + "Person";
File file = new File(fromPath);
if (!file.exists())// 没有文件,就创建一个文件
try {
file.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 定义低级输出流
FileOutputStream out = null;
// 定义高级数据流
DataOutputStream dos = null;
try {
// 实例化
out = new FileOutputStream(file);
dos = new DataOutputStream(out);
int lenth = names.length;
for (int i = 0; i < lenth; i++) {
dos.writeUTF(names[i]);// 以与机器无关方式使用 UTF-8 修改版编码将一个字符串写入基础输出流。
dos.writeInt(age[i]);
dos.writeBoolean(marry[i]);
}
System.out.println("我瑟吉欧椎间盘公共IP热门");
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
} finally {
try {
out.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// ----------------------------------------
// 使用高级数据流,读取内容
// ----------------------------------------
// 定义低级输入流
FileInputStream in = null;
// 定义高级数据流
DataInputStream dis = null;
try {
in = new FileInputStream(file);
dis = new DataInputStream(in);
while(true) {
System.out.println(dis.readUTF());
System.out.println(dis.readInt());
System.out.println(dis.readBoolean());
}
} catch (Exception e) {
// TODO: handle exception
// e.printStackTrace();
}finally {
try {
in.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
打印输出流:
使用字节打印输出流 ,去格式化文本文件的内容,可以让我们输出到文件中的内容,以操作系统默认的字符编码集进行编码显示
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
String[] names = { "张帅", "徐帅", "袁帅", "胡帅", "帅胡" };// 名字
int[] age = { 20, 18, 29, 19, 91 };// 年龄
boolean[] marry = { true, false, true, true, false };// 结没结婚
// 将上面的这些数据,写入到文件中
String fromPath = "C:" + File.separatorChar + "2" + File.separatorChar + "Person.txt";
File file = new File(fromPath);
if (!file.exists())// 没有文件,就创建一个文件
try {
file.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 定义低级输出流
FileOutputStream out = null;
// 定义高级字节打印输出流
/**
* PrintStream 在进行输出,采用操作系统的默认字符编码集,来进行输出
*/
PrintStream ps = null;
try {
// 实例化
out = new FileOutputStream(file);
ps = new PrintStream(out);
int lenth = names.length;
for(int i = 0; i < lenth; i ++) {
ps.print(names[i] +" ");
ps.print(age[i] +" ");
ps.print(marry[i] +" ");
ps.println();
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
} finally {
try {
out.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
对象流:
public class StudentBean implements Serializable{
*/
private static final long serialVersionUID = 5453124311904581252L;
/**
* 数据的唯一标识
*/
private String id;
/**
* 学生名字
*/
private String stuName;
/**
* 学生年龄
*/
private int age;
/**
* 学生性别(0-女,1-男,-1 不男不女)
*/
private int gender;
/**
* 学生学号
*/
private String stuNo;
/**自行添加下面内容:
*无参构造
*get/set方法
*toString方法
*/
}
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
String fromPath = "C:" + File.separatorChar + "2" + File.separatorChar + "students.data";
File file = new File(fromPath);
if(file.exists()) {
//定义低级字节流
FileInputStream in = null;
//定义高级对象输入流
ObjectInputStream ois = null;
try {
//实例化
in = new FileInputStream(file);
ois = new ObjectInputStream(in);
//从文件中读取多个JAVA对象
Object obj = null;
while((obj = ois.readObject()) != null) {
if(obj instanceof StudentBean) {
StudentBean stu = (StudentBean) obj;
System.out.println(stu);
}
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}finally {
try {
in.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
字符流
低级字符流
字符流中的低级流包括:
- 对内存数组进行操作的CharArrayReader和CharArrayWriter类,与ByteArrayInputStream和ByteArrayOutputStream类似,其数据源为内存中的字符数组。
- 对内存中的String对象进行操作的StringReader和StringWriter类,其数据源为内存中的String对象。
- 对线程管道进行操作的PipedReader和PipedWriter类,与PipedInputStream和PipedOutputStream类似,其数据源为线程管道。
- 对文本文件进行读写操作的FileReader和FileWriter类,与FileInputStream和FileOutputStream类似,其数据源为磁盘文件。FileReader和FileWriter按照本地操作系统平台的默认字符编码,读写文件。
低级字符流:
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
//文本文件,适合使用字符流来读取、写入
String fromPath = "C:" + File.separatorChar +"1" + File.separatorChar + "MainEnter.java";
File file = new File(fromPath);
String toPath = "C:" + File.separatorChar +"2" + File.separatorChar + "MainEnter.java";
File file02 = new File(toPath);
//判断文件是否存在
if(file.exists()) {
//声明字符输入流,字符输出流
FileReader r = null;
FileWriter w = null;
try {
//实例化字符流入流,和字符输出流
r = new FileReader(file);
w = new FileWriter(file02);
char[] data = new char[1024];
int lenth = 0;
while((lenth = r.read(data)) != -1) {
w.write(data, 0, lenth);
System.out.println(Arrays.toString(data));
}
} catch (IOException e) {
// TODO: handle exception
e.printStackTrace();
}finally {
try {
r.close();
w.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
高级字符流
字符流中常用的高级流包括:
- 缓冲流:包括BufferedReader和BufferedWriter类,利用缓冲区来提高读写数据的效率。
- 转换流:用于字节数据到字符数据之间的转换,包括InputStreamReader和OutputStreamWriter。
- 打印输出流:包括PrintWriter类,允许将基本类型数据打印输出到字符串流中,PrintWriter带有带自动刷新(Flush)功能。