14 IO流(下)


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



1、字节流					
	针对的字节数据,包括文本也包括媒体数据,如果是纯文本用字符流处理较为便捷。基本操作与字符流相同
        字节流所使用的缓冲区是一个byte[]。

    常用的对象:
        FileInputStream:用来读取文件的字节流
	    read()方法可以一次读取一个字节
	    read(byte[])方法可以一次读取若干字节到数组中
	FileOutputStream:用来写出文件的字节流
	    write(int)方法可以一次写出一个字节
	    write(byte[], int, int)方法可以一次写出数组中的一部分数据
	BufferedInputStream:字节流的输入缓冲区
	BufferedOutputStream:字节流的输出缓冲区

    字节流的缓冲区:
	同样是提高了字节流的读写效率。
	模拟BufferedInputStream原理:
	    将一个字节数组进行封装,通过方法将一批数据存入数组中,再通过数组的指针每一次返回数组中一个字节。
	    当数组元素全部取出后,在存入一批新的数据,重复此过程。
	    


当使用自定义的缓冲区时,居然出现的秒杀的情况,为什么会如此呢?
    因为mp3数据最终的二进制表现形式中,很容易出现连续N多1的情况,
    只要出现了连续的8个1,对于一个字节而言十进制体现形式就是-1。
    那么就满足while循环结束条件。程序终止。
    为了避免这种情况,在读到一个字节时,将该字节进行了提升变成int型。
    但是byte-1,变成int 还是-1。为了避免,在进行提升的过程中,保留的源字节的8为数据,并在前以补零方式进行提升。
 
    这样一个byte -1 变成了int 的255。这就避免了-1的情况。
    如何补的零呢?只要将读到的字节&255或者&0xFF.都可以。这也是read方法不是返回byte而返回int类型的原因。

    通过该过程就可以明确,read方法在对字节或者字符进行提升,而write方法在对提升后的int数据进行强转,
    只写出了最低的8位,或者最低的16位

 
2、转换流:
    为了实现字符和字节流之间的转换,出现了转换流。
    InputStramReader:字节通向字符的桥梁
    OutputStreamWriter:字符通向字节的桥梁
 
    转换流的由来:
	当读到的字节数据都是纯文本的时候,而且文本中出现中文字符,那么在解析该字节数据时就需要指定编码表。
	因为可以识别中的编码表不唯一。在使用转换流时,如果未指定编码表,那么默认使用本地码表。

    转换流的应用:
	字节流中的数据都是字符时,转成字符流操作更高效。

 
3、标准输入输出流:
    System类中的成员变量:in,out。
    它们各代表了系统标准的输入和输出设备。
    默认输入设备是键盘,输出设备是显示器。
    System.in的类型是InputStream。
    System.out的类型是PrintStream,是OutputStream子类FilterOutputStream的子类。
    carriage return 回车; line feed 换行 

    标准输入输出流示例:
	例:获取键盘录入数据,然后将数据流向显示器,那么显示器就是目的地。
	通过System类的setIn,setOut方法对默认设备进行改变。
	System.setIn(new FileInputStream(“1.txt”));//将源改成文件1.txt。
	System.setOut(new FileOutputStream(“2.txt”));//将目的改成文件2.txt
	因为是字节流处理的是文本数据,可以转换成字符流,操作更方便。
	BfferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
	BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));

 
