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

来源:互联网 发布:255hh的新域名网站 编辑:程序博客网 时间:2024/05/22 03:41

------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
原创粉丝点击