Java基础---I/O流---字节流+字符流

                                                         IO流基本导图


----字节流
     
        输入字节流:
        ------| InputStream                  输入字节流基类
        -----------| FileInputStream      输入字节流管道
        -----------| BufferedInputStream  缓冲输入字节流(内部维护了一个8kb的字节数组) 

        输出字节流:
        ------| OutputStream                 输出字节流基类
        -----------| FileOutputStream     输出字节流管道
        -----------| BufferedOutputStream 缓冲输出字节流(内部维护了一个8kb的字节数组)


---字符流 = 字节流+ 编码(解码)

        输入字符流
        -----| Reader                       输入字符流基类
            -----------| FileReader      输入字符流管道
            -----------| BUfferedReader  缓冲输入字符流(维护了一个1024个长度的字符数组)                                                                 拓展功能---->readLine()
        输出字符流
        -----| Writer  抽象类             输出字符流基类
            -----------| FileWriter         输出字符流管道
            -----------| BuffereWriter   缓冲输出字符流(维护了一个1024个长度的字符数组)                                                                 拓展功能---->newLine()


File类仅能
        获取文件的属性数据
        修改文件的属性数据
        不能读取文件内容数据
         
操作文件内容数据需要学习---> "IO流"技术
IO流类别:
     1. 流向划分:输入流 + 输出流
        以当前程序作为参照物,数据流入则使用输入流, 数据流出则使用输出流。
     2. 处理单位:
                  字节流:读取文件的(纯)字节数据 
                  字符流:读取字节数据+解码字节数据


输入字节流:
------| InputStream                输入字节流基类
-----------| FileInputStream      输入字节流管道
-----------| BufferedInputStream  缓冲输入字节流(内部维护了一个8kb的字节数组) 

使用 FileInputStream 读取文件数据:
    1.找到目标文件
    2.建立数据的输入通道
    3.读取文件的数据
--------------------------------------------------------------

先理解两个方法:string和read
public int read(byte[] b) throws IOException
从输入流中将最多 b.length 个字节的数据读入一个字节数组中 
    覆盖:类 InputStream 中的 read
    参数:b 缓冲数组 
    返回:读入缓冲区的字节总数,如果已经到达文件末尾,则返回 -1。 
    抛出:IOException - 如果发生 I/O 错误。
public String(byte[] bytes, int offset, int length)
构造一个新的 String,方法是使用指定的字符集解码字节的指定子数组。

    新的 String 的长度是一个字符集函数,因此不能等于该子数组的长度。 
    参数:
    bytes - 要解码为字符的字节
    offset - 要解码的首字节的索引
    length - 要解码的字节数

方式一:使用 循环 配合 缓冲数组 读取(用这个)

    File file = new File("F:\\a.txt");   //获取目标文件对象
    //建立数据的通道
    FileInputStream fileInputStream= new FileInputStream(file);
    //读取数据
    byte[] buf = new byte[1024];  //缓冲字节数组的长度一般都是1024的倍数。  
    int length = 0 ;               //记录本次读取的自己个数。
    while((length = fileInputStream.read(buf))!=-1){
        System.out.print(new String(buf,0,length));
    }
    fileInputStream.close();    //关闭资源(释放资源文件)

注意用System.out.print   不要用System.out.println因为读取完会换行

--------------------------------------------------------------------
方式二:使用(缓冲数组)字节数组读取  :无法完整读取一个文件的数据 

    //找到目标文件
    File file = new File("F:\\a.txt");
    //建立数据的通道
    FileInputStream fileInputStream= new FileInputStream(file);
    //创建一个字节数组,读取文件数据
    byte[] buf = new byte[10]; 
    //read(byte[] buf) 先把读取到的数据存储到字节数组中,然后返回的是本次读取到字节数。 
    int length = fileInputStream.read(buf);  
    System.out.println("读取到的内容:"+ new String(buf,0,length));

