Java IO
总览:
流的概念:
在外部设备和其他计算机进行交流的输入/输出操作,尤其是对磁盘文件的操作,是计算机程序重要的功能,任何计算机语言都必须对输入/输出提供支持。
java也不例外,它提供了基于流的输入/输出系统。
java程序通过流执行 I/O 。流是一种抽象,要么产生信息,要么使用信息。流通过java的 I/O 系统链接到物理设备。从而实现文件的各种操作。
java中的流
java中定义了两种类型的流:字节流和字符流。
字节流: 字节流为处理字节的输入和输出提供了方法。
字符流: 字符流为处理字符的输入和输出提供了方法。
java中基于流的I/O构建在4个抽象类上:
分别是操作字节流的InputStream
和OutputStream
。
操作字符流的Reader
和Writer
虽然分为字节流和字符流,但在最底层,所有的 I/O 都是面向字节的。
.
.
.
.
核心类(File)
这是IO中的核心类,这个类主要用于文件和目录的创建、文件的查找和文件的删除等。
通过给定的父抽象路径名和子路径名字符串创建一个新的File实例。
File(File parent, String child);
通过将给定路径名字符串转换成抽象路径名来创建一个新 File 实例。
File(String pathname);
通过将给定的 file: URI 转换成一个抽象路径名来创建一个新的 File 实例。
File(URI uri);
具体的方法有很多,可以查看java API文档。
下面是演示File对象的使用(该演示来自菜鸟教程):
import java.io.File;
public class DirList {
public static void main(String args[]) {
String dirname = "/java";
File f1 = new File(dirname);
if (f1.isDirectory()) {
System.out.println("Directory of " + dirname);
String s[] = f1.list();
for (int i = 0; i < s.length; i++) {
File f = new File(dirname + "/" + s[i]);
if (f.isDirectory()) {
System.out.println(s[i] + " is a directory");
} else {
System.out.println(s[i] + " is a file");
}
}
} else {
System.out.println(dirname + " is not a directory");
}
}
}
运行结果:
Directory of /java
bin is a directory
lib is a directory
demo is a directory
test.txt is a file
README is a file
index.html is a file
include is a directory
.
.
.
IO操作
IO操作四大基本步骤:
1.选择源(选择需要操作的文件,也就是用File类进行构建)
2.选择流(根据文件的类型选择流,纯文本的文件就用字符流。不是文本文件的,音乐,视频,图片就用字节流)
3.处理流(根据流进行操作,拷贝,转字节存储一系列的)
4.关闭流(如果是节点流就要进行释放流,调用流的close方法进行释放,字节流可以不用释放。)
这就是IO的基本步骤。基本上大同小异。只要搞懂了规律,会拷贝文件,初入IO就可以了。
拷贝文件:
package com.hjj.io;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
*1、 图片读取到字节数组
*2、 字节数组写出到文件
* @author hjj
*
*/
public class IOTest09 {
public static void main(String[] args) {
//图片转成字节数组
byte[] datas = fileToByteArray("hjj.png");
System.out.println(datas.length);
byteArrayToFile(datas,"hjj-byte.png");
}
/**
* 1、图片读取到字节数组
* 1)、图片到程序 FileInputStream
* 2)、程序到字节数组 ByteArrayOutputStream
*/
public static byte[] fileToByteArray(String filePath) {
//1、创建源与目的地
File src = new File(filePath);
byte[] dest =null;
//2、选择流
InputStream is =null;
ByteArrayOutputStream baos =null;
try {
is =new FileInputStream(src);
baos = new ByteArrayOutputStream();
//3、操作 (分段读取)
byte[] flush = new byte[1024*10]; //缓冲容器
int len = -1; //接收长度
while((len=is.read(flush))!=-1) {
baos.write(flush,0,len); //写出到字节数组中
}
baos.flush();
return baos.toByteArray();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
//4、释放资源
try {
if(null!=is) {
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
/**
* 2、字节数组写出到图片
* 1)、字节数组到程序 ByteArrayInputStream
* 2)、程序到文件 FileOutputStream
*/
public static void byteArrayToFile(byte[] src,String filePath) {
//1、创建源
File dest = new File(filePath);
//2、选择流
InputStream is =null;
OutputStream os =null;
try {
is =new ByteArrayInputStream(src);
os = new FileOutputStream(dest);
//3、操作 (分段读取)
byte[] flush = new byte[5]; //缓冲容器
int len = -1; //接收长度
while((len=is.read(flush))!=-1) {
os.write(flush,0,len); //写出到文件
}
os.flush();
} catch (IOException e) {
e.printStackTrace();
}finally {
//4、释放资源
try {
if (null != os) {
os.close();
}
} catch (Exception e) {
}
}
}
}
这样就实现了文件的拷贝。
.
.
.
.
.
装饰器模式
装饰器模式,即就是在不改变原来的代码,再在上面追加代码,增加功能。
可以看下这个大佬的博客:https://blog.csdn.net/jason0539/article/details/22713711。
就像博客里举例的,一个鸡腿堡,不加生菜不加辣椒,也是鸡腿堡。加了也是鸡腿堡,不过更好吃了。
在 IO 里面也是加上了装饰器。就更能提升代码执行效率。
.
.
.
字节缓冲流(BufferedInputStream
&BufferedOutputStream
)
它为原本没有缓冲区的字节流加上缓冲区(即内存),所以加了缓冲区的字节流读取和写出速度很快。
字符缓冲流(BufferedReader
&BufferedWriter
)
和字节缓冲流一样,也是为字符流加入缓冲区
转换流(InputStreamReader
&OutputStreamWriter
)
即将字符流装换为字节流,字节流转换为字符流,这样之间互转。
数据流(DataInputStream
&DataOutputStream
)
这个就是为了处理java中的8大数据类型,它不仅保留了我们的数据,还保留我们的数据类型。必须先写出再读取,而且还得按顺序读取。(没有怎么读取嘛)
对象流(ObjectInputStream
&ObjectOutputStream
)
这个和数据流差不多,也是一样。也是先写出后读取。不一样的是,这个对象流需要序列化,但也不是所有的对象都可以序列化,需要实现Serializable
接口,才能被序列化。
如果一个类的属性不想被序列化就可以使用transient
关键字。
这样就被加上关键字的属性就不会被序列化,返回的结果为null。
private transient string baby;
这样baby就无法被序列化
打印流(PrintStream
)
这个流方便我们打印各种数据,我们经常用的System.out
就是这个流中的。
随机流(RandomAccessFile
)
随机流就可以随便从哪个位置访问都是可以的,比如读取一个文件里面的内容,一般地话,就得直接从开始读取,而这个流就可以读取其中一点。
合并流(SequenceInputStream
)
合并就将分割后的字节文件从新组合一起,形成一个完整文件
.
.
.
.
.
阿杰的学习总结.很菜但会努力的.fight.