4、流基本应用小节:
    流是用来处理数据的。
    处理数据时,一定要先明确数据源,与数据目的地(数据汇)。
    数据源可以是文件,可以是键盘。
    数据目的地可以是文件、显示器或者其他设备。
    而流只是在帮助数据进行传输,并对传输的数据进行处理,比如过滤处理.转换处理等

    流操作的基本规律:
	a.明确数据源和数据目的:使用输入流还是输出流。
	b.明确要处理的数据是否是纯文本:使用字符流还是字节流。
	当明确体系后,到底该用该体系的哪个对象呢?
	    根据数据存在的设备而定,
	    数据源所在设备可以是,硬盘,键盘,内存。
	    数据目的所在设备可以是,硬盘,控制台,内存。
 
    需求:获取键盘录入,将录入信息存储到本地文件中。
    分析:
	    源:键盘录入,使用输入流。
	    处理的数据:纯文本,使用字符输入流Reader
	    使用对象:键盘录入System.in完成的。那么它是一个标准的字节输入流。InputStream。
	    为了操作文本数据方便,将字节流转换成字符流:使用InputStreamReader。为了提高效率使用BufferedReader.
	    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
	 
	    目的:本地文件(硬盘)输出流。
	    处理的数据:纯文本,字符输出流。Writer。
	    使用对象:可以操作的文件FileWriter对象。为了提高写入流的效率。BufferedWriter.


    需求:获取本地文本数据,将数据息存储到本地另一个文件中,按照UTF-8的编码形式。
    分析:
	    源:硬盘,输入流。
	    处理的数据:纯文本,字符输入流,Read。
	    使用对象:因为是文件FileReader为了提高效率BufferedReader.
	    
	    目的:本地文件(硬盘)输出流。
	    处理的数据:纯文本,字符输出流。Writer。
	    使用对象:可以操作的文件的对象,但是要制定码表再进行存储, 需要使用转换流OutputStreamWriter。
			    将字符转成字节。而转换流要接收的对象都是字节流对象,所以要使用可以操作File的
			    FileOutputStream。为了提高写入流的效率使用BufferedWriter.
		

5、File类
    用来将文件或者文件夹路径封装成对象
    方便对文件与文件夹进行操作。
    File对象可以作为参数传递给流的构造函数。
    
    File类中的常用方法:
        创建:
	    createNewFile(): 创建文件,如果指定目录下已有要创建文件,那么不进行覆盖,通过返回值来确定是否创建成功。
			     输出流也可以创建文件,但是如果文件已存在,会出现覆盖。
	    mkdir():创建单级目录。
	    mkdirs():创建多级目录。
	删除:
	    boolean delete():删除失败返回false。如果文件正在被使用,则删除不了返回falsel。
	    void deleteOnExit();在程序退出时删除指定文件。
	判断:
	    booleanexsits():判断文件或者文件夹是否存在。
	    isFile():在判断一个文件对象封装的是否是文件或者文件夹,必须要先明确该文件是存在的。
	    isDirectory():
	    isHidden():
	    isAbsolute():
	获取信息:
	    getName();
	    getPath();
	    getParent():返回的是绝对路径中的父目录。如果获取的是相对路径,返回null。
	    getAbsolutePath():
	    long length():

	    static File[] listRoots():列出当前机器有效的盘符。
	    String[] list():获取指定目录的当前所有文件或者文件夹的名称。
	    String[] list(FilenameFilter filter):可以通过指定的条件对数据进行过滤。
	    File[] listFiles():返回的是当前目录下所有文件或者文件夹对应的file对象。
	跨平台的目录分隔符:separator File f = new File("c:"+File.separator+"a.txt");


6、递归:函数自己调用自己。
    注意:递归时一定要明确限定条件以及控制调用次数,以免出现内存溢出。
    应用场景:当某一功能要重复使用时,但是操作的未知内容不同
     public static void listAll(File dir) {
        System.out.println(dir.getName());
        File[] files = dir.listFiles();
        for(int x=0;x <files.length; x++) {
            if(files[x].isDirectory())
                listAll(files[x]);
            else
                System.out.println(files[x].getName());
        }
    }