------------------------------------------------------------------------------------------------------------------------
方式三:每次读取一个字节的数据,可以读取完整文件数据  (效率低)

		// 第一步:找到目标文件
		File file = new File("g:/a.txt");
		// 第二步: 建立数据通道
		FileInputStream fileInputStream = new FileInputStream(file);
		// 第三步:读取文件的数据
		int content = 0; // 用于保存读取到的数据
		while ((content = fileInputStream.read()) != -1) {
			// read() 方法如果读取了文件的末尾则返回-1表示。
			System.out.print((char) content);
		}
		// 关闭资源
		fileInputStream.close();

================================================================

输出字节流:
------| OutputStream              输出字节流基类
-----------| FileOutputStream     输出字节流管道
-----------| BufferedOutputStream 缓冲输出字节流(内部维护了一个8kb的字节数组)
使用FileOutputStream步骤:
    1. 找到目标文件
    2. 建立数据的输出通道
    3.写入文件
理解write方法:
    public void write(byte[] b) throws IOException
        将 b.length 个字节从指定字节数组写入此文件输出流中
    write(byte[] b, int off, int len) 
FileOutputStream要注意的细节:
    1. new FileOutputStream 目标文件不存在会先创建目标然后再写入。
    2. new FileOutputStream(file) 目标文件已经存在,先清空然后再写入。
    3. 以追加的形式写入,需要使用new FileOutputStream(file,true) 构造函数。
    4. 使用write(int b)方法实际上只会把数据的低八位写出,其他位丢弃。

方式一:普通方法(getByte()方法转换成字节数组)   新建写入

		// 找到目标文件
		File file = new File("F:\\a.txt");
		// 建立数据的输出通道
		FileOutputStream fileOutputStream = new FileOutputStream(file);
		String data = "abcd";
		byte[] buf = data.getBytes(); // 转换成字节数组97 98 99 100
		fileOutputStream.write(buf, 0, 2); // 指定开始的索引值与字节个数写出。
		fileOutputStream.close();

方式二:追加写入FileOutputStream(file,true)

		// 找到目标文件
		File file = new File("F:\\a.txt");
		// 建立数据的输出通道
		FileOutputStream fileOutputStream = new FileOutputStream(file, true);
		// 第二个参数为true时,写入文件数据就是以追加的形式写入的
		// 准备数据, 把数据写出
		String str = "\r\nhello world";
		// 把字符串转成字节数组
		byte[] buf = str.getBytes();
		// 把字节数组写出
		fileOutputStream.write(buf);
		// 关闭资源
		fileOutputStream.close();

应用:拷贝图片

		File infile=new File("g:/a.jpg");
		File outfile=new File("f:/女神.jpg");
		FileInputStream fi=new FileInputStream(infile);
		FileOutputStream fo=new FileOutputStream(outfile);
		byte[] buf=new byte[1024];
		int length=0;
		while((length=fi.read(buf))!=-1){
			fo.write(buf, 0, length);
		}
		fo.close();
		fi.close();

IO异常处理:

应用一:比较正常的操作

	public static void main(String[] args) {
		readTest();
	}

	public static void readTest() {
		FileInputStream fileInputStream = null;
		try {
			File file = new File("g:\\a.txt");
			// 建立文件的输入流通道
			fileInputStream = new FileInputStream(file);
			// 建立缓冲字节数组读取文件数据
			byte[] buf = new byte[1024];
			int length = 0; // 记录本次读取的字节个数
			// 读取文件的数据
			while ((length = fileInputStream.read(buf)) != -1) {
				System.out.println(new String(buf, 0, length));
			}
		} catch (IOException e) {

			System.out.println("读取文件出错...");
			throw new RuntimeException(e);
			// 把真正的异常原因包装到RuntimeException中然后再抛出。

		} finally {
			try {
				// 关闭资源()
				if (fileInputStream != null) {
					fileInputStream.close();
					System.out.println("关闭资源成功...");
				}
			} catch (IOException e) {
				System.out.println("关闭资源失败...");
				throw new RuntimeException(e);
			}
		}
	}

