IO流
读取流: 读取数据
输出流: 写出数据
按照数据类型
字节流:任何文件都可以被看成是一个字节数组,字节流可以操作任何文件。
字符流:只能操作文本类型的文件
字节流基类
输出流基类:OutputStream
输入流基类:InputStream
字符流基类
输出流基类:Writer
输入流基类:Reader
字节流和字符流的子类命名方式都是以他们的基类作为后缀名的
在写入过程中,会先判断硬盘上有没有对应的文件,如果没有就创建,然后建立一个通道,通过这个通道写入字节。当数据写入结束以后,通道就应该关闭掉,不然会占用资源,会导致内存泄漏;当内存泄漏过多就会导致内存溢出。
public static void main(String[] args) throws Exception {
FileOutputStream stream = null;
try {
stream = new FileOutputStream("/Users/yoofale/Desktop/haha.txt");
byte[] bytes = "腰子啊".getBytes();
stream.write(bytes);
System.out.println(bytes.length);
stream.write(bytes, 0, 6);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
stream.close();
}
}
标准格式就是先在外面定义一个FileOutPutStream,并初始化。try中前面一旦发生错误就不会继续执行,没法继续下面的关闭通道释放资源,所以将关闭通道放在finally中,确保安全。
字节流写数据
FileOutputStream的构造方法
FileOutputStream(File file) 创建一个向指定File文件写入数据的文件输出流
FileOutputStream(String name) 创建一个向具有指定名称的文件中写入数据的输出流
写入数据
public void write(int b)
public void write(byte[] b)
public void write(byte[] b,int off,int len)
如何追加和换行写入?
追加
new FileOutputStream(file, append)True写在文件末尾处,false写在文件开头
换行
byte[] bytes = "腰子啊\r\n".getBytes(); 字符串后面加\r\n
public static void main(String[] args) {
// public FileInputStream(File file)和指定文件建立一个读取通道
// public FileInputStream(String name)和指定文件建立一个读取通道
try {
stream = new FileInputStream("/Users/yoofale/Desktop/haha.txt");
//public int read()从读取通道中读取一个字节,这个方法是阻塞的
int i=stream.read();
System.out.println(i);//232
i=stream.read();
System.out.println(i);//133
// public int read(byte[] b)从输入流中读取一定数量的字节,并将其存储在缓冲区数组b中
// 读入缓冲区的总字节数,如果因为已经到达流末尾而不再有数据可用,返回-1
byte[] buf=new byte[1024];
int read = stream.read(buf);
String string = new String(buf,0,read);
System.out.println(string);
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
两种读取,一次读取一个字节,一次读取一个数组。一次读取一个数组比一次读取一个字节效率高得多。
运用字节流复制文件
public static void main(String[] args) {
// 先读后写,文件字节读取流
FileInputStream fis=null;
FileOutputStream fos=null;
try {
fis = new FileInputStream("/Users/yoofale/Desktop/haha.txt");
fos = new FileOutputStream("/Users/yoofale/Desktop/hehe.txt");
// 读的时候,需要定义一个缓冲区容器,一次多取一点
byte[] buf=new byte[1024];
// 定义一个变量,用于接受每次读取的字节数
int len =-1;
// 循环读写
while((len=fis.read(buf))!=-1){
fos.write(buf,0,len);
}
System.out.println("拷贝成功");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
//先创建的后关闭
if(null!=fos){
try {
fos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(null!=fis){
try {
fis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
代码分析:标准格式。唯一需要注意的就是,先创建的流要后关闭。因为所有的内容全都获取到,不能只是一部分。如果读取到的内容不为-1,开始写入内容。,读多少就写多少。
简化关闭流
将两个关闭封装成方法,打包放入IOUtils中(将private换成public,不要带main),想要调用方法,IOUtils.closeIn()即可
JDK1.7新特性,可以在用完流的时候自动关闭;在try()里面自动只能用于创建流.不能创建其他。执行到try结束之后,流自动关闭
public static void main(String[] args) {
// 先读后写,文件字节读取流
try (FileInputStream fis = new FileInputStream("/Users/yoofale/Desktop/haha.txt");
FileOutputStream fos = new FileOutputStream("/Users/yoofale/Desktop/hehe.txt");) {
// 读的时候,需要定义一个缓冲区容器,一次多取一点
byte[] buf = new byte[1024];
// 定义一个变量,用于接受每次读取的字节数
int len = -1;
// 循环读写
while ((len = fis.read(buf)) != -1) {
fos.write(buf, 0, len);
}
System.out.println("拷贝成功");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
完整版封装复制文件代码
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class IOUtils {
public static void copyFile(String srcPath, String destPath){
try (FileInputStream fis = new FileInputStream(srcPath);
FileOutputStream fos = new FileOutputStream(destPath);) {
// 读的时候,需要定义一个缓冲区容器,一次多取一点
byte[] buf = new byte[1024];
// 定义一个变量,用于接受每次读取的字节数
int len = -1;
// 循环读写
while ((len = fis.read(buf)) != -1) {
fos.write(buf, 0, len);
}
System.out.println("拷贝成功");
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 关闭字节读取流
* @param fis 要关闭的流名称
*/
// TODO Auto-generated method stub
public static void closeIn(InputStream fis) {
if(null!=fis){
try {
fis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
* 关闭字节输出流
* @param fos 要关闭的流名称
*/
public static void closeOut(OutputStream fos) {
if(null!=fos){
try {
fos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
采用了新特性,下面留了普通关闭流的方法。