Java之I/O输入输出流解析

推荐资源站:https://zhimalier.com/

一、流的概述

流是一组有序的数据序列,根据操作的类型,可以分为输入流和输出流。I/O流提供了一条通道程序,可以使用这条通道把源中的字节序列送到目的地。

二、输入模式 输出模式图

Java之I/O输入输出流解析_第1张图片

三、java流的分类

按流向分:

  输入流: 程序可以从中读取数据的流。
  输出流: 程序能向其中写入数据的流。

按数据传输单位分:

  字节流: 以字节为单位传输数据的流
  字符流: 以字符为单位传输数据的流

按功能分:

  节点流: 用于直接操作目标设备的流
  处理流: 是对一个已存在的流的链接和封装,通过对数据进行处理为程序提供功能强大、灵活的读写功能。

四、字节输入流(InputStream)/字节输出流(OutputStream)简介及方法

InputStream类是字节输入流的抽象类,是所有字节输入流的父类。必须依靠其子类实现各种功能,且数据单位为字节(8bit);他是指数据以字节形式从其他文件或者设备向程序流入。常用方法如下:

       (1) public abstract int read( ):读取一个byte的数据,返回值是高位补0的int类型值。若返回值=-1说明没有读取到任何字节读取工作结束。
  (2) public int read(byte b[ ]):读取b.length个字节的数据放到b数组中。返回值是读取的字节数。该方法实际上是调用下一个方法实现的 。
  (3) public int read(byte b[ ], int off, int len):从输入流中最多读取len个字节的数据,存放到偏移量为off的b数组中。 
  (4) public int available( ):返回输入流中可以读取的字节数。注意:若输入阻塞,当前线程将被挂起,如果InputStream对象调用这个方法的话,它只会返回0,这个方法必须由继承InputStream类的子类对象调用才有用。
  (5) public long skip(long n):忽略输入流中的n个字节,返回值是实际忽略的字节数, 跳过一些字节来读取 。
  (6) public int close( ) :我们在使用完后,必须对我们打开的流进行关闭。

Java之I/O输入输出流解析_第2张图片

OutputStream类是字节输出流的抽象类,此抽象类是表示输出字节流的所有类的超类;他是数据以字节形式从程序流出,输出流只能向流中写入数据。

OutputStream提供了3个write方法来做数据的输出,这个是和InputStream是相对应的。 

  1. public void write(byte b[ ]):将参数b中的字节写到输出流。 
  2. public void write(byte b[ ], int off, int len) :将参数b的从偏移量off开始的len个字节写到输出流。 
  3. public abstract void write(int b) :先将int转换为byte类型,把低字节写入到输出流中。 
  4. public void flush( ) : 将数据缓冲区中数据全部输出,并清空缓冲区。 
  5. public void close( ) : 关闭输出流并释放与流相关的系统资源。 
注意:并不是所有的inputstream类的子类都支持inputstream中定义的方法,如skip() mark() reset()等方法只对某些子类有用

Java之I/O输入输出流解析_第3张图片

五、文件输入/输出流实例
FileInputStream类与FileOutputStream类

/*文件输入流: FileInputStream类
作用:以文件作为数据输入源的数据流。或者说是打开文件,从文件读数据到内存的类。
*/
import java.io.IOException;  
import java.io.FileInputStream;  
public class TestFile {  
    public static void main(String args[]) throws IOException {  
        try{      
               FileInputStream rf=new   FileInputStream("A.java");  //有内容的java文件
               int n=512;   byte  b[]=new  byte[n];     
               while((rf.read(b,0,n)!=-1)&&(n>0)){  
                   System.out.println(new String(b) );  
                }  
                System.out.println();  
                rf.close();  
        } catch(IOException  IOe){        
              System.out.println(IOe.toString());  
        }  
    }  
}  

/*文件输出流:FileOutputStream类
作用:用来处理以文件作为数据输出目的数据流;或者说是从内存区读数据入文件
*/
import java.io.IOException;  
import java.io.FileOutputStream;  
public class TestFile {  
    public static void main(String args[]) throws IOException {  
        try {  
            System.out.println("请输入");  
            int count, n = 512;  
            byte buffer[] = new byte[n];  
            count = System.in.read(buffer);     //从键盘接收 
            FileOutputStream wf = new FileOutputStream("d:/write.txt");   //文件需要已存在 
            wf.write(buffer, 0, count);  
            wf.close(); // 当流写操作结束时,调用close方法关闭流。  
            System.out.println("内容保存成功!");  
        } catch (IOException IOe) {  
            System.out.println("文件写入失败!");  
        }  
    }  
}

六、字符流的读取和写入 抽象类:Reader和Writer

