黑马程序员-IO流(核心IO流)

-----------android培训java培训、java学习型技术博客、期待与您交流! ------------



一、操作基本数据类型的流对象



1、概述:


(1)操作基本数据类型的流对象:DataInputStream和DataOutputStream
(2)这两个读写对象,可用于操作基本数据类型的流对象,包含读写各种基本数据类型的方法

2、特有方法:


                                  读                                                    写

int型                 writeInt(int n)                               int readInt()

boolean型      writeBoolean(boolean b)         boolean readBoolean()

double型        writeDouble(double d)              double readDouble()


3、代码示例:

import java.io.*;

class DataStreamDemo {
	public static void main(String[] args) throws IOException {
		writeData();
		readData();

	}

	public static void writeUTFDemo() throws IOException {
		DataOutputStream dos = new DataOutputStream(new FileOutputStream(
				"utfdate.txt"));

		dos.writeUTF("你好");

		dos.close();
	}

	public static void readData() throws IOException {
		DataInputStream dis = new DataInputStream(new FileInputStream(
				"data.txt"));

		int num = dis.readInt();
		boolean b = dis.readBoolean();
		double d = dis.readDouble();
		// 读取基本数据类型。
		System.out.println("num=" + num);
		System.out.println("b=" + b);
		System.out.println("d=" + d);

		dis.close();
	}

	public static void writeData() throws IOException {
		DataOutputStream dos = new DataOutputStream(new FileOutputStream(
				"data.txt"));

		dos.writeInt(234);
		dos.writeBoolean(true);
		dos.writeDouble(9887.543);// 写入基本数据类型。
		dos.close();

	}
}

/*output:
num=234
b=true
d=9887.543
*/



二、操作数组和字符串


1、操作字节数组的对象:ByteArrayInputStream和ByteArrayOutputStream


(1)这个对象并没有调用底层资源,所以不用关闭流资源
(2)存入的是缓冲区,并未用到键盘和硬盘,所以不需要抛任何IO异常
(3)对象中封装了数组
(4)构造函数:
1)ByteArrayInputStream:在构造函数的时候,需要接受数据源,而且数据源是一个字节数据。
2)ByteArrayOutputStream:在构造函数的时候,不用定义数据目的,因为该对象中已经在内部封装了可变长度的字节数组,这就是数据的目的地
(5)因为两个流对象都是操作的是数据,并没有使用系统资源,所以不用进行close关闭。
(6)其实就是用流的思想操作数组
(7)特有方法:writeTo(OutputStream out) 这个方法用到了字节输出流,有异常存在,需要抛IO异常

 

代码示例1:

/*
 * ByteArrayOutputStream把内存中的数据写到字节数组中,
 * 而ByteArrayInputStream又把字节数组中的字节以流的形式读出,
 * 从而实现了对同一个字节数组的操作
 */
import java.io.*;

public class Test {
	public static void main(String[] args) {
		int a = 0;
		int b = 1;
		int c = 2;
		ByteArrayOutputStream bout = new ByteArrayOutputStream();
		// 将数据写入输出流的内存缓冲区
		bout.write(a);
		bout.write(b);
		bout.write(c);//利用ByteArrayOutputStream把所有的变量收集到一起,然后一次性把数据发送出去。

		// 创建字节数组,并把ByteArrayOutputStream内存缓冲区中的数据以 byte 数组的形式写入字节数组
		byte[] shuZu = bout.toByteArray();
		for (int i = 0; i < shuZu.length; i++)
			System.out.println(shuZu[i]);
		System.out.println("***********************");

		//ByteArrayInputStream把字节数组shuZu作为其缓冲区数组,并把shuZu中的字节以输入流的形式读出
		ByteArrayInputStream bin = new ByteArrayInputStream(shuZu);
		while ((b = bin.read()) != -1) {
			System.out.println(b);
		}
	}
}

/*output:
0
1
2
***********************
0
1
2
*/

代码示例2:

import java.io.*;

