流的概念
流(Stream)是指在计算机的输入输出操作中各部件之间的数据流动。按照数据的传输方向,流可分为输入流和输出流。Java语言里的流序列中的数据既可以时未经过加工的原始二进制数据,也可以是经过一i的那个编码处理后符合某种特定格式的数据。
流的分类
按大小
按大小分为字节流与字符流。字节流:读取的最小单位是一个字节(byte)。字符流:字符流以此可以读取一个字符(char)。
字节流与字符流的区别
java.io包中操作文件内容的主要有两大类:字节流、字符流,两类都有输入和输出操作。在字节流中,输出数据是依靠OutputStream完成,输入使用InputStream;在字符流中,输出使用Writer类完成,输入使用Reader类完成。
字符流处理的单元为两个字节的Unicode字符,分为操作字符、字符数组或字符串,而字节流处理单元为一个字节,操作字节和字节数组。字节流时JVM将字节转化为2个字节的Unicode字符而成的,所以它对多国语言支持性能较好!如果是音频文件、图片、歌曲等 就用字节流,如果是关系到中文(文本)的,就用字符流。
所有文件的存储都是字节(byte)的存储,在磁盘上保存的并不是文件的字符而是先把字符编码成字节,再储存字节到磁盘。读取文件时,也是一个一个字节地读取以形成字节序列。
按传输方向
分为输入流和输出流
按等级
分为:节点流(低级流)和处理流(高级流或过滤流)
IO流
IO指的是输出与输出
I即Input:输入,从文件到程序
O即Output:输出,从程序到文件,写出数据
字节流
1.FIS和FOS
即 FileInputStream(文件输入流) 和 FileOutputStream(文件输出流)
直接上FileInputStream的源码:
public
class FileInputStream extends InputStream
/* File Descriptor - handle to the open file */
private final FileDescriptor fd;
/**
* The path of the referenced file
* (null if the stream is created with a file descriptor)
*/
private final String path;
private FileChannel channel = null;
private final Object closeLock = new Object();
private volatile boolean closed = false;
大部分看不懂,截取关键的部分,由源码可以得到 FileInputStream 是继承自InputStream 这个父类的
再来看看它里面的方法:
可见方法有点小多,但是现阶段就read(读文件)和close(关闭流)两个方法有用
再上 FileOutputStream的原码和方法列表
public
class FileOutputStream extends OutputStream
{
/**
* The system dependent file descriptor.
*/
private final FileDescriptor fd;
/**
* True if the file is opened for append.
*/
private final boolean append;
/**
* The associated channel, initialized lazily.
*/
private FileChannel channel;
/**
* The path of the referenced file
* (null if the stream is created with a file descriptor)
*/
private final String path;
private final Object closeLock = new Object();
private volatile boolean closed = false;
类似地,FileOutputStream继承自抽象类OutputStream,方法主要是write(写入)和close(关闭流)。
下面用两个流实现对文件地读写以及复制地操作:
public class TestFISAndFOS {
File file;
FileInputStream fis;
FileOutputStream fos;
@Before //在所有test运行之前先运行的内容
public void getFile(){
file = new File("src\\com\\jmn\\io\\testio\\fisfos.txt");
}
@Test//写
public void test() throws IOException {
/*
write(in)
*/
fos = new FileOutputStream(file);
fos.write("helloworld".getBytes());
}
@Test//读
public void read() throws IOException {
fis = new FileInputStream(file);
/*
int read(): 返回值就是读取出来的字符,如果没有字符则返回-1
// */
// int i = -1;
// while ((i = fis.read()) != -1){
// System.out.println((char) i);
// }
/*
int read(byte[] bus):读取文件内容到byte数组中
*/
int i = -1;
byte[] bus = new byte[1024];
if((i = fis.read(bus)) != -1){
System.out.println(new String(bus));
}
}
@Test//文件的复制 ,将fisfos.txt 在相同路径下复制一个副本fisfos_copy.txt
public void fileCopy() throws Exception{
//1.先读
fis = new FileInputStream(file);
file = new File("src\\com\\jmn\\io\\testio\\fisfos_copy.txt");
fos = new FileOutputStream(file);
int i = -1;
//读单个
// while ((i = fis.read()) != -1){
// fos.write(i);
// }
//读byte[]
byte[] bytes = new byte[1024];
if((i = fis.read(bytes)) != -1){
System.out.println(new String(bytes));
}
}
@After //每运行一个test之后必须要运行的内容
public void close() throws IOException {
//非空判断 关闭流,释放资源
if(fis != null) fis.close();
if(fos != null) fos.close();
}
}
2.BIS与BOS(带缓存的输入输出流)
BIS:BufferedInputStream
BOS:BufferedOutputStream
缓冲流: 内部定义了一个缓冲区
就不看源码了,这里我们看看他们的继承关系: