Java IO流原理
1)I/O是input/Output的缩写,I/O技术是非常实用的技术,用于处理数据传输。如读/写文件,网络通讯等;
2)Java程序中,对于数据的输入和输出操作以“流(stream)”的方式进行;
3)java.io包下提供了各种“流”类和接口,用以获取不同种类的数据,并通过方法输入或输出数据;
4)输入(input):读取外部数据(磁盘、光盘等存储设备的数据到程序(内存)中);
5)输出(output):将程序(内存)数据输出到磁盘、光盘等存储设备中。
流的分类
1)按照操作数据单位不同分为:字节流(8bit),字符流(按字符)(分别按照字符和字节进行读取,如果从操作单位方面看字符流操作效率较高,但是操作二进制文件时字节流不会出现错误,字节流操作文本文件比较好);
2)按数据流的流向不同分为:输入流和输出流;
3)按流的角色不同分为:节点流,处理流(包装流);
(抽象基类) | 字节流 | 字符流 |
输入流 | 字节输入流的顶级父类 InputStream | 字符输入流的顶级父类 Reader |
输出流 | 字节输出流的顶级父类 OutputStream | 字符输出流的顶级父类 Writer |
★Java的IO流共涉及40多个类,都是从如上4个抽象基类派生的;
★由这四个基类派生出来的子类名称以其父类名作为子类名后缀;
InputStream抽象类实现了Closeable接口,Closeable接口上面还有一个AutoCloseable接口;OutputStream抽象类实现了Closeable接口和Flushable接口;Reader抽象类实现了Closeable接口和Readable接口;Writer抽象类实现了Appendable接口、Flushable接口和Closeable接口;在使用时,创建他们的实现子类。
IO流 | 字节流 | InputStream |
OutputStream | ||
字符流 | Reader | |
Writer |
InputStream | FileInputStream | |
PipedInputStream | ||
ObjectInputStream | ||
ByteArrayInputStream | ||
SequenceInputStream | ||
FilterInputStream | BufferedInputStream | |
DigestInputStream | ||
DataInputStream | ||
OutputStream | FileOutputStream | |
PipedOutputStream | ||
ObjectOutputStream | ||
ByteArrayOutputStream | ||
FilterOutputStream | BufferedOutputStream | |
DigestOutputStream | ||
DataOutputStream | ||
PrintStream | ||
Reader | InputStreamReader | FileReader |
BufferedReader | ||
CharArrayReader | ||
FilterReader | ||
PipedReader | ||
StringReader | ||
Writer | OutputStreamWriter | FileWriter |
BufferedWriter | ||
CharArrayWriter | ||
FilterWriter | ||
PipedWriter | ||
PrintWriter | ||
StringWriter |
InputStream常用子类
1)FileInputStream:文件输入流;
2)BufferedInputStream:缓冲字节输入流;
3)ObjectInputStream:对象字节输入流;
package com.pero.inputStream;
import org.junit.jupiter.api.Test;
import java.io.FileInputStream;
import java.io.IOException;
/**
* @author Pero
* @version 1.0
*/
public class FileInputStream_ {
public static void main(String[] args) {
}
@Test
//读取文件
public void test(){
//定义文件路径
String filePath = "d:\\demo\\test\\HelloWorld.txt";
//定义文件输入流对象名称
FileInputStream fileInputStream = null;
//定义接收读取一字节数据
int readData;
try {
//获取文件输入流对象,用于读取文件
fileInputStream = new FileInputStream(filePath);
while ((readData = fileInputStream.read()) != -1){ //如果返回-1表示已经读取到最后一位
System.out.print((char)readData); //读取数据为int型,需要转成字符型char
}
} catch (IOException e) {
throw new RuntimeException(e);
}finally { //必须关闭流,释放链接文件的流,否则造成资源浪费
try {
fileInputStream.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
@Test
public void test2(){
String path = "d:\\demo\\test\\HelloWorld.txt";
FileInputStream fileInputStream = null;
byte[] bytes = new byte[8];
int readLength = 0;
try {
fileInputStream = new FileInputStream(path);
//如果读取正常返回读取的字节数
while((readLength = fileInputStream.read(bytes)) != -1){
//第一次读取时,bytes第一次接收八个字符hello,wo;
// 此时fileInputStream.read(bytes)返回值为8,
//while循环不退出,输出hello,wo后,再次进入循环
// 第二次读取bytes第二次接收rld!
// 此时fileInputStream.read(bytes)返回值为4,
// (bytes中存储的为rld!o,wo,其中o,wo为上次读取的数据,bytes中没有将其覆盖)
//但是new String(bytes, 0, readLength)输出bytes数组的0~3(0~readLength-1)位的字符
//第三次读取,读取到数据的最后一位,此时fileInputStream.read(bytes)返回值为-1退出循环
System.out.print(new String(bytes,0,readLength));
}
} catch (IOException e) {
throw new RuntimeException(e);
}finally {
try {
fileInputStream.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
OutputStream常用子类
1)FileOutputStream:文件输出流。
package com.pero.outputStream_;
import org.junit.jupiter.api.Test;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
/**
* @author Pero
* @version 1.0
*/
public class FileOutputStream_ {
public static void main(String[] args) {
}
@Test
public void writeFile(){
String path = "d:\\demo\\test\\next.txt";
FileOutputStream fileOutputStream = null;
try {
//fileOutputStream = new FileOutputStream(path);以此方式创建输出流
//输出文件内容会覆盖原来的内容
//fileOutputStream = new FileOutputStream(path,true);以此方式创建输出流
//输出文件内容会添加到原来的内容之后
fileOutputStream = new FileOutputStream(path,true);
//写入一个字节
//fileOutputStream.write('H');
//写入字符串
String str = "Hello,world!";
//使用getBytes,将字符串转成字节(byte)数组
fileOutputStream.write(str.getBytes());
//写入字符串部分数据Hello(0~5-1)
fileOutputStream.write(str.getBytes(),0,5);
} catch (IOException e) {
throw new RuntimeException(e);
}finally {
try {
fileOutputStream.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
文件拷贝(图像)
package com.pero.outputStream_;
import org.junit.jupiter.api.Test;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* @author Pero
* @version 1.0
*/
public class FileCopy {
public static void main(String[] args) {
}
@Test
public void copy(){
//大文件读取中,边读取数据边输出存放文件(流的形式)
//将地址所在文件数据输入到程序
//输入、输出路径
String inputPath = "C:\\Users\\Pero\\Desktop\\4.jpeg";
//将文件数据输出到指定地址存放
String outputPath = "D:\\demo\\test\\4.jpeg";
FileInputStream fileInputStream = null;
FileOutputStream fileOutputStream = null;
byte[] bytes = new byte[1024]; //饱和读取数量
int readLength = 0;
try {
fileInputStream = new FileInputStream(inputPath);
fileOutputStream = new FileOutputStream(outputPath);
//读取文件数据
while ((readLength = fileInputStream.read(bytes)) != -1){
//边读边写,一定要用write(bytes,0,readLength);
//因为最后一次读写,不一定把bytes里的存储数据完全覆盖,
//最后剩余的空间是倒数第二次传输的部分数据,会发生错误
fileOutputStream.write(bytes,0,readLength);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
finally {
try {
if (fileInputStream != null){
fileInputStream.close();
}
if (fileOutputStream != null){
fileOutputStream.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
FileReader类和FileWriter类(字符流,按照字符来操作IO)
FileReader相关方法
1)构造器:new FileReader(File/String)
2)read:每次读取单个字符,则返回该字符,如果到了文件末尾则返回-1;
3)read(char[]):批量读取多个字符到数组,返回读取到的字符数,如果到了文件末尾则返回-1;
相关API:
1)new String(char[] ):将char[]转换阿成String;
2)new String(char[] ,off ,len):将char[]的指定部分转换成String。
package com.pero.reader_;
import org.junit.jupiter.api.Test;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
/**
* @author Pero
* @version 1.0
*/
public class FileReader_ {
public static void main(String[] args) {
}
@Test
public void reader(){
//创建路径
String path = "d:\\demo\\test\\Story.txt";
FileReader fileReader = null;
int data = 0;
//char[] chars = new char[1024];
try {
fileReader = new FileReader(path);
//循环读取
while ((data = fileReader.read()) != -1){
System.out.print((char)data);
}
} catch (IOException e) {
throw new RuntimeException(e);
}finally {
try {
if (fileReader != null){
fileReader.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
@Test
public void reader1(){
String path = "d:\\demo\\test\\Story.txt";
char[] chars = new char[1024];
int length = 0;
FileReader fileReader = null;
try {
fileReader = new FileReader(path);
while ((length = fileReader.read(chars)) != -1){
System.out.print(new String(chars,0,length));
}
} catch (IOException e) {
throw new RuntimeException(e);
}finally {
try {
if (fileReader != null){
fileReader.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
FileWriter相关方法
1)构造器:new FileWriter(File/String):覆盖模式,相当于流的指针在首端;
2)构造器:new FileWriter(File/String,true):追加模式,相当于流的指针在尾端;
3)write(int ):写入单个字符;
4)write(char[]):写入指定数组;
5)write(char[],off,len):写入指定数组的指定部分;
6)write(String):写入整个字符串;
7)write(String,off,len):写入字符串的指定部分。
相关API:String类中toCharArray:将String转换成char[]。
★注意:FileWriter使用后,必须要关闭(close)或刷新(flush),否则写入不到指定的文件。
package com.pero.writer_;
import org.junit.jupiter.api.Test;
import java.io.FileWriter;
import java.io.IOException;
/**
* @author Pero
* @version 1.0
*/
public class FileWriter_ {
public static void main(String[] args) {
}
@Test
public void writer(){
String path = "d:\\demo\\test\\note.txt";
FileWriter fileWriter = null;
char[] chars = {'H','e','l','l','o',',','H','o','r','l','d','!'};
try {
fileWriter = new FileWriter(path/*,true*/);
fileWriter.write('h');
fileWriter.write(chars);
fileWriter.write("不经历风雨,怎能见彩虹");
fileWriter.write("锄禾日当午,汗滴禾下土",0,5);
fileWriter.write(chars,0,5);
} catch (IOException e) {
throw new RuntimeException(e);
}finally {
try {
fileWriter.close();
//fileWriter.flush();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}