java IO之字节流

1、IO(Input Output)流的概述

1、io的概念及其特点

    流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流.

    宏观上io有以下特点

    ·        IO流用来处理设备之间的数据传输。

    ·        Java对数据的操作是通过流(系统资源)的方式。

    ·        Java用于操作流的对象都在java.io包中。

    ·        流按操作数据分为两种:字节流与字符流。

    ·        流按流向分为:输入流,输出流。

2、io的体系结构


2、IO中常用的类

    1. File(文件特征与管理):用于文件或者目录的描述信息,例如生成新目录,修改文件名,删除文件,判断文件所在路径等。

     2. InputStream(二进制格式操作):抽象类,基于字节的输入操作,是所有输入流的父类。定义了所有输入流都具有的共同特征。

     3.OutputStream(二进制格式操作):抽象类。基于字节的输出操作。是所有输出流的父类。定义了所有输出流都具有的共同特征。

     4.Reader(文件格式操作):抽象类,基于字符的输入操作。

     5. Writer(文件格式操作):抽象类,基于字符的输出操作。

     6. RandomAccessFile(随机文件操作):一个独立的类,直接继承至Object.它的功能丰富,可以从文件的任意位置进行存取(输入输出)操作。

3、File详解

        1、File(文件特征与管理)

            用来将文件或者文件夹封装成对象。

            方便对文件与文件夹的属性信息进行操作。

            File对象可以作为参数传递给流的构造函数。

        2、File API

package com.xyq.file;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;

public class FileTest {

	public static void main(String[] args) throws IOException {

//		method_1();
//		method_2();
//		method_3();
//		method_4();
//		method_5();
//		method_6();
//		method_7();
		File file = new File("E:\\test");
		FilesFilter(file);
	}
	
    /*
     *  file类的四个静态常量
     *  public static String separator 与系统有关的目录分隔符 Windows中 :\ 
     *  public static char separatorChar Linux中: /
     *  public static String pathSeparator 与系统有关的路径分隔符 Windows中  ; 分号
     *  public static char pathSeparatorChar Linux中  : 冒号
     */
	public static void method_1(){
		File file = new File("E:\\");
		String s = file.separator;
		System.out.println(s);
		s = file.pathSeparator;
		System.out.println(s);
	}
	
	 /*
     * file 类的构造方法
     * 1. File(String pathName)
     * 2. File(String parent, String child)
     * 3. File(File parent, String child)
     */	
	public static void method_2(){
		
		File file = new File("E:\\KeCheng");
		File file2 = new File("E:\\","KeCheng");
		File file3 = new File(file, "");
		System.out.println(file);
		System.out.println(file2);
		System.out.println(file3);
	}
	
	 /* File类的创建方法 ,目标文件或者路径存在时,均会返回false
     *  1. boolean createNewFile() 创建文件,成功返回true
     *  2. boolean mkdir() 创建文件夹,成功返回true,只能创建一级目录
     *  3. boolean mkdirs() 创建多级文件夹
     */
	public static void method_3()throws IOException{
		File file = new File("E:\\text.txt");
		System.out.println(file.createNewFile());
		File file2 = new File("E:\\test\\test\\test");
		System.out.println(file2.mkdirs());
	}
	
	 /* File类的删除方法
     * 1. boolean delete() 删除指定目录或者文件,成功返回true,注意此删除不走回收站,文件夹不为空时没有办法删除
     * 2. void deleteOnExit() jvm退出前删除,
     */
	public static void method_4()throws IOException{
		File file = new File("E:\\test.txt");
		System.out.println(file.createNewFile());
		System.out.println(file.delete());
	}
	
	/* File类的判断方法
     * boolean exists() 判断构造方法中封装的路径或者文件是否存在
     * boolean isAbsolute() 判断构造方法中封装的路径是不是绝对路径,是返回真
     * boolean isDirectory() 判断是不是路径,是返回true
     * boolean isFile() 判断是不是文件,是返回true
     * boolean isHidden() 判断封装的路径(包括文件)是不是隐藏属性是返回true
     */
	public static void method_5(){
		File file = new File("E:\\abcde");
		System.out.println(file.exists());
		System.out.println(file.isAbsolute());
	}
	
