文本文件的读写
- 用FileInputStream和FileOutputStream读写文本文件
- 用BufferedReader和BufferedWriter读写文本文件
二进制文件的读写
- 使用DataInputStream和DataOutputStream读写二进制文件
1、文件读写的实现步骤:
- 引入相关类
- 构造文件输入输出流对象
- 读取文本文件的数据
- 关闭文件流对象
与JDBC编程一样,程序里面打开的文件IO资源不属于内存的资源,垃圾回收机制无法回收该资源,所以应该显示的关闭打开的IO资源。Java 7改写了所有的IO资源类,它们都实现了AntoCloseable接口,因此都可以通过自动关闭资源的try语句来关闭这些Io流。
2、IO流的用法
2.1 IO操作的基类(InputStream/Reader,OutputStream/Writer)。
InputStream和Reader是所有输入流的抽象基类,本身并不能创建实例来执行输入,但它们将成为所有输入流的模板,所以它们的方法是所有输入流都可使用的方法。
在InputStream里面包含如下3个方法。
- int read(); 从输入流中读取单个字节,返回所读取的字节数据(字节数据可直接转换为int类型)。
- int read(byte[] b)从输入流中最多读取b.length个字节的数据,并将其存储在字节数组b中,返回实际读取的字节数。
- int read(byte[] b,int off,int len); 从输入流中最多读取len个字节的数据,并将其存储在数组b中,放入数组b中时,并不是从数组起点开始,而是从off位置开始,返回实际读取的字节数。
在Reader中包含如下3个方法。
- int read(); 从输入流中读取单个字符,返回所读取的字符数据(字节数据可直接转换为int类型)。
- int read(char[] b)从输入流中最多读取b.length个字符的数据,并将其存储在字节数组b中,返回实际读取的字符数。
-
int read(char[] b,int off,int len); 从输入流中最多读取len个字符的数据,并将其存储在数组b中,放入数组b中时,并不是从数组起点开始,而是从off位置开始,返回实际读取的字符数。
OutputStream和Writer:
OutputStream和Writer的用法也非常相似,它们采用如图15.6所示的模型来执行输入,两个流都提供了如下三个方法:
- void write(int c); 将指定的字节/字符输出到输出流中,其中c即可以代表字节,也可以代表字符。
- void write(byte[]/char[] buf); 将字节数组/字符数组中的数据输出到指定输出流中。
- void write(byte[]/char[] buf, int off,int len ); 将字节数组/字符数组中从off位置开始,长度为len的字节/字符输出到输出流中。
因为字符流直接以字符作为操作单位,所以Writer可以用字符串来代替字符数组,即以String对象作为参数。Writer里面还包含如下两个方法。
- void write(String str); 将str字符串里包含的字符输出到指定输出流中。
- void write (String str, int off, int len); 将str字符串里面从off位置开始,长度为len的字符输出到指定输出流中。
2.2 IO操作的基类文件流的使用(FileInputStream/FileReader ,FileOutputStream/FileWriter)
前面说过InputStream和Reader都是抽象类,本身不能创建实例,但它们分别有一个用于读取文件的输入流:FileInputStream和FileReader,它们都是节点流——会直接和指定文件关联。下面程序示范使用FileInputStream和FileReader。
使用FileInputStream读取文件:
package cn.sxt.IOStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/**
* 输入流和输出流式相对计算机内存而言的
* 输出流:OutputStream和Writer作为基类
* 输入流:InputStream和Reader做为基类
*
* 字节流:OutputStream和InputStream,能操做任意文件,图片、视频、文档
* 字符流:Writer和Reader,只能操作文档类型的文件
* 如果是音频文件、图片、歌曲,就用字节流好点,如果是关系到中文(文本)的,用字符流好点
* @author 关启培
*
*/
public class FileInputStreamTest {
public static void main(String[] args) throws IOException {
FileInputStream fis=null;
try {
//创建字节输入流
fis=new FileInputStream("E:/eclipse/a.txt"); //这里注意写入自己的路径
//创建一个长度为1024的byte数组作为中转
byte[] word=new byte[1024];
//用于保存的实际字节数
int len=0;
//使用循环来重复取数据的过程
//从输入流中最多读取word.length个字节的数据,并将其存储在字节数组word中,返回实际读取的字节数。
while((len=fis.read(word))!=-1) {
//输出Word中的数据
for(int i=0;i<len;i++) {
System.out.println((char)word[i]);
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}finally {
if(fis!=null) {
fis.close(); //关闭流对象
}
}
}
}
使用FileReader读取文件:
package cn.stan.ReaderAndWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class FileReaderTest {
public static void main(String[] args) throws IOException {
FileReader fr=null; //用来对文件操作的对象
StringBuffer sbf=null;//用来接收数据
try {
//创建字节输入流对象
fr=new FileReader("E:/eclipse/a.txt");
//创建一个长度为1024的char数组,用来存放数据
char[] ch=new char[1024];
//可修改,并且不产生新的对象
sbf=new StringBuffer();
//用于保存的实际字节数
//从输入流中最多读ch.length个字节的数据,并将其存储在字节数组ch中,返回实际读取的字节数。
int len=fr.read(ch);
while(len!=-1){
//使用append向字符串中追加数据
sbf.append(ch);
len=fr.read();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}finally {
if(fr!=null) {
fr.close();
}
}
System.out.println(sbf.toString());
}
}
可以看出使用FileInputStream和FileReader进行文件的读写并没有什么区别,只是操作单元不同而且。
FileOutputStream/FileWriter是Io中的文件输出流,下面介绍这两个类的用法。
FileOutputStream的用法:
package cn.sxt.IOStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* 输入流和输出流式相对计算机内存而言的
* 输出流:OutputStream和Writer作为基类
* 输入流:InputStream和Reader做为基类
*
* 字节流:OutputStream和InputStream,能操做任意文件,图片、视频、文本文件
* 字符流:Writer和Reader,只能操作文本类型的文件
* @author 关启培
*
*/
public class FileOutputStreamTest {
public static void main(String[] args) throws IOException {
FileOutputStream fos=null;
//要输出的内容
String str="dafkjdsf";
//将字符串转换为byte序列
byte[] words=str.getBytes();
//第二个参数为false会覆盖原文件内容,true则会在后面添加新的内容,默认为false
//创建字节输出流
fos=new FileOutputStream("E:/eclipse/b.txt",true);
//写入文件中
fos.write(words,0,words.length);
System.out.println("文件已经创建,并写入内容");
}
}
FileWriter的用法:
package cn.stan.ReaderAndWriter;
/**
* FileWriter操作的是字符,可以不用转换成比byte;
*
*/
import java.io.*;
public class FileWriterTest {
public static void main(String[] args) {
FileWriter fw=null;
try {
fw=new FileWriter("E:/eclipse/a.txt",true);
fw.write("我真是天才");
//刷新缓冲区,输出所有缓冲字节,强制将缓冲区的字节输出出去
fw.flush();
System.out.println("文件已写入");
} catch (IOException e) {
System.out.println("文件出现异常");
e.printStackTrace();
}finally {
try {
if(fw!=null) {
fw.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
缓冲流的使用(BufferedInputStream/BufferedReader, BufferedOutputStream/BufferedWriter),缓冲流能够提高读写文件的效率,他们是四个基类的子类,并且带有缓冲区。
下面介绍字节缓存流的用法:
public class BufferedStreamTest {
public static void main(String[] args)throws IOException {
FileInputStream fis=null;
FileOutputStream fos=null;
BufferedInputStream bis=null;
BufferedOutputStream bos=null;
try {
//创建字节输入流
fis=new FileInputStream("E:\\learnproject\\Iotest\\lib\\src\\main\\java\\com\\Test.txt");
//创建字节输出流
fos=new FileOutputStream("E:\\learnproject\\Iotest\\lib\\src\\main\\java\\com\\newTest.txt");
//创建字节缓存输入流
bis=new BufferedInputStream(fis);
//创建字节缓存输出流
bos=new BufferedOutputStream(fos);
byte[] b=new byte[1024];
int hasRead=0;
//循环从缓存流中读取数据
while((hasRead=bis.read(b))>0){
//向缓存流中写入数据,读取多少写入多少
bos.write(b,0,hasRead);
}
}catch (IOException e){
e.printStackTrace();
}finally {
bis.close();
bos.close();
}
}
}
下面是字符缓冲流的的使用:
package cn.stan.ReaderAndWriter;
/**
* 文本复制
*/
import java.io.*;
public class Practice {
public static void main(String[] args) {
FileReader fr=null;
BufferedReader br=null;
FileWriter fw=null;
BufferedWriter bw=null;
try {
fr=new FileReader("E:/eclipse/a.txt");
br=new BufferedReader(fr);
fw=new FileWriter("E:/eclipse/b.txt",true);
bw=new BufferedWriter(fw);
//读取一行数据
String line=br.readLine();
while(line!=null) {
bw.write(line);
bw.flush();
line=br.readLine();
}
System.out.println("文件复制成功");
}catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(fr!=null) {
fr.close();
}
if(br!=null) {
br.close();
}
if(fw!=null) {
fw.close();
}if(bw!=null) {
bw.close();
}
}catch(IOException e) {
e.printStackTrace();
}
}
}
}
二进制文件的读写
下面给出实例,对二进制文件进行操作:
package cn.stan.binaryIO;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class PictureCopy {
public static void main(String[] args) {
FileInputStream fin=null;
FileOutputStream fout=null;
DataInputStream dis=null;
DataOutputStream out=null;
try {
//创建输入流对象
fin=new FileInputStream("E:/img/5.jpg");
dis=new DataInputStream(fin);
//创建输出流对象
fout=new FileOutputStream("F:/img/7.jpg");
out=new DataOutputStream(fout);
int temp;
while((temp=dis.read())!=-1) {
out.write(temp);
System.out.println(temp);
}
System.out.println("文件复制成功");
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
if(out!=null) {
out.close();
}
if(fout!=null) {
fout.close();
}
if(dis!=null) {
dis.close();
}
if(fin!=null) {
fin.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
}
}
这里是从一个目录复制一张图片到另外的目录。
到这里IO的学习基本告一段落,最后是总结: