从数据传输方式或者说是运输方式角度看,可以将 IO 类分为:
字节流
字符流
io类型 | 特点 |
---|---|
字节流 | 字节流是字节读写;可以读取各种类型的文件可以是二进制文件,可以是音频,可以是各种各样的类型,只要符合字节形式存储的都可以接字节流 |
字符流 | 字符流是块读写,有缓存,适用与字符类文件 |
Java IO流对象
1 输入字节流 InputStream
从IO中输入字节流的继承图中可以看出。
1)InputStream是所有数据字节流的父类,它是一个抽象类。
2)ByteArrayInputStream、StringBufferInputStream、FileInputStream是三种基本的介质流,它们分别从Byte数组、StringBuffer、和本地文件中读取数据,PipedInputStream是从与其他线程共用的管道中读取数据。
3)ObjectInputStream和所有FileInputStream 的子类都是装饰流(装饰器模式的主角)。
2、输出字节流 OutputStream
从IO中输入字节流的继承图中可以看出。
1)OutputStream是所有输出字节流的父类,它是一个抽象类。
2)ByteArrayOutputStream、FIleOutputStream是两种基本的介质,它们分别向Byte 数组,和本地文件中写入数据。PipedOutputStream是从与其他线程共用的管道中写入数据。
3)ObjectOutputStream和所有FileOutputStream的子类都是装饰流。
3、字符输入流Reader
1、Reader是所有的输入字符流的父类,它是一个抽象类。
2、CharReader、StringReader 是两种基本的介质流,它们分别将Char数组、String中读取数据。PipedInputReader 是从与其他线程共用的管道中读取数据。
3、BuffereReader 很明显的是一个装饰器,它和其子类复制装饰其他Reader对象。
4、FilterReader 是所有自定义具体装饰流的父类,其子类PushbackReader 对Reader 对象进行装饰,回增加一个行号。
5、InputStreamReader 是一个连接字节流和字符流的桥梁,它将字节流转变为字符流。FileReader 可以说是一个达到此功能、常用的工具类,在其源代码中明显使用了将FileInputStream转变为Reader 的方法。我们可以从这个类中得到一定的技巧。Reader 中各个类的用途和使用方法基本和InputStream 中的类使用一致。
4、字符输入流Writer
在上面的关系图中可以看出:
1、Writer 是所有输出字符流的父类,它是一个抽象类。
2、CharArrayWriter、StringWriter 是两种基本的介质流,它们分别向Char 数组、String 中写入数据。PipedInputWriter 是从与其他线程共用的管道中读取数据。
3、BuffereWriter 很明显是一个装饰器,他和其子类复制装饰其他Reader对象。
4、FilterWriter 和PrintStream 及其类似,功能和使用也非常相似。
5、OutputStreamWriter 是OutputStream 到Writer 转换到桥梁,它的子类FileWriter 其实就是一个实现此功能的具体类(具体可以研究一下SourceCode)。功能和使用OutputStream极其类似。
5 、使用说明
5.1 字节流
- FileInputStream/FileOutputStream(文件copy)
package com.example.netty.io;
import java.io.*;
public class FileStreamEq {
public static void main(String[] args) throws IOException {
InputStream is=null;
OutputStream os=null;
try{
is=new FileInputStream("C:\\Users\\Admin\\Desktop\\test1.txt");
os=new FileOutputStream("C:\\Users\\Admin\\Desktop\\test2.txt");
int temp=-1;
byte[] data=new byte[1024];
while((temp=is.read(data))!=-1){
os.write(data,0,temp);
}
}catch (FileNotFoundException e){
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
}finally{
os.close();
is.close();
}
}
}
- ByteArrayOutputStream/ByteArrayInputStream
package com.example.netty.io;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
public class ByteStreamEq {
public static void main(String args[])throws IOException {
ByteArrayOutputStream bOutput = new ByteArrayOutputStream(12);
while( bOutput.size()!= 10 ) {
// 获取用户输入值
bOutput.write(System.in.read());
}
byte b [] = bOutput.toByteArray();
System.out.println("Print the content");
for(int x= 0 ; x < b.length; x++) {
// 打印字符
System.out.print((char)b[x] + " ");
}
int c;
ByteArrayInputStream bInput = new ByteArrayInputStream(b);
System.out.println("Converting characters to Upper case " );
for(int y = 0 ; y < 1; y++ ) {
while(( c= bInput.read())!= -1) {
System.out.println(Character.toUpperCase((char)c));
}
bInput.reset();
}
}
}
- FilterOutputStream/FilterInputStream
3.1 DataInputStream /DataOutputStream (装饰其他字节流,允许底层输入流中读取基本 Java 数据类型”)
package com.example.netty.io.Filter;
import java.io.*;
public class DateStreamEq {
public static void main(String[] args) {
try {
write();
read();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void read() throws IOException {
try(DataInputStream dis = new DataInputStream(new FileInputStream("C:\\Users\\Admin\\Desktop\\test1.txt"))) {
byte a = dis.readByte();
int b = dis.readInt();
char c = dis.readChar();
float d = dis.readFloat();
System.out.println(a);
System.out.println(b);
System.out.println(c);
System.out.println(d);
}
}
public static void write() throws IOException {
try( DataOutputStream dos = new DataOutputStream(new FileOutputStream("C:\\Users\\Admin\\Desktop\\test1.txt"))) {
dos.writeByte(123);
dos.writeInt(123);
dos.writeChar('a');
dos.writeFloat(123.123f);
}
}
}
3.2 Objectinputstream/ObjectOutputstream (装饰其他字节流,允许底层输入流中读取基本 Java 数据类型和对象)
package com.example.netty.io;
import java.io.*;
import java.util.HashMap;
import java.util.Map;
public class ObjectStreamEq {
public static void main(String[] args) throws Exception{
ser();//序列化
dser();//反序列化
}
public static void ser() throws Exception{//序列化操作
File f = new File("D:" + File.separator + "test.txt");
try(OutputStream out = new FileOutputStream(f); ObjectOutputStream oos =new ObjectOutputStream(out)){
Map map=new HashMap<>();
map.put("java",40);
oos.writeObject(map);
}
}
public static void dser() throws Exception{//反序列化操作
File f = new File("D:" + File.separator + "test.txt");
try(InputStream input = new FileInputStream(f); ObjectInputStream ois = new ObjectInputStream(input)) {
Object obj = ois.readObject();//读取对象
System.out.println(obj);
}
}
}
3.3 BufferedInputStream/BufferedOutputStream(装饰其他字节流,允许底层输入流中读取字节)
package com.example.netty.io.Filter;
import java.io.*;
public class BufferedStream {
public static void main(String[] args) throws IOException {
//创建字节缓冲流对象,参数传入文件输入输出流对象
//真正的读写依旧是字节流(文件输入输出流)
//缓冲流使读写过程提速
try(BufferedInputStream bis = new BufferedInputStream(new FileInputStream("C:\\Users\\Admin\\Desktop\\test1.txt"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("C:\\Users\\Admin\\Desktop\\test2.txt"));) {
//字节缓冲流在底层实际上也是创建了字节数组(该数组的长度为8192)
/*在底层(数据源硬盘到内存再到目标硬盘)
read()从数据源硬盘直接读取8192个字节,存储到内存中的字节缓冲输入流创建的字节数组中
再在内存中----将该字节数组中的元素一个一个地传入内存中的字节缓冲输出流创建的字节数组中
最后再通过write()方法将这个包含8192个字节元素的数组直接写入到目标硬盘中,
减少了硬盘和内存直接读写的次数,从而极大地节约了读写时间
因为内存的运行速度比硬盘要快很多!!
*/
int b;
while ((b = bis.read()) != -1) {
bos.write(b);
}
}
}
}
3.3 PrintStream打印流的功能是非常强大的,我们在学习字节字符输出流的时候发现输出的数据要转换为字节或者字符才可以进行输出。
但是打印流不需要这么麻烦,它的底层已经帮我们自动的转换为字节输出流对象。
package com.example.netty.io;
import java.io.PrintStream;
public class PrintStreamEq {
public static void main(String[] args) throws Exception{
try (PrintStream pS = new PrintStream("C:\\Users\\Admin\\Desktop\\test1.txt")) {
pS.print(97); //97
pS.print("我爱中国"); //我爱中国
pS.println(); //换行
pS.print('s'); //s
pS.println(); //换行
pS.print(true); //true
}
}
}
3.4 ZipOutputStream/ZipInputStream
import java.io.*;
import java.nio.file.Files;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public class ZipStreamEq {
public static void main(String[] args) {
try ( ZipOutputStream gzipOutputStream=new ZipOutputStream(new FileOutputStream("C:\\Users\\Admin\\Desktop\\test1.zip"))){
File f=new File("C:\\Users\\Admin\\Desktop\\test2.txt");
//创建一个ZipEntry
gzipOutputStream.putNextEntry(new ZipEntry(f.getName()));
//将原文件的字节内容,写入zip压缩包
gzipOutputStream.write(Files.readAllBytes(f.toPath()));
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
3.5 JarOutputStream/JarIntputStream
package com.example.netty.io;
import java.io.*;
import java.nio.file.Files;
import java.util.jar.JarOutputStream;
import java.util.zip.ZipEntry;
public class JarStreamEq {
public static void main(String[] args) {
try ( JarOutputStream gzipOutputStream=new JarOutputStream(new FileOutputStream("C:\\Users\\Admin\\Desktop\\test1.jar"))){
File f=new File("C:\\Users\\Admin\\Desktop\\test2.txt");
//创建一个ZipEntry
gzipOutputStream.putNextEntry(new ZipEntry(f.getName()));
//将原文件的字节内容,写入jar压缩包
gzipOutputStream.write(Files.readAllBytes(f.toPath()));
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
- ObjectInputStream/ObjectOutputStream(装饰其他字节流,对基本数据和对象进行序列化操作支持)
package com.example.netty.io;
import java.io.*;
import java.util.HashMap;
import java.util.Map;
public class ObjectStreamEq {
public static void main(String[] args) throws Exception{
ser();//序列化
dser();//反序列化
}
public static void ser() throws Exception{//序列化操作
File f = new File("D:" + File.separator + "test.txt");
try(OutputStream out = new FileOutputStream(f); ObjectOutputStream oos =new ObjectOutputStream(out)){
Map map=new HashMap<>();
map.put("java",40);
oos.writeObject(map);
}
}
public static void dser() throws Exception{//反序列化操作
File f = new File("D:" + File.separator + "test.txt");
try(InputStream input = new FileInputStream(f); ObjectInputStream ois = new ObjectInputStream(input)) {
Object obj = ois.readObject();//读取对象
System.out.println(obj);
}
}
}
- PipedInputStream/PipedOutputStream(用来解决跨线程的字节数据传输)
当需要在内存中生成文件然后上传到云端时,请记得使用管道流,伪代码如下:
public static void main(String[] args) {
try (PipedOutputStream out = new PipedOutputStream();
PipedInputStream in = new PipedInputStream(out)) {
new Thread(() -> {
Listdatabase = new LinkedList<>();
try {
//文件生成
ExcelUtils.getInstance().exportObjects2Excel(database,out);
} catch (IOException e) {
e.printStackTrace();
}
}).start();
//文件上传
ossClient.putObject("test","test.xlsx",in);
} catch (IOException e) {
e.printStackTrace();
}
}
5.2 字符流
- FileRead/FileWriter
package com.example.netty.io.zfl;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class FileReaderAndWriterEq {
public static void main(String[] args) {
try(FileReader fileReader=new FileReader("C:\\Users\\Admin\\Desktop\\read1.txt"); FileWriter fileWriter=new FileWriter("C:\\Users\\Admin\\Desktop\\read2.txt");) {
int temp=-1;
char[] chars = new char[1024];
while ((temp= fileReader.read(chars))!=-1){
fileWriter.write(chars,0,temp);
}
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
- FileRead/FileWriter
package com.example.netty.io.zfl;
import java.io.*;
/**
* 字符缓冲流
* BufferReader与BufferWriter默认的字符缓冲区(defaultCharBufferSize )的大小均为8192个字符
*/
public class BufferReaderAndWriterEq {
public static void main(String[] args) {
try(BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream("C:\\Users\\Admin\\Desktop\\read1.txt"),"UTF-8"));
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("C:\\Users\\Admin\\Desktop\\read3.txt"),"UTF-8"))) {
String line;
while ((line=bufferedReader.readLine())!=null){
bufferedWriter.write(line);
}
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
- PrintWriter
package com.example.netty.io.zfl;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
public class PrintWriterEq {
public static void main(String[] args) {
try (PrintWriter pS = new PrintWriter("C:\\Users\\Admin\\Desktop\\read1.txt")) {
pS.print(97); //97
pS.print("我爱中国"); //我爱中国
pS.println(); //换行
pS.print('s'); //s
pS.println(); //换行
pS.print(true); //true
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
}
}
- CharArrayReader/CharArrayWriter
package com.example.netty.io.zfl;
import java.io.*;
public class CharArrayReadAndWriterEq {
public static void main(String[] args) throws IOException {
CharArrayWriter bOutput = new CharArrayWriter(12);
while( bOutput.size()!= 10 ) {
// 获取用户输入值
bOutput.write(System.in.read());
}
char b [] = bOutput.toCharArray();
System.out.println("Print the content");
for(int x= 0 ; x < b.length; x++) {
// 打印字符
System.out.print(b[x] + " ");
}
int c;
CharArrayReader bInput = new CharArrayReader(b);
System.out.println("Converting characters to Upper case " );
for(int y = 0 ; y < 1; y++ ) {
while(( c= bInput.read())!= -1) {
System.out.println(Character.toUpperCase((char)c));
}
bInput.reset();
}
}
}
- PipedReader/ PipedWriter与字节流类似,只不过只适应字符型文件
- StringReader/StringWriter
StringReader类将普通字符串转换为reader,而StringWriter类则收集字符串缓冲区中的字符,该缓冲区用于构造字符串
package com.example.netty.io.zfl;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
public class StringReadAndWriterEq {
public static void main(String[] args) {
String input = "This is an example of StringReader.";
StringReader stringReader = new StringReader(input);
int c;
try {
while ((c = stringReader.read()) != -1) {
System.out.print((char) c);
}
} catch (IOException e) {
e.printStackTrace();
}
StringWriter stringWriter = new StringWriter();
stringWriter.write("\n");
stringWriter.write("This is an example ");
stringWriter.write("of StringWriter.");
// Convert writer to String
System.out.println(stringWriter.toString());
}
}