应用二:拷贝文件   读写操作都具备的异常

	public static void main(String[] args) {

		copyImage();
	}

	// 拷贝图片
	public static void copyImage() {
		FileInputStream fileInputStream = null;
		FileOutputStream fileOutputStream = null;
		try {
			// 找到目标文件
			File inFile = new File("g:/a.jpg");
			File outFile = new File("F:/拷贝.jpg");
			// 建立数据的输入输出通道
			fileInputStream = new FileInputStream(inFile);
			fileOutputStream = new FileOutputStream(outFile);
			// 建立缓冲字节数组,边读边写
			byte[] buf = new byte[1024];
			int length = 0;
			while ((length = fileInputStream.read(buf)) != -1) {
				fileOutputStream.write(buf, 0, length);
			}
		} catch (IOException e) {
			System.out.println("拷贝出错了...");
			throw new RuntimeException(e);
			// 关闭资源的原则: 先开后关, 后开先关。
		} finally {
			try {
				if (fileOutputStream != null) {
					// 关闭资源
					fileOutputStream.close();
				}
			} catch (IOException e) {
				throw new RuntimeException(e);
			} finally {
				try {
					if (fileInputStream != null) {
						fileInputStream.close();
					}
				} catch (IOException e) {
					throw new RuntimeException(e);
				}
			}
		}

	}

缓冲字节流
          缓冲输入字节流    BufferedInputStream    作用: 提高读取文件数据的效率
         缓冲输出字节流    BufferedOutputStream   作用: 提高读写文件数据的效率
注意:凡是缓冲流都没有读写文件的能力,只是内部维护数组,提高效率(类似内存读取)
BufferedInputStream
        BufferedInputStream没有读取文件 数据的能力,但是又要读取文件的数据,这时候只能依赖一个具备读取文件数据能力的对象。

应用代码1:  读取效率不怎么高的,不想用

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

	// 因为内部判断,读取大文件时效率并不怎么高的不如用 :字节数组+循环
	public static void readTest() throws IOException {
		// 第一步:找到目标文件
		File file = new File("g:\\a.txt");
		// 第二步:建立文件与程序的输入通道
		FileInputStream fileInputStream = new FileInputStream(file);
		// 第三部:建立缓冲输入字节流
		BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
		// 读取文件数据
		int content = 0;
		while ((content = bufferedInputStream.read()) != -1) {
			System.out.print((char) content);
		}
		// 关闭资源
		bufferedInputStream.close();
	}

BufferedOutputStream
注意: 
     1.BufferedOutputStream的write方法,数据只是写入了BufferedOutputStream内部维护的字节数组中,只有调用BufferedOutputStream的close方法或者flush方法数据才会真正的写到硬盘上 ;或者内部维护的字节数组数据已经存储满,这时数据也会写到硬盘
     2. BufferedOutputStream的close方法实际上关闭的是传入的OutputStream对象的    close方法

应用代码1:

	public static void main(String[] args) throws IOException {
		// 找到目标文件对象
		File file = new File("f:/d.txt");
		// 建立数据的输出通道
		FileOutputStream fileOutputStream = new FileOutputStream(file);
		// 建立缓冲输出字节流
		BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
		// 写数据
		String data = "hello world";
		bufferedOutputStream.write(data.getBytes());
		// bufferedOutputStream.flush(); //把缓冲字节数组的数据写到硬盘上去。
		bufferedOutputStream.close();

	}

字符流 = 字节流+ 编码(解码)   读取 的数据是以字符为单位
    输入字符流
    -----| Reader                      
        -----------| FileReader      
        -----------| BUfferedReader 
    -----| Writer             
        -----------| FileWriter      
        -----------| BuffereWriter   
         字节流可以写中文,但不会读中文,因为字节流不会编码;字节流之所以可以写中文,是因为它借用了String类的getBytes方法,把字符串转成了数字。
          public byte[] getBytes()     使用平台默认的字符集将此 String 解码为字节序列,并将结果存储到一个新的字节数组中。

 FileWriter 使用步骤:    
     1. 找到目标文件
     2. 建立数据的输出通道
     3. 写出数据
     4. 关闭资源

    方式一:每次只会读取一个字符的数据

	public static void readTest1() throws IOException {
		// 找到目标对象
		File file = new File("f:\\a.txt");
		// 建立数据的输入通道
		FileReader fileReader = new FileReader(file);
		// 读取文件数据
		int content = 0;
		while ((content = fileReader.read()) != -1) { 
            // FileReader的read()方法每次读取一个字符的数据,如果读到
			// 了文件末尾返回-1表示。
			System.out.print((char) content);
		}
		// 关闭资源
		fileReader.close();
	}