class ArrayStreamDemo {
	public static void main(String[] args) {
		// 数据源
		ByteArrayInputStream bais = new ByteArrayInputStream(
				"ABCDEFF".getBytes());
		// 数据目的
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		int by = 0;
		// 读取和写入数据
		while ((by = bais.read()) != -1) {
			baos.write(by);
		}
		System.out.println(baos.size());

		System.out.println(baos.toString());

		try {
			// 方法,此处抛异常,所以上面需要抛出去
			baos.writeTo(new FileOutputStream("a.txt"));
		} catch (IOException e) {
			throw new RuntimeException("写入文件失败");
		}

	}
}

/*output:
7
ABCDEFF
*/


2、对应的操作字符数组和字符串的对象:


字符数组流对象:CharArrayReader和CharArrayWriter
字符串流对象:   StringReader和StringWriter


三、字节流常见需求:


需求1:在硬盘上创建一个文件并写入信息(字节流写入时没有刷新)

import java.io.*;

public class ByteDemo {

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

		FileOutputStream fos = new FileOutputStream("g:\\filestream.txt");
		fos.write(97);// 写入一个字节,int:97代表写入char:a
		fos.write("也可以写入字节数组".getBytes());// 通常使用此种方式写入,直观!
		fos.close();

	}
}

需求2:在硬盘已有文件上续写数据(字节流写入时没有刷新)

import java.io.*;

public class ByteDemo {

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

		FileOutputStream fos = new FileOutputStream("g:\\filestream.txt", true);
		fos.write("创建字节写入流时,传进去一个true参数就可以继续写入信息".getBytes());
		fos.close();

	}
}

需求3:读取硬盘上的文件

import java.io.*;

public class ByteDemo {

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

		FileInputStream fis = new FileInputStream("g:\\filestream.txt");
		// 第一种读法:一个字节一个字节的读(此种读法慢)
		int ch = 0;
		while ((ch = fis.read()) != -1) {
			System.out.print((char) ch);
		}
		System.out.println("over");

		// 第二种读法:利用字节数组读(此种读法效率有一定提高)
		byte[] buf = new byte[1024];
		int len = 0;
		while ((len = fis.read()) != -1) {
			System.out.print(new String(buf, 0, len));
		}
		System.out.println("over");
	}
}

需求4:拷贝字节文件,如图片或者MP3或者电影

import java.io.FileInputStream;  
import java.io.FileNotFoundException;  
import java.io.FileOutputStream;  
import java.io.IOException;  
  
public class CopyPhotos {  
  
    /**  
     * 复制一个图片:  
     * 1.用字节读取流和图片关联  
     * 2.用字节写入流对象创建一个图片文件,用于存储获取到得图片数据  
     * 3.第一种拷贝:不带缓冲流,只用数组做缓冲(慢,还是效率问题)
     * 4.通过循环读写,完成数据的存储  
     */  
    public static void main(String[] args) {  
          
         FileOutputStream fos=null;  //定义字节流  
         FileInputStream  fis=null;  
           
         try {  
                 
             fis=new FileInputStream("g://a.jpg");  
             fos=new FileOutputStream("h://b.jpg");  
                 
                 
               //定义数组,作为两个字节流之间的中转站  
               byte[] buf=new byte[1024];   
               int len=0;  
               while((len=fis.read(buf))!=-1){  //循环读写,完成数据的存储  
                     
                    fos.write(buf,0,len);  
               }  
                 
                 
        } catch (FileNotFoundException e) {  
              
            e.printStackTrace();  
        } catch (IOException e) {  
              
            e.printStackTrace();  
        }finally{  
              
              //释放流资源  
             if(fis!=null){  
                   
                 try {  
                    fis.close();  
                } catch (IOException e) {  
              
                    e.printStackTrace();  
                }  
                   
             }  
               
             if(fos!=null){  
                 try {  
                    fos.close();  
                } catch (IOException e) {  
                      
                    e.printStackTrace();  
                }  
                   
             }  
               
        }  
          
    }  
  
}  


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

public class CopyMp3 {