7、IO包中的其它类
	序列流:SequenceInputStream
	    可以将多个字节输入流整合成一个流,操作多文件数据较为方便。在使用这个流读取的时候,读到第一个流
	    的末尾时继续读第二个,第二个读到末尾则继续读第三个,以此类推,直到读到最后一个流的末尾返回-1。
	    它的构造函数有两个:一个可以将两个流合并成一个流。一个可以将枚举Enumeration中的流对象合并一个流。
		通常获取Enumeration是通过Vector的elements方法来完成。但是Vector效率较低,所以该用ArrayList。

	操作对象:ObjectOutputStream与ObjectInputStream:
	    特点:可以用流直接操作Object.将对象冲对内存存储到了硬盘上,称为对象的本地持久化。
	    注意:被操作的Object 必须实现一个标记接口Serializable,该接口中没有方法。该接口用来给类进行UID指定。
            通过ObjectInputStream的readObject方法,获取存储的对象。
	    通过ObjectOutputStream的writeObject方法。来完成对象的持久化。
	    注意:static的成员,还有非静态但被transient关键字所修饰,该属性的对象特有值不会进行持久化存储。
		  这两个对象在构造的时候都需要传入一个字节流进行。
	
	打印流:PrintStream 、PrintWriter
	    字节打印流(PrintStream):System.out对应的类型就是PrintStream。
		该类构造函数可以接收三种类型的参数:File、String name、OutputStream
		前两者在传递参数时,可以指定字符编码。 后者传递参数是,可以指定是否自动刷新。
	    字符打印流:PrintWriter。
		该类构造函数可以接收四种类型的参数:File、String name、OutputStream、Writer
		前两者在传递参数时,可以指定字符编码。后两者传递参数时,可以指定是否自动刷新。
		该自动刷新动作,只有println,printf,format方法来完成。
            该打印流较为常用。在日后学习javaweb中,在进行往客户端应答的时候通过response既可以
	    获取PrintWriter对象,通过将html数据打印到客户端,客户端通过浏览器进行数据解析并展现页面效果。
	    PrintWriter out =
            new PrintWrite(new BufferedWriter(new OutputStreamWriter(new FileOutputStream("a.txt"),"UTF-8")));
	    相比普通的OutputStream和Writer增加了print()和println()方法,这两个方法可以输出实参对象的
	    toString()方法返回值。这两个类还提供自动flush()的功能
	
	操作内存缓冲数组:ByteArrayInputStream与ByteArrayOutputStream
	    这两个流中的子类对象,并没有调用底层资源。所以关闭方法close是无效的。数据源和数据目的都是内存。
	    操作字节数组中的元素只要通过指针的偏移即可,封装成对象其实是通过流的读写思想完成了数组操作

	    ByteArrayInputStream:可以从一个字节数组中读取字节。
	    ByteArrayOutputStream: 写出到字节数组(内存)中,可以获取写出的内容装入一个字节数组。通常
				    我们用这个流来缓冲数据。
	    CharArrayReader:可以从一个字符数组中读取字符。
	    CharArrayWriter:写出字符到字符数组(内存)中,可以获取写出的内容装入一个字符数组。
	    StringReader 与 StringWriter:操作字符串,原理和ByteArrayInputStream ByteArrayOutputStream相同。
        
	管道流:
	    PipedInputStream:管道输入流,可以从管道输出流中读取数据
	    PipedOutputStream:管道输出流,可以向管道输入流中写出数据
	    特点:读取流和写入流可以进行连接。通过这两个流对象构造函数,或者通过两个流对象connect方法。
		  通常都需要结合多线程进行引用。

	操作基本数据类型:DataInputStream与DataOutputStream
	    可以按照基本数据类型占用空间大小读写数据,专门用于操作基本数据类型。如:writeInt(),readInt().
	    writeUTF(),,readUTF();所使用的utf是utf-8修改版。通过writeUTF()写入的数据,必须通过readUTF()获取。

	随机访问文件:RandomAccessFile,封装了字节流。
	    特点:可以对数据进行读和写的操作。通过构造函数的第二个参数模式来区分读写。r rw。
            好处:对于规则的数据可以通过指针的偏移进行随机的数据获取。
            方法 :seek(),skipBytes(),getFilePointer().
            注意:如果在指定位置写入数据,该位置如果已存在数据,那么会发生局部数据覆盖。

	字符编码:
	    ASCII:ISO8859-1、GB2312、GBK、UTF-8
	    在流对文本数据操作,为了方便提供了转换流,转换流中就融入了编码表,默认是GBK.


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值