	/*
     * File类的获取方法
     * 1.String getName() 获取封装路径最后部分的名字,此方法不会判断路径是否存在,使用之前最好判断
     * 2.String getParent() 返回封装路径的父路径
     * 3.File getParentFile() 返回封装路径的父路径的File对象
     * 4.String getAbsolutePath() 返回封装路径的绝对路径
     * 5.File getAbsoluteFile() 返回封装路径的绝对路径的File对象
     */
	
	public static void method_6(){
		File file = new File("scr");
		System.out.println(file.getAbsoluteFile().getParent());
	}
	
	 /*
     * File的list方法
     * 1. static File[] listRoots() 静态的方法,列出系统所以的根,光驱和移动设备存储也会算进去
     * 2. String[] list()返回File构造方法封装的路径下的所有文件和文件夹
     * 3. File[] listFiles()返回File构造方法封装的路径下的所有文件和文件夹,返回的Filed对象,带全路径
     */
	public static void method_7(){
		File []roots = File.listRoots();
		for(File file:roots){
			System.out.println(file);
		}
	}
	
	//递归过滤方法的实现,选出目录下的*.java文件
    //直接使用匿名内部内实现了FileFilter接口
	public static void FilesFilter(File file){
		
		File []files = file.listFiles(new FileFilter() {
			
			@Override
			public boolean accept(File pathname) {
				if (pathname.getName().endsWith(".java") || pathname.isDirectory()) {
					return true;
				} else {
					return false;
				}
			}
		});
		
		if(files != null){
			for(File file2:files){
				if(file2.isFile()){
					System.out.println(file2);
				}else {
					FilesFilter(file2);
				}
			}
		}
	}
}

4、IO流常用基类

  • 字节流的抽象基类: 
    • InputStream 读取一个文本文件中的数据
    • OutputStream 向一个文本文件中写入数据
    • 用输出流还是输入流 参考标准是内存
  • 字符流的抽象基类:

    • Reader
    • Writer

比较常用的字节流

  • FileInputStream
  • FileOutputStream
  • BufferedInputStream
  • BufferedOutputStream

4.1字节输出流——FileOutputStream

注意 在创建字节输出流对象用于操作文件,在对象初始化时必须明确数据存储的目的地,输出流所关联的目的地,如果不存在,则会自动创建;如果存在,则会覆盖。

具体用法  例  向一个文本文件中写入数据

package com.xyq.outputstream;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

public class FileOutputStreamTest {
	/*
     * 将数据写入到文件中。
     * 使用字节输出流。FileOutputStream。
     */
	public static void main(String[] args) throws IOException{
		
		//1、创建文件夹
		File dir = new File("tempFile");
		if(!dir.exists()){
			dir.mkdir();
		}
		//显示创建文件的路径
		System.out.println(dir.getAbsoluteFile().getParent());
		 // 2、创建字节输出流对象,用于操作文件,在对象初始化时必须明确数据存储的目的地。
         // 输出流所关联的目的地,如果不存在,会自动创建。如果存在,则覆盖。
		FileOutputStream fos = new FileOutputStream("tempFile\\test.txt");
		
		 // 3、调用输出流的写功能。
		fos.write("abcd".getBytes());
		
		//4、释放资源
		fos.close();
		
	}

}

4.2字节输入流——FileInputStream

具体用法  例  读取一个文本文件中的数据

4.2.1 read():一个一个字节的读

package com.xyq.outputstream;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

public class FileInputStreamTest {

