黑马程序员第五季——IO流

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------



一、什么是流? 
流就是字节序列的抽象概念,能被连续读取数据的数据源和能被连续写入数据的接收端就是流,流机制是Java及C++中的一个重要机制,通过流我们可以自由地控制文件、内存、IO设备等数据的流向。
而IO流就是用于处理设备上的数据,如:硬盘、内存、键盘录入等。IO流根据处理类型的不同可分为字节流和字符流,根据流向的不同可分为输入流和输出流。

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

  流按流向分为:输入流和输出流。

   字节流的抽象基流:InputStreamOutputStream

   字符流的抽象基流:ReaderWriter

二 字节流

字节流是最基本的流,文件的操作、网络数据的传输等等都依赖于字节流。而字符流常常用于读取文本类型的数据或字符串流的操作等等。

(1)InputStream的API
 
1、public int read()
从输入流读取下一个数据字节。返回 0 到 255 范围内的 int 字节值。如果因已到达流末尾而没有可用的字节,则返回值 -1。
 
2、public int read(byte[] b)
从输入流中读取一定数量的字节并将其存储在缓冲区数组 b 中。以整数形式返回实际读取的字节数。如果因为流位于文件末尾而没有可用的字节,则返回值 -1;否则,至少可以读取一个字节并将其存储在 b 中。此方法等同于read(b, 0, b.length)
 
3、public int read(byte[] b, int off, int len)
将输入流中最多 len 个数据字节读入字节数组。尝试读取多达 len 字节,但可能读取较少数量。以整数形式返回实际读取的字节数。如果由于已到达流末尾而不再有数据,则返回 -1。
参数:
b - 读入数据的缓冲区。
off - 在其处写入数据的数组 b 的初始偏移量。
len - 要读取的最大字节数。
 (2)OutputStream的API
 
1、public void write(int b)
将指定的字节写入此输出流。write 的常规协定是:向输出流写入一个字节。要写入的字节是参数 b 的八个低位。b 的 24 个高位将被忽略。
 
2、public void write(byte[] b)
将 b.length 个字节从指定的字节数组写入此输出流。write(b) 的常规协定是:应该与调用 write(b, 0, b.length) 的效果完全相同。
 
3、public void write(byte[] b,
                  int off,
                  int len)
将指定字节数组中从偏移量 off 开始的 len 个字节写入此输出流。write(b, off, len) 的常规协定是:将数组 b 中的某些字节按顺序写入输出流;元素 b[off] 是此操作写入的第一个字节,b[off+len-1] 是此操作写入的最后一个字节。
参数:
b - 数据。
off - 数据中的初始偏移量。
len - 要写入的字节数。
 
4、public void flush()
刷新此输出流并强制写出所有缓冲的输出字节。flush 的常规协定是:如果此输出流的实现已经缓冲了以前写入的任何字节,则调用此方法指示应将这些字节立即写入它们预期的目标。
 
(3)几点原则
 
1、不管是输入还是输出流,使用完毕后要close(),如果是带有缓冲区的输出流,应在关闭前调用flush()。
 
2、应该尽可能使用缓冲区,来减少IO次数,以提高性能。
 
3、能用字符流处理的不用字节流。
下面我写了一个例子程序,帮助大家理解:
import java.io.FileInputStream;
public class myInputStream {

	public static void main(String[] args) throws Exception {
		T t = new T();
		t.getClassName();

	}

}

class T {

	public void getClassName() throws Exception {
		FileInputStream fileInputStream = new FileInputStream(
				"d:/11.txt");

		int t=fileInputStream.read();
		while(t!=-1){

		System.out.print((char)t);
                                  t=fileInputStream.read();
		}
		fileInputStream.close();
	}
}

三 字符流
在程序中一个字符等于两个字节,Java为我们提供了Reader和Writer两个专门操作字符流的类。
ASCII 码支持英文,但不支持东亚地区的字符,而Unicode支持。
Java语言使用 Unicode来表示字符和字符串 ,一个Unicode字符用两个字节表示的,也就是 16位
Reader和Writer都是抽象类,有较多的子类,与字节流相似,他们用来创建具体的字符流对象进行IO操作。
字符流的读写方法和 字节流的相应方法是很类似的,但读写对象使用的是字符,这里就不再累赘阐述。
还是看下面这段代码,帮助大家理解吧。
public static void main(String[] args) throws Exception {  
  
   // 声明一个File对象  
  
   File file = new File("hellowolrd.txt");  
  
  
  
   // 声明一个Write对象  
  
   Writer writer = null;  
  
   // 通过FileWriter类来实例化Writer类的对象并以追加的形式写入  
  
   writer = new FileWriter(file, true);  
  
  
  
   // 声明一个要写入的字符串  
  
   String str = "字符串形式写入Helloworld";  
  
   // 写入文本文件中  
  
   writer.write(str);  
  
   // 刷新  
  
   writer.flush();  
  
   // 关闭字符输出流  
  
   writer.close();  
  
}  

四 转换流