	/**
	 * 复制一个MP3文件 1.用字节读取流和MP3文件关联 2.用字节写入流对象创建一个MP3文件,用于存储获取到得图片数据
	 * 3.第二种拷贝:带缓冲流,高效 4.通过循环读写,完成数据的存储
	 */
	public static void main(String[] args) {

		FileInputStream fis = null; // 操作数据不是纯文本定义字节流
		FileOutputStream fos = null;

		BufferedInputStream bufis = null; // 定义缓冲区
		BufferedOutputStream bufos = null;

		long start = System.currentTimeMillis(); // 复制文件开始时间

		try {
			fis = new FileInputStream("g://a.mp3"); // 读取,写入文件
			fos = new FileOutputStream("h://b.mp3");

			bufis = new BufferedInputStream(fis);
			bufos = new BufferedOutputStream(fos);

			int len = 0;
			while ((len = bufis.read()) != -1) {

				bufos.write(len);

			}

			long end = System.currentTimeMillis(); // 复制文件结束时间
			System.out.println(end - start + "毫秒"); // 复制文件花费上时间

		} catch (FileNotFoundException e) {

			e.printStackTrace();
		} catch (IOException e) {

			e.printStackTrace();
		} finally {

			// 关闭流资源
			if (bufis != null) {
				try {
					bufis.close();
				} catch (IOException e) {

					e.printStackTrace();
				}
			}

			if (bufos != null) {
				try {
					bufos.close();
				} catch (IOException e) {

					e.printStackTrace();
				}

			}

		}
	}

}


四、字符流常见需求(字符流写入时要刷新)


需求1:在硬盘上创建一个文件并写入信息

import java.io.*;

public class CharDemo {

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

		// 用字符写入流:FileWriter
		FileWriter fw = new FileWriter("g:\\filewriter.txt");
		fw.write("输入信息");
		fw.write("也可以写入字符数组".toCharArray());
		fw.flush();
		fw.close();

	}
}

需求2:在原有文件上续写数据

import java.io.*;

public class CharDemo {

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

		FileWriter fw = new FileWriter("g:\\filewriter.txt", true);
		fw.write("还可以续写信息");
		fw.write("也可以写入字符数组".toCharArray());
		fw.flush();
		fw.close();

	}
}

需求3:读取硬盘上的文本文件,并将数据打印在控制台

import java.io.*;

public class CharDemo {

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

		FileReader fr = new FileReader("g:\\filewriter.txt");
		// 第一种读取方法:一个一个字节的读
		int ch = 0;
		while ((ch = fr.read()) != -1)
			// ch = fr.read();
			System.out.print((char) ch);
		fr.close();

	}
}

需求4:拷贝文本文件


(1)用数组做缓冲区

import java.io.*;

public class CharDemo {

	/**
	 * 拷贝文件步骤: 1.创建一个文件B,用于存储读取A文件内数据 2.定义读取流和A文件关联 3.定义数组,作为读取流和写入流之间联系的桥梁
	 * 4.通过不断的读写完成数据存储 5.关闭流资源
	 */
	public static void main(String[] args) {

		FileWriter fw = null; // 定义写入流
		FileReader fr = null; // 定义读取流

		try {
			fw = new FileWriter("g://hello.txt"); // 创建写入流
			fr = new FileReader("h://demo.txt"); // 创建读取流

			char[] buf = new char[1024]; // 创建数组作为连接写入流与读取流之间的联系桥梁

			int len = 0; // 数组长度变量

			while ((len = fr.read(buf)) != -1) { // 将读取的元素存到数组中

				fw.write(buf, 0, len); // 将数组中的元素写入到写入流中
			}

		} catch (IOException e) {
			System.out.println("拷贝文件失败");
			e.printStackTrace();
		} finally {
			if (fw != null) {
				try {
					fw.close(); // 将写入流中的数据冲入到保存区域并关闭写入流
				} catch (IOException e) {
					System.out.println("关闭写入流失败。。。");
					e.printStackTrace();
				}
				if (fr != null) {
					try {
						fr.close();
					} catch (IOException e) {
						System.out.println("关闭读取流失败。。。");
						e.printStackTrace();
					}
				}

			}
		}

	}

}


(2)用装饰类缓冲区

import java.io.*;

public class CharDemo {

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

		/*
		 * 利用缓冲区提高数据读写效率 (无缓冲区就相当于一滴一滴的喝水,有缓冲区就相当于一杯一杯的喝水)
		 */
		BufferedReader bufr = new BufferedReader(new FileReader(
				"g:\\filewriter.txt"));
		BufferedWriter bufw = new BufferedWriter(new FileWriter(
				"h:\\copyfilewriter.txt"));
		String line = null;
		while ((line = bufr.readLine()) != null) {
			bufw.write(line);
			bufw.newLine();
			bufw.flush();
		}
		bufr.close();
		bufw.close();

	}
}

