1、 io初识
1.1、java的io可以说是java最关键的基础部分,因为基本上所有的开发都会用到io,都会有输入输出,都会涉及文件的操作,关于File的使用请看http://blog.csdn.net/jin970505/article/details/78446387
1.2、java的流可以这样分类:
<1>按照处理的数据类型可以分为:字节流和字符流。
<2>按照流的流向可分为输入流和输出流。
<3>按照流的功能可分为节点流和过滤流。
这一篇先来总结字节流。
1.3、java流的框架图:
2、字节流初识
2.1、在java中,我们一般用字节流来处理字节文件(像图片、视频等),用字符流来处理字符文件,但是由于转换流的存在,我们又可以将两者进行转换,对数据的处理更加灵活。
2.2在字节流中,InputStream和OutputStream是输入输出流的”帮主”,也就是各种字节流的基类,需要注意的是,这两名”帮主”是抽象类,并不能实例化对象,只有其子类才可以实例化。我们下面通过代码和具体的例子来学习。
3、java.io.InputStream
常用方法:
1.void close() 关闭此输入流并释放所有与之有关的资源
2.int read() 从输入流中读取数据的下一个字节
3.int read(byte[] b) 从输入流中读取一定数量的字节,将其存储在缓冲区字节数组b中。
4.int read(byte[] buf,int start,int size) 读取数据到字节数组buf从buf的start位置开始存放size长度的数据
****read()方法在返回值为-1时表示输入流到达了终点****
下面来介绍InputStream的子类的用法
4、FileInputStream
基于文件的读取文件的输入流:
1、关联文件建立输入流
2、进行读取操作
3、关闭流
构造方法:
<1>FileInputStream(File file) 根据指定的File对象来建立输入流
<2>FileInputStraem(String name) 根据文件的路径(name)来建立输入流
使用字节流的具体代码,几种建立方式,注意:字节输入流是一个字节一个字节的读取,中文占两个字节,所以在读取的时候,要转换为字符流。
<1>read()方法来读取
public class IoUtil {
public static void printHex(String FileName) throws IOException{
//FileName是一个文件路径
FileInputStream in = new FileInputStream(FileName);
int b ;
//while循环外要注意变量的初始化,如果将b=in.read()放在外面,则会形成死循环
while((b=in.read())!=-1){
System.out.println(Integer.toHexString(b) + " ");
}
in.close();
}
}
<2>read(byte[] arr)方法:
public class Demo {
public static void readFile() throws IOException{
FileInputStream fis = new FileInputStream("F:\\Java.txt");
//返回文件的总大小,单位是字节
int num = fis.available();
byte[] arr = new byte[num];
/*
* 当数组长度和文件总大小相同时
* 读取一次即可
* 不再需要循环读取
* 但文件太大时不适合用
* 以防内存溢出
*/
int len = fis.read(arr);
System.out.print(new String(arr,0,len));
}
}
public static void main(String [] args){
readFile();
}
<3>read(byte[] buf,int start,int size)方法:
public static void printHexByByteArray(String fileName)throws IOException{
FileInputStream in = new FileInputStream(fileName);
byte[] buf = new byte[20 * 1024];
//从in中批量读取字节,放入到buf这个字节数组中,从第0个位置开始放,最多放buf.length个,返回的是读到的字节的个数
int bytes = in.read(buf,0,buf.length);//一次性读完,说明字节数组足够大
//若一次读不完,可以用while循环,第一次读,若读完,则执行函数,第二次读就跳出循环了,若没有读完,则会继续读buf.length个字节在执行函数,直到读完跳出循环。
while(( int bytes = in.read(buf,0,buf.length))!=-1){
int j =0;
for(int i = 0;i < bytes;i++){
if(buf[i] <= 0xf){
//如果是一个字节,就补一个0;
System.out.print("0");
}
System.out.print(Integer.toHexString(buf[i]) + " ");
if(j++%10==0){
System.out.println();
}
}
}
5、java.io.OutputStream
所有字节输出流的父类,用于将一些字节输出到某个接收器
5.1常用方法:(其中子类必须重写write(int b)才可使用)
void close() 关闭此输出流并释放与输出流有关的系统资源
void flush() 刷新输出流并强制写出缓冲区的所有内容
abstract void write(int b) 将指定的字节写入此输出流
void write(byte []b) 将b.length个字节从指定的b数组中写入到输出流中
void write(byte[]b, int off, int len) 将指定b数组中从偏移量off开始的len个字节写入输出流
6、FileOutputStream
FileOutputStream是将数据写入文件的字节输出流,若要写入字符,考虑FileWrite类。
构造方法概要:
FileOutputStream(File file) 创建一个指向File对象的写入数据的输出流(文件内容会清空,重新写入新的,也就是覆盖原有的内容)
FileOutputStream(File file, boolean flag) 创建一个指向File对象的写入数据的输出流,flag为true时,表示在原有的内容后面追加内容,不会清空
FileOutputStream(String na,e) 创建一个指向name路径文件写入数据的输出流(文件内容会清空,重新写入新的,也就是覆盖原有的内容)
FileOutputStream(String name, boolean flag) 创建一个指向name路径文件的写入数据的输出流,flag为true时,表示在原有的内容后面追加内容,不会清空
一个输出流写的实例:
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutDemo1 {
public static void main(String[] args)throws IOException {
// TODO Auto-generated method stub
//如果该文件不存在,则直接创建;如果存在,删除后创建
FileOutputStream out = new FileOutputStream("demo/out.dat",true);
out.write('A');//写出了'A'的低八位
out.write('B');//写出了'B'的低八位
int a = 10;//write()方法只能写低八位,那么写一个int,需要写4次,每次8位。
/*a>>>24的意义:
a是一个整型,四个字节,32位,.write()方法一次只能写一个字节,8位,所以如果要写一个整型a,就要写4次,a>>>24位,写32位中的最后8位,以此类推。*/
out.write(a >>> 24);
out.write(a >>> 16);
out.write(a >>> 8);
out.write(a);
byte[] gbk = "中国".getBytes("gbk");
//getBytes()函数,将一个字符串转换为一个字节数组
out.write(gbk);
out.close();
IOUtil.printHex("demo/out.dat");
}
}
通过字节流来拷贝文件:
public static void copyFile(File srcFile,File destFile)throws IOException{
if(!srcFile.exists()){
throw new IllegalArgumentException("文件:" + srcFile + "不存在");
}
if(!srcFile.isFile()){
throw new IllegalArgumentException(srcFile + "不是文件");
}
FileInputStream in = new FileInputStream(srcFile);
FileOutputStream out = new FileOutputStream(destFile);//若destFile不存在,则先创建它
byte[] buf = new byte[8 * 1024];
int b ;
while((b = in.read(buf,0,buf.length))!=-1){
out.write(buf,0,b);
/*write的三种方式:
<1>void write(byte[] b)例如:
while(c = in.read(b)!=-1){
out.write(b);
}
将 b.length 个字节从指定字节数组写入此文件输出流中。
<2>void write(byte[] b, int off, int len)
将指定字节数组中从偏移量 off 开始的 len 个字节写入此文件输出流。
<3>void write(int b) 例如:
while(c = in.read()!=-1){
out.write(c);
}
将指定字节写入此文件输出流。*/
out.flush(); // 最好加上
}
in.close();
out.close();
}
7、BufferedInputStream和BufferedOutputStream
BufferedInputStream和BufferedOutputStream这两个流类为IO提供了带缓冲区的操作,一般打开文件进行写入或读取操作时,都会加上缓冲,这种流模式提高了IO的性能。
FileOutputStream的write()方法相当于一滴一滴地把水“转移”过去;
DataOutputStream的writeXxx()方法相当于一瓢一瓢把水“转移”过去;
BufferedOutputStream的write()方法更方便一些,相当于一瓢一瓢先放入 桶中,在从桶中倒入到另外一个罐中。
需要说明的是:创建BufferedOutStream和BufferedInputStream时,必须在InputStream和OutputStream的前提下建立,例如:
FileInputStream fis = new FileInputStream();
BufferedInputStream bis = new BufferedInputStream(fis);
三种拷贝文件的方法:
<1>逐个逐个字节拷贝文件
public class IoUtil {
public static void copyFileByByte(File srcFile, File destFile) throws IOException {
if (!srcFile.exists()) {
throw new IllegalArgumentException("文件:" + srcFile + "不存在");
}
if (!srcFile.isFile()) {
throw new IllegalArgumentException(srcFile + "不是文件");
}
FileInputStream in = new FileInputStream(srcFile);
FileOutputStream out = new FileOutputStream(destFile);
int c;
while ((c = in.read()) != -1) {
out.write(c);
// out.flush();
}
in.close();
out.close();
}
}
<2>利用字节缓冲流来拷贝文件
public class IoUtil {
public static void copyFileByBuffer(File srcFile, File destFile) throws IOException {
if (!srcFile.exists()) {
throw new IllegalArgumentException("文件:" + srcFile + "不存在");
}
if (!srcFile.isFile()) {
throw new IllegalArgumentException(srcFile + "不是文件");
}
BufferedInputStream in = new BufferedInputStream(new FileInputStream(srcFile));
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(destFile));
int c;
while ((c = in.read()) != -1) {
out.write(c);
out.flush();
}
in.close();
out.close();
}
}
<3>一次性直接拷贝文件
public class IoUtil {
public static void copyFileByData(File srcFile, File destFile) throws IOException {
if (!srcFile.exists()) {
throw new IllegalArgumentException("文件:" + srcFile + "不存在");
}
if (!srcFile.isFile()) {
throw new IllegalArgumentException(srcFile + "不是文件");
}
DataInputStream in = new DataInputStream(new FileInputStream(srcFile));
DataOutputStream out = new DataOutputStream(new FileOutputStream(destFile));
int c;
byte[] arr = new byte[8 * 1024];
while ((c = in.read(arr, 0, arr.length)) != -1) {
out.write(arr, 0, c);
}
in.close();
out.close();
}
}