JavaSE IO原理及流的引入(上)
-
IO流用来处理设备之间的数据传输。
-
Java中,对于数据的输入/输出操作以“流(Stream)”的方式进行。
-
java.io包下提供了各种“流”类和接口,用来获取不同种类的数据,并通过标准的方法输入或输出数据。
Java IO原理
输入input: 读取外部数据(磁盘、光盘等存储设备的数据)到程序内存中。
**输出output:**将程序(内存)数据输出到磁盘、光盘等存储设备中
流的分类
按照操作数据单位不同分为:字节流(8bit),字符流(16bit)
按照数据流的流向不同分为:输入流、输出流
按照流的角色不同分为:结点流、处理流
抽象基类 | 字节流 | 字符流 |
---|---|---|
输入流 | InputStream | Reader |
输出流 | OutputStream | Writer |
1 文件流
1.1 文件字节流
-
文件字节输入流
FileInputStream in = new FileInputStream("file");
重点关注
int read(byte[] b)
的使用 -
文件字节输出流
FileOutputStream out = new FileOutputStream("file")
重点关注
out.write(str.getBytes())
、out.flush()
的使用
注意:字节流使用完毕后一定要关闭。
文件输入输出流案例:
package com.io;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Demo02 {
public static void main(String[] args) {
testFileInputStream();
testFileOutputStream();
}
//文件字节输入流
public static void testFileInputStream(){
try {
FileInputStream in = new FileInputStream("/Users/demut/Documents/File/aaa.txt");
byte[] b = new byte[100]; //设置一个byte数组接受读取的文件内容
int len = 0;//设置一个读取数据的长度
// in.read(b);//读取字符到b数组,返回读取到的字符个数,如果是文件结尾返回-1
while((len = in.read(b)) != -1){
System.out.println(new String(b,0,len));
//new String(b,0,len)表示从0开始读取,总共转换len个字节
}
in.close();//流在使用完毕之后一定要关闭
} catch (IOException e) {
e.printStackTrace();
}
}
//文件字节输出流
public static void testFileOutputStream(){
try {
FileOutputStream out = new FileOutputStream("/Users/demut/Documents/File/aaa.txt");
String str = "aaaaaabbbbbbbccc";
out.write(str.getBytes());//把数据写入内存
out.flush(); //将内存中的数据刷写到硬盘上
out.close();//关闭流
} catch (IOException e) {
e.printStackTrace();
}
}
}
复制文件到指定文件/文件夹案例:
package com.io;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
//复制文件到指定文件夹下
public class Demo03 {
public static void main(String[] args) {
//将aaa.txt中内容写入到tt1.txt文件中
copyFile("/Users/demut/Documents/File/aaa.txt","/Users/demut/Documents/File/tt1.txt");
}
public static void copyFile(String inPath, String outPath){
try {
FileInputStream in = new FileInputStream(inPath);
FileOutputStream out = new FileOutputStream(outPath);
byte[] b = new byte[100];
int len = 0;
while ((len = in.read(b)) != -1){
out.write(b, 0, len); //b表示缓冲数组,0表示从数组的位置开始写,len表示获取的数组总长度
}
out.flush();
out.close();
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
结果展示:(写入成功!)
运行前:
运行后:
注意: 文件字节流非常通用,可以用来操作字符的文档,还可以操作任何的其他类型文件(图片,压缩包等),因为字节流直接使用二进制。
1.2 文件字符流
-
文件字符输入流
读取文件操作步骤:
-
建立一个流对象,将已存在的一个文件加载进流。
FileReader fr = FileReader("Test.txt");
-
创建一个临时存放数据的数组。
char[] ch = new char[1024];
-
调用流对象的读取方法将流中的数据读入到数组中。
fr.read(ch)
-
-
文件字符输出流
数据写入文件操作步骤:
-
建立一个流对象,将已存在/不存在的一个文件加载进流。
FileWriter fw = FileWriter("Test.txt");
-
将读取到的字符数组/字符串/数字写入内存中。
fw.write(text);
-
把内存中数据刷到硬盘中,即写入文件。
fw.flush();
-
注意: 无论是输入流/输出流,使用完毕一定要关闭流。
文件字符输入&&输出流案例:
package com.io;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class Test4 {
public static void main(String[] args) {
File file = new File("/Users/demut/Documents/File/ttt.txt");
testFileReader(file.toString()); //读取原文件中字符串
testFileWriter("HelloWorld",file.toString()); //写入新的字符串到文件中
testFileReader(file.toString()); //读取更改后文件内部的字符串
}
/**
* 文件字符输入流
* @param inPath 读取的文件
*/
public static void testFileReader(String inPath){
try {
FileReader fr = new FileReader(inPath);//创建文件字符输入流的对象
char[] c = new char[10]; //创建临时存放数据的数组-->一次最多存放10个
int len = 0; //定义一个输入流的读取长度
while ((len = fr.read(c)) != -1){
System.out.println(new String(c, 0, len));
}
fr.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 文件字符输出流FileWriter
* @param text 输出的内容
* @param outPath 输出的文件
*/
public static void testFileWriter(String text, String outPath){
try {
FileWriter fw = new FileWriter(outPath);
fw.write(text); //写到内存中
fw.flush(); //把内存数据刷到硬盘中
fw.close(); //关闭流
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行结果:
更改前:
更改后:
使用字符流拷贝文件到指定文件案例:
package com.io;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class Test4 {
public static void main(String[] args) {
copyFile("/Users/demut/Documents/File/ttt.txt",
"/Users/demut/Documents/File/aaa/ttt1.txt");
}
/**
* 字符流完成拷贝文件,字符流只适合操作内容是字符的文件
* @param inPath
* @param outPath
*/
public static void copyFile(String inPath, String outPath){
try {
FileReader fr = new FileReader(inPath);
FileWriter fw = new FileWriter(outPath);
char[] c = new char[1024];
int len = 0;
while ((len = fr.read(c)) != -1){ //读取数据
fw.write(c,0,len); //写入数据到内存中
}
fw.flush(); //内存数据刷新到硬盘
fw.close();
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行结果:
运行前:
运行后:
注意:
- 字符流只适合操作内容是字符的文件!
- 在写入一个文件时,如果目录下有同名文件将被覆盖。
- 在读取文件时,必须保证文件存在,否则会异常。
2 缓冲流(基于内存的操作)
我们之前提到的文件流:FileInputStream, FileOutputStream,FileReader, FileWrite
这些都是计算机与硬盘之间发生的io操作,基于硬盘的读写相对不较慢,这个操作的速度收到硬盘的读写速度制约,为了能够提高读写速度,一定程度上绕过硬盘的限制,java提供了缓冲流来实现。
为了提高数据读写的速度,JavaAPI提供了带缓冲功能的流类,在使用这些流类时,会创建一个内部缓冲区数组。
缓冲流就是先把数据缓冲到内存中,在内存中去做io操作,基于内存的io操作比基于硬盘的io操作快75000多倍。
2.1 缓冲字节流
使用与文件字符流使用相像,但是声明过程为以下:
-
缓冲字节输入流:
FileInputStream in = new FileInputStream("...");
BufferedInputStream br = new BufferedInputStream(in);
-
缓冲字节输出流
FileOutputStream out = new FileOutputStream("...");
BufferedOutputStream bo = new BufferedOutputStream(out)
案例展示:(本案例展示缓冲字节输入、输出流及拷贝文件的操作)
package com.io;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class Test5 {
public static void main(String[] args) throws Exception {
testBufferedInputStream();
testBufferedOutputStream();
copyFile();
}
/**
* 缓冲字节输入流
* @throws Exception
*/
public static void testBufferedInputStream() throws Exception{
//文件字节输入流对象
FileInputStream in = new FileInputStream("/Users/demut/JAVASE Project" +
"/JavaSE/基础语法/src/com/io/aaa.txt");
//把文件字节输入流放到缓冲字节输入流对象
BufferedInputStream br = new BufferedInputStream(in);
byte[] b = new byte[10];
int len = 0;
while ((len = br.read(b)) != -1){
System.out.println(new String(b,0,len));//将比特数组转换为字符串
}
//关闭流的时候顺序要求:后开的流先关闭
br.close();
in.close();
}
/**
* 缓冲字节输出流
* @throws Exception
*/
public static void testBufferedOutputStream() throws Exception{
//创建字节输出流对象
FileOutputStream out = new FileOutputStream("/Users/demut/JAVASE Project" +
"/JavaSE/基础语法/src/com/io/aaa.txt");
//把字节输出流对象放到缓冲字节输出流中
BufferedOutputStream bo = new BufferedOutputStream(out);
String str = "Hello World";
bo.write(str.getBytes()); //写入内存中
bo.flush(); //内存中数据刷到硬盘上
bo.close(); //关闭流
out.close(); //关闭流
}
/**
* 拷贝文件
* @throws Exception
*/
public static void copyFile() throws Exception{
//缓冲输入流
BufferedInputStream br = new BufferedInputStream(new FileInputStream("/Users/demut/JAVASE Project" +
"/JavaSE/基础语法/src/com/io/aaa.txt"));
//缓冲输出流
BufferedOutputStream bo = new BufferedOutputStream(new FileOutputStream("/Users/demut/JAVASE Project" +
"/JavaSE/基础语法/src/com/io/bbb.txt"));
byte[] b = new byte[1024];
int len = 0; //len接受读取到的数据的长度,直到读取到最后(返回-1)
while ((len = br.read(b)) != -1){
bo.write(b,0,len); //数据写入内存中
}
bo.flush(); //数据从内存刷新到硬盘中
bo.close();
br.close();
}
}
结果展示:(仅展示拷贝文件结果)
程序运行前:
程序运行后:
2.2 缓冲字符流
同样与上述使用十分相似,注意声明语句如下:
-
缓冲字符输入流:
FileReader fr = new FileReader("...");
BufferedReader br = new BufferedReader(fr);
-
缓冲字节输出流
FileWriter fw = new FileWriter("...");
BufferedWriter bw = new BufferedWriter(fw)
案例展示:(本案例展示缓冲字符输入、输出流及拷贝文件的操作)
package com.io;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
/**
* 缓冲字符流
*/
public class Test6 {
public static void main(String[] args) throws Exception{
//testBufferedReader();
//testBufferedWriter();
copyFile();
}
/**
* 缓冲字符输入流
* BufferedReader
* @throws Exception
*/
public static void testBufferedReader() throws Exception{
FileReader fr = new FileReader("/Users/demut/JAVASE Project/JavaSE/基础语法/src/com/io/aaa.txt");
BufferedReader br = new BufferedReader(fr);
char[] c = new char[100];
int len = 0;
while ((len = br.read(c))!=-1){
System.out.println(new String(c,0,len));
}
br.close();
fr.close();
}
/**
* 缓冲字符输出流
* BufferedWriter
* @throws Exception
*/
public static void testBufferedWriter() throws Exception{
FileWriter fw = new FileWriter("/Users/demut/JAVASE Project/JavaSE/基础语法/src/com/io/bbb.txt");
BufferedWriter bw = new BufferedWriter(fw);
String str = "JeverDemut";
bw.write(str); //写入内存
bw.flush(); //刷入硬盘
bw.close();
fw.close();
}
/**
* 使用缓冲字符流拷贝文件
* @throws Exception
*/
public static void copyFile() throws Exception{
BufferedReader br = new BufferedReader(new FileReader("/Users/demut/JAVASE Project/JavaSE/基础语法/src/com/io/bbb.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("/Users/demut/JAVASE Project/JavaSE/基础语法/src/com/io/ccc.txt"));
char[] c = new char[100];
int len = 0;
while ((len = br.read(c))!=-1){
bw.write(c,0,len);
}
bw.flush();
bw.close();
br.close();
}
}
结果展示:(仅展示拷贝文件结果)
程序运行前:
程序运行后:
注意:缓冲流是把数据缓冲到内存中。
**JavaSE IO原理及流的引入(下)**重点介绍以下流:
转换流、打印流(了解)、数据流(了解)、对象流 —涉及序列化、反序列化、随机存取文件流