	public static void main(String[] args) throws IOException{
		
		//1、为了确保文件一定在读之前是存在的,将字符串路径封装成File对象。
		File file = new File("tempFile\\test.txt");
		//2、判断文件是否存在
		if(!file.exists()){
			throw new RuntimeException("要读取的文件不存在");
		}
		
		//3、创建文件字节读取流对象时,必须明确与之关联的数据源。
		FileInputStream fis = new FileInputStream(file);
		
		//4、调用读方法
		int by = 0;
		while ((by = fis.read()) != -1) {
			System.out.println(by);
		}
		
		//5、关闭资源
		fis.close();
	}

}

4.2.2read(byte[] buf):先把字节存入到缓冲区字节数组中,一下读一个数组(常用)

package com.xyq.outputstream;

import java.io.FileInputStream;
import java.io.IOException;

public class FileInputStreamTest2 {
	
	//1、定义缓冲区的大小可以是1024的整数倍
	private static final int SIZE = 1024;

	public static void main(String[] args) {
		
		//2、创建文件字节读取流对象。
		FileInputStream fis = null;
		try {
			fis = new FileInputStream("tempFile\\test.txt");
			//3、创建一个字节数组。
			byte [] buf = new byte[SIZE];
			//4、调用读方法
			int len = 0;// len记录的是往字节数组里存储的字节个数。
			while((len = fis.read(buf)) != -1){
				// 将字节数组转成字符串,打印并看一下效果。
				System.out.println(new String(buf, 0, len));
			}
		} catch (IOException e) {
			// 将异常信息写入到日志文件中以进行记录。
		}finally {
			//5、关闭资源
			if(fis != null){
				try {
					fis.close();
				} catch (IOException e) {
					// 一般可以throw RuntimeException异常,或者将异常信息写入到日志文件中以进行记录。
					e.printStackTrace();
				}
			}
		}
		
	}

}

4.3缓冲流-BufferedInputStream、BufferedOutputStream

4.3.1有了InputStream和OutputStream为什么还要有BufferedInputStream和BufferedOutputStream?

因为不带缓冲的操作,每读一个字节就要写入一个字节,由于涉及磁盘的IO操作相比内存的操作要慢很多,所以不带缓冲的流效率很低。带缓冲的流,可以一次读很多字节,但不向磁盘中写入,只是先放到内存里。等凑够了缓冲区大小的时候一次性写入磁盘,这种方式可以减少磁盘操作次数,速度就会提高很多! 

同时正因为它们实现了缓冲功能,所以要注意在使用BufferedOutputStream写完数据后,要调用flush()方法或close()方法,强行将缓冲区中的数据写出。否则可能无法写出数据。

4.3.2 BufferedInputStream和BufferedOutputStream的具体用法

例 图片的复制
package com.xyq.outputstream;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class CopyPicBufferTest {
	
	//1、定义缓冲区的大小可以是1024的整数倍
	private static final int SIZE = 1024;
	
	public static void main(String[] args) {
		
		File oldFile = new File("tempFile\\1.jpg");
		
		File newFile = new File("tempFile\\abc.jpg");
		
		copyFile(oldFile, newFile);
	}
	
	public static void copyFile(File oldFile, File newFile){
		
		//2、创建流
		FileInputStream fis = null;
		BufferedInputStream bis = null;
		FileOutputStream fos = null;
		BufferedOutputStream bos = null;
		
		try {
			
			fis = new FileInputStream(oldFile);
			bis = new BufferedInputStream(fis);
			fos = new FileOutputStream(newFile);
			bos = new BufferedOutputStream(fos);
			
			//3、进行读写操作
			byte []byf = new byte[SIZE];
			int len = 0;// len记录的是往字节数组里存储的字节个数。
			//先读后写
			while((len = bis.read(byf)) != -1){
				bos.write(byf, 0, len);
			}
			bos.flush();//冲刷没有达到缓存限度的数据,确保数据全部写完
			System.out.println("复制完成。。。");
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			//4、关闭资源
			if(fis != null){
				try {
					fis.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			if(bis != null){
				try {
					bis.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			if(fos != null){
				try {
					fos.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			if(bos != null){
				try {
					bos.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		
	}
	
}


猜你喜欢

转载自blog.csdn.net/Strong997/article/details/79942282