五、转换流:


1、转换流的引入

键盘录入转成大写输出,并判断over结束的程序中使用了到对字节数据的存储,并对回车符进行判断。

发现这个功能和readLine方法一致。
因为readLine是字符流BufferedReader对象中的方法。而键盘录入是字节流。
能不能将这个字节读取流转成字符流呢?因为BufferedReader只能对字符流进行装饰 。
这就用到了转换流


2、分类:

|---InputStreamReader:是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。
|---OutputStreamWriter:是字符流通向字节流的桥梁:可使用指定的 charset 将要写入流中的字符编码成字节。它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符集。

 

3、代码示例:


步骤1:读取一个键盘录入

import java.io.*;

public class transform {

	public static void main(String[] args) throws IOException {
		InputStream in = System.in;// 创建一个键盘录入流,流不关则可以一直录入
		int by1 = in.read();// 一次读一个字节
		int by2 = in.read();// 一次读一个字节
		System.out.println((char) by1);// 假设键盘录入的是abcd,则打印a
		System.out.println((char) by2);// 假设键盘录入的是abcd,则打印b
		in.close();
	}

}


步骤2:键盘录入一行数据打印一行数据,如果录入的是over则结束录入

import java.io.*;

public class transform {

	public static void main(String[] args) throws IOException {
		InputStream in = System.in;
		StringBuilder sb = new StringBuilder();
		while (true) {
			int ch = in.read();
			if (ch == '\r')
				continue;
			if (ch == '\n') {
				String line = sb.toString();
				if ("over".equals(line))
					break;
				System.out.println(line.toUpperCase());// 输出大写
				sb.delete(0, sb.length());// 清除上一行录入的数据

			} else
				sb.append((char) ch);
		}
		in.close();

	}

}


步骤3:发现需求2中其实就是读一行的原理,故引入字节通向字符的桥梁:InputStreamReader

import java.io.*;

public class transform {

	public static void main(String[] args) throws IOException {
		// 为提高效率加入缓冲区:
		BufferedReader bufr = new BufferedReader(new InputStreamReader(
				System.in));
		String line = null;
		while ((line = bufr.readLine()) != null) {
			if ("over".equals(line))
				break;
			System.out.println(line.toUpperCase());// 输出大写
		}
		bufr.close();

	}

}


步骤4:键盘录入数据并打印到控制台

import java.io.*;

public class transform {

	public static void main(String[] args) throws IOException {
		BufferedReader bufr = new BufferedReader(new InputStreamReader(
				System.in));
		BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(
				System.out));
		String line = null;
		while ((line = bufr.readLine()) != null) {
			if ("over".equals(line))
				break;
			bufw.write(line.toUpperCase());
			bufw.newLine();
			bufw.flush();
		}
		bufr.close();
		bufw.close();

	}

}


步骤5:将键盘录入的数据存储到硬盘文件

/*则只需将(4)中的
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));
改为:
BufferedWriter bufw = new BufferedWriter(new FileWriter("g:\\demo.txt"));
 */

import java.io.*;

public class transform {

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

		BufferedReader bufr = new BufferedReader(new InputStreamReader(
				System.in));
		BufferedWriter bufw = new BufferedWriter(new FileWriter("g:\\demo.txt"));
		String line = null;
		while ((line = bufr.readLine()) != null) {
			if ("over".equals(line))
				break;
			bufw.write(line.toUpperCase());
			bufw.newLine();
			bufw.flush();
		}
		bufr.close();
		bufw.close();
	}

}


步骤6:将硬盘文件的数据打印到控制台

/*则只需将(4)中的
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
改为:
BufferedReader bufr = new BufferedReader(new FileReader("g:\\demo.txt"));
即:*/

import java.io.*;

public class transform {

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

		BufferedReader bufr = new BufferedReader(new FileReader("g:\\demo.txt"));
		BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(
				System.out));
		String line = null;
		while ((line = bufr.readLine()) != null) {
			if ("over".equals(line))
				break;
			bufw.write(line.toUpperCase());
			bufw.newLine();
			bufw.flush();
		}
		bufr.close();
		bufw.close();

	}

}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值