Reader用于读取字符流的抽象类。子类必须实现的方法只有 read(char[], int, int) 和 close()。

      FileReader :与FileInputStream对应  主要用来读取字符文件,使用缺省的字符编码,有三种构造函数: 

      (1)将文件名作为字符串 :FileReader f=new FileReader(“c:/temp.txt”); 

      (2)构造函数将File对象作为其参数。               

File f=new file(“c:/temp.txt”); 
FileReader f1=new FileReader(f);

      (3)  构造函数将FileDescriptor对象作为参数               

FileDescriptor() fd=new FileDescriptor() 
FileReader f2=new FileReader(fd); 

主要方法

           (1) 用指定字符数组作为参数:CharArrayReader(char[]) ;
           (2) 将字符数组作为输入流:CharArrayReader(char[], int, int) 读取字符串,构造函数如下: public StringReader(String s);              (3) CharArrayReader:与ByteArrayInputStream对应;
      (4) StringReader : 与StringBufferInputStream对应 ;
      (5) InputStreamReader从输入流读取字节,在将它们转换成字符:Public inputstreamReader(inputstream is); 
      (6) FilterReader: 允许过滤字符流   protected filterReader(Reader r);
      (7) BufferReader :接受Reader对象作为参数,并对其添加字符缓冲器,使用readline()方法可以读取一行。   Public BufferReader(Reader r); 

Java之I/O输入输出流解析_第4张图片
 

Writer 写入字符流的抽象类。子类必须实现的方法仅有 write(char[], int, int)、flush() 和 close()。

       1)FileWrite: 与FileOutputStream对应  将字符类型数据写入文件,使用缺省字符编码和缓冲器大小 Public FileWrite(file f); 

     2)  chararrayWrite:与ByteArrayOutputStream对应 ,将字符缓冲器用作输出。  Public CharArrayWrite(); 

  3) PrintWrite:生成格式化输出  public PrintWriter(outputstream os); 

  4) filterWriter:用于写入过滤字符流   protected FilterWriter(Writer w); 

  5) PipedWriter:与PipedOutputStream对应   

       6) StringWriter:无与之对应的以字节为导向的stream  

 主要方法:
       (1)  public void write(int c) throws IOException; //将整型值c的低16位写入输出流 ;
  (2)  public void write(char cbuf[]) throws IOException; //将字符数组cbuf[]写入输出流 ;
  (3)  public abstract void write(char cbuf[],int off,int len) throws IOException; //将字符数组cbuf[]中的从索引为off的位置处开始的len个字符写入输出流 ;
  (4)  public void write(String str) throws IOException; //将字符串str中的字符写入输出流 ;
  (5)  public void write(String str,int off,int len) throws IOException; //将字符串str 中从索引off开始处的len个字符写入输出流 ;
  (6)  flush( ) //刷空输出流,并输出所有被缓存的字节; 
  (7)  close()    关闭流 public abstract void close() throws IOException;

Java之I/O输入输出流解析_第5张图片

----------------------------------------------------------------------------------------------------------------------------
字节与字符的转换流

说到这先说一下二者的区别

       1)字符流处理的单元为2个字节的Unicode字符,分别操作字符、字符数组或字符串,

       2)而字节流处理单元为1个字节, 操作字节和字节数组。

       字节流可用于任何类型的对象,包括二进制对象,而字符流只能处理字符或者字符串; 字节流提供了处理任何类型的IO操作的功能,但它不能直接处理Unicode字符,而字符流就可以。      所以字符流是由Java虚拟机将字节转化为2个字节的Unicode字符为单位的字符而成的,所以它对多国语言支持性比较好! 
      如果是 音频文件、图片、歌曲,就用字节流好点。
      如果是关系到中文(文本)的,用字符流好点

/*InputStreamReader 和OutputStreamWriter 分别是Reander和Writer的子类,二者用于字节流和字符流之间的转换。
InputStreamReader用于将输入的字节流转变为字符流
OutputStreamWriter  用于将输入的字符流转变为字节流*/

Reader reader = new InputStreamReader(new FileInputStream("d:\\1.txt"));
System.out.println(reader.read());
reader.close();

File f=new File(“d:/1.txt”);
OutputStreamWriter os=new OutputStreamWriter(new FileOPutInStream(f));
Os.write(“hello word”);
Os.close();

---------------------------------------------------------------------------------------------------------------

七、带缓存的输入/输出流

BufferedInputStream:当向缓冲流写入数据时候,数据先写到缓冲区,待缓冲区写满后,系统一次性将数据发送给输出设备。

BufferedOutputStream :当从向缓冲流读取数据时候,系统先从缓冲区读出数据,待缓冲区为空时,系统再从输入设备读取数据到缓冲区。

1)将文件读入内存:

将BufferedInputStream与FileInputStream相接