转换流是指将字节流与字符流之间的转换,包含两个类:InputStreamReader和OutputStreamWriter。

转换流的出现方便了对文件的读写,她在字符流与字节流之间架起了一座桥梁,使原本毫无关联的两种流操作能够进行转化,提高了程序的灵活性。

何时使用转换流?
1.
如果使用非默认编码保存文件或者读取文件时,需要用到转换流,因为字节流的重载构造方法中有指定编码格式的参数,而FielReader 与 FileWriter 是默认编码的文本文件
比如:
当我们使用默认GBK编码保存文本时,下面2句代码其实是一样的效果,
new OutputStreamWriter(new FileOutputStream("out.txt"))
new FileWriter("out.txt")
当要求保存为其他编码比如UTF-8时,就要这样写
new OutputStreamWriter(new FileOutputStream("out.txt"),"UTF-8")
而如果要读取一个UTF-8编码的文本文件时,同样的要用
new InputStreamReader(new FileInputStream("in.txt"),"UTF-8");
而不能用new FileWriter("in.txt")
2.
当文件是字节文件时:
     读取:提高效率用BufferedReader的独有快速方法时,需要转换。FileInputStream BufferedReader
     输出:提高效率一般用BufferedWriter缓存,需要转换。FileOutputStream  BufferedWriter
当文件是字符流时:需要转换。
计算机处理的是字节数据
          读取时:将字符转换为字节,FileReader  BufferedRead
          输出时:将字节转换为字符,FileWriter BufferedWriter
总之,不论是字节文件还是字符文件,提高效率一般会用转换流的。

还是废话不多说,上代码:

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.InputStreamReader;

/**
 * 
 */

/**
 * @author lenovo
 * 
 */
public class myInputStream {

	public static void main(String[] args) throws Exception {
		T t = new T();
		t.getClassName();

	}

}

class T {

	public void getClassName() throws Exception {
		File f = new File("src/config/test.properties");
		FileInputStream fileInputStream = new FileInputStream(f);
		InputStreamReader inputStreamReader = new InputStreamReader(
				fileInputStream);
		BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
     	String s = bufferedReader.readLine();
		StringBuffer str=new StringBuffer();
		//String s;

		// int t = fileInputStream.read();

		// FileReader fileReader=new FileReader(f);

		// int t=fileReader.read();
		while (s != null) {
			 str.append(s);

			//System.out.print(str);
			s = bufferedReader.readLine();
			// t = fileInputStream.read();
			// t=fileReader.read();
		}
		
		/**
		 * readLine()每读取一行,指针会自动下移到下一行,直到末尾为空,返回null
		 */
		while((s=bufferedReader.readLine())!=null){
			System.out.print(s);
			
		}
		bufferedReader.close();
	}
}
五 缓冲流

java IO通过缓冲流来提高读写效率,普通的字节、字符流都是一个字节一个字符这样读取的,而缓冲流则是将数据先缓冲起来,然后一起写入或者读取出来。

经常使用的是readLine()方法,表示一次读取一行数据。

package com.io;


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

public class TestBufferedString {

    public static void main(String[] args) throws Exception {
        // 指定要读取文件的缓冲输入字节流
        BufferedInputStream in = new BufferedInputStream(new FileInputStream("F:\\photo\\IMG0460A.jpg"));
        File file = new File("F:\\IMG0460A.jpg");
        if (file != null) {
            file.createNewFile();
        }
        // 指定要写入文件的缓冲输出字节流
        BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file));
        byte[] bb = new byte[1024];// 用来存储每次读取到的字节数组
        int n;// 每次读取到的字节数组的长度
        while ((n = in.read(bb)) != -1) {
            out.write(bb, 0, n);// 写入到输出流
        }
        out.close();// 关闭流
        in.close();
    }

}

六 字节数组流 与数据流

 ByteArrayInputStream   :字节数组输入流

ByteArrayOutputStream :字节数组输出流

DataInputStream     :数据输入流

DataOutputStream  :数据输出流

我写这个是非常实用的,大家玩网络游戏的时候,我们怎么知道彼此间的数据,

往往是将数据转换成字节,然后发送,你接受后然后再将字节转换成数据显示。

下面,我将写一个程序,是将一个long类型的数写入到字节数组中,然后再将字节数组转换成long类型的数。

废话不多说,上代码

public class Output {
        

        public static void main(String[] args) throws IOException {
                long i=10;
                byte[] b;
                //变量在定义的时候可以赋值,但在调用的时候就要有值。
                //成员变量,系统会初始化,赋默认值。
                //System.out.print(i);
                ByteArrayOutputStream bos=new ByteArrayOutputStream();
                DataOutputStream dos=new DataOutputStream(bos);
                dos.writeLong(i);
                b=bos.toByteArray();
                dos.close();
                bos.close();
                ByteArrayInputStream bis=new ByteArrayInputStream(b);
                DataInputStream dis=new DataInputStream(bis);
                long a=dis.readLong();
                System.out.print(a);





何时使的。



















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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值