// 方式二:缓冲数组(推荐)

	public static void readTest2() throws IOException {
		// 找到目标文件
		File file = new File("F:\\Demo1.java");
		// 建立数据的输入通道
		FileReader fileReader = new FileReader(file);
		// 建立缓冲字符数组,读取文件的数据
		char[] buf = new char[1024];
		int length = 0;
		// read(char[] buf) 读取到的字符数组存储到了字符数组中,返回了本次读取到的字符个数。
		while ((length = fileReader.read(buf)) != -1) {

			System.out.print(new String(buf, 0, length));
		}
		// 关闭资源
		fileReader.close();
	}

FileWriter 注意:
    1.使用new FileWriter(file)时,目标文件不存在则先创建;存在不创建。
    2.使用new FileWriter(file)构造方法时,先清空文本的数据,再写入新的数据。
    3.需要追加数据则需要使用 new FileWriter(file,true)构造方法
    4.使用FileWriter的write方法的时候,数据只是写入了FileWriter内部维护的字符数组中,把数据真正的写到硬盘上去,需要调用flush方法或者 是close方法或者是内部维护的字符数组已经满了,这时也会写到硬盘

	public static void readTest2() throws IOException {
		// 找到目标文件
		File file = new File("f:\\a.txt");
		// 建立数据的输入通道
		FileReader fileReader = new FileReader(file);
		// 建立缓冲字符数组,读取文件的数据
		char[] buf = new char[1024];
		int length = 0;
		// read(char[] buf) 读取到的字符数组存储到了字符数组中,返回了本次读取到的字符个数。
		while ((length = fileReader.read(buf)) != -1) {

			System.out.print(new String(buf, 0, length));
		}
		// 关闭资源
		fileReader.close();
	}

字符流和字节流选用:
    纯文本数据:使用字符流。(txt)
    非文本数据:使用字节流。(图片,视频,音频,word)

拷贝文件应用:

	public static void main(String[] args) throws IOException {
		// 找到目标文件
		File inFile = new File("g:/a.txt");
		File outFile = new File("E:/b.txt");
		// 建立数据 的输入输出通道
		FileReader fileReader = new FileReader(inFile);
		FileWriter fileWriter = new FileWriter(outFile);
		// 边写边读
		char[] buf = new char[1024];
		int length = 0;
		while ((length = fileReader.read(buf)) != -1) {
			fileWriter.write(buf, 0, length);
			// System.out.print(new String(buf, 0, length));
		}
		// 关闭资源
		fileWriter.close();
		fileReader.close();

	}

BufferedReader 缓冲输入字符流  作用:提高读取文件字符数据的效率
    对FileReader的功能进行了拓展---readLine()。
public String readLine() throws IOException
    读取一个文本行。
    返回:该行内容的字符串,如果已到达流末尾,则返回 null 

		File file = new File("G:\\a.txt");
		// 建立文件的输入通道。
		FileReader fileReader = new FileReader(file);
		// 缓冲输入字符流
		BufferedReader bufferedReader = new BufferedReader(fileReader);
		// 读取文件的数据
		String line = null;
		while ((line = bufferedReader.readLine()) != null) {
			System.out.println(Arrays.toString(line.getBytes()));
		}
		// 关闭资源
		bufferedReader.close();

BufferedWriter 缓冲输出字符流    作用:提高写入文件字符数据的效率

		// 找到目标文件
		File file = new File("f:\\a.txt");
		// 建立数据输出通道
		FileWriter fileWriter = new FileWriter(file, true);
		// 建立缓冲输出字符流
		BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
		// 准备数据,把数据写出
		bufferedWriter.newLine(); 
		bufferedWriter.write("奥特曼");
		// 刷新一个缓冲区
		bufferedWriter.close();

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值