FileInputStream in=new  FileInputStream( “file1.txt ” );
BufferedInputStream bin=new  BufferedInputStream( in); 

2)将内存写入文件:

将BufferedOutputStream与 FileOutputStream相接

FileOutputStreamout=new FileOutputStream(“file1.txt”);
BufferedOutputStream  bin=new BufferedInputStream(out);

BufferedReader和BufferedWriter是带缓冲区的Reader和Writer.

使用BufferedReader读取文本时,将首先从文件中读取字符数据并存入缓冲区中,然后调用read(),先冲缓冲区开始读取,缓冲区不足是再从文件中读取;

使用BufferedWriter时,写入数据将先存储到缓冲区中,在缓冲区饱满的情况下将一次性写入目的地。

通过缓冲区可以减少对硬盘的输入或输出操作,提高文件存取效率。

File f=new File(“d;/demo.txt);
FileWriter bufWriter=new BufferedWriter(writer);
bufWriter.writer(“hello word);
bufwruter.close();
writer.close();
FileReader reader =new FileReader(“f);
BufferedReader bufReader=new BufferedReader(reader);
Sysout.out.print(bufReader.readLine());

八、数据输入/输出流

DataInputStream与DataOutputStream允许应用程序以与机器无关的方式从底层输入流中读取基本java数据类型。

简单说就是,当读取一个数据时,不必再关心这个数值应当是哪种字节

构造方法

DataInputStream(InputStream in)  使用指定的底层 InputStream 创建一个 DataInputStream;
DataOutputStream(OutputStream out) 创建一个新的数据输出流,将数据写入指定基础输出流;
DataOutputStream类提供的3种写入方法;
writeBytes(String s)  将字符串按字节顺序写出到基础输出流中;
writeChars(String s)   将字符串按字符顺序写入基础输出流;
writeUTF(String str)  以与机器无关方式使用 UTF-8 修改版编码将一个字符串写入基础输出流;

public static void main(String[] args) throws Exception {
	//创建FileOutputStream对象
	FileOutputStream fos=new FileOutputStream("d:/1.txt");
	//创建DataOutputStream对象
	DataOutputStream dos=new DataOutputStream(fos);
	//写入磁盘文件数据
	dos.writeUTF("使用writeUTF()方法写入数据");
//	dos.writeBytes("使用writeBytes()方法写入数据");
//	dos.writeChars("使用writeChars()方法写入数据");
	dos.close();//关闭流
	//创建FileInputStream对象
	FileInputStream fis=new FileInputStream("d:/1.txt");
	//创建DataInputStream对象
	DataInputStream dis=new DataInputStream(fis);
	System.out.print(dis.readUTF());                 //将文件输入输出
  }
}

九、一言不合就上题:文件及文件夹的拷贝实例

public static void main(String[] args) {
	File f=new File("d:/英雄时刻");
	new File(f, f.getName()).mkdir();
	copyDirectory(new File("d:/英雄时刻"),new File( "e:/"));
	try {
		copyFile(new File("d:/1.txt"), new File("e:/1.txt"));
	} catch (IOException e) {
		e.printStackTrace();
}
	System.out.println("拷贝完毕!");
}
//文件的复制
public static void copyFile(File f1,File f2) throws IOException{
	BufferedInputStream bis=new BufferedInputStream(new FileInputStream(f1));
	BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream(f2));
	byte [] b=new byte[512];
			int len;
	while((len=bis.read(b))!=-1){
		bos.write(b, 0, len);
	}
	bos.flush();
	if(bos!=null)
	bos.close();
	if(bos!=null)
	bis.close();
	
}
//文件夹的复制
public static void copyDirectory(File f1,File f2){
	File f=new File(f2, f1.getName());
	f.mkdir();
	File []fl=f1.listFiles();
	for (File file : fl) {
		if(file.isDirectory()){
			copyDirectory(file, f);
		}
		else{
			try {
				copyFile(file, new File(f,file.getName()));
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

十、IOException异常类的子类

1.public class  EOFException :   非正常到达文件尾或输入流尾时,抛出这种类型的异常。

2.public class FileNotFoundException:   当文件找不到时,抛出的异常。

3.public class InterruptedIOException:   当I/O操作被中断时,抛出这种类型的异常。

为什么要有异常处理
因为在输入输出中,会出现一些你想不到的异常,所以要用try catch语句捕获这些异常并做友好提示,方便我们的操作
比如读文件时你的文件不存在 它会出现系统错误,为了方便,捕获他做友好提示很方便继续操作

更多内容:
http://blog.csdn.net/hguisu/article/details/7418161
http://blog.csdn.net/xfhuajian/article/details/6439374

 


 

你可能感兴趣的:(Java之旅)