黑马程序员——IO流

(一)IO流的概述

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

1、IO流用来处理设备之间的数据传输       Java对数据的操作是通过流的方式       Java用于操作流的对象都在IO包中​

2、流按操作数据分为两种:字节流与字符流。

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

4、按功能的不同可分为节点流和处理流。

      节点流:直接操作目标设备,例如:磁盘或一块内存区域。

      处理流:通过操作节点流,从而间接完成输入或输出功能的流。处理流的存在是建立在       一个已经存在的输入流或输出流的基础之上的。

5、IO流的基本类:

字节流的抽象基类:

InputStream      OutputStream

字符流的抽象基类:

Reader      Writer

这四个类派生出来的子类名称都是以其父类名作为子类的后缀。

(二)字符流

​操作数据最常见的基本体现形式是文件,用Writer和Reader的子类FileWriter    和    FileReader

字符流的缓冲区

缓冲区的出现提高了对数据的读写效率,缓冲区要结合流才可以使用在流的基础上对流的功能增强  ,BufferedWriter    BufferedReader

​ReadLine原理:

无论是读一行还是读取多个字符,其实最终都是在硬盘上一个个读取,用的还是read方法一次读一个,把数据临时存起来遇到回车符时一次性全部读出来。​

​实例1

package IO;

import java.io.BufferedReader;

import java.io.BufferedWriter;

import java.io.FileReader;

import java.io.FileWriter;

import java.io.IOException;

public class BufferefDemo {

public static void main(String[] args) {

BufferedWriter   bfw = null;

BufferedReader   bfd = null;

try {

bfw = new BufferedWriter(new FileWriter("E:\\javalianxi\\新建文件夹\\lang\\text1.txt"));

bfd = new BufferedReader(new FileReader("E:\\javalianxi\\新建文件夹\\lang\\Demo.txt"));

String len = null;

while((len = bfd.readLine())!=null){

bfw.write(len);

bfw.newLine();//换行

bfw.flush();//刷新

}

} catch (IOException e) {

throw new RuntimeException("读写异常");

}

finally{

try {

if(bfd!=null)

bfd.close();

} catch (IOException e2) {

throw new RuntimeException("读关闭异常");

}

try {

if(bfw!=null)

bfw.close();

} catch (IOException e2) {

throw new RuntimeException("写关闭异常");

}

}

}

}

装饰设计模式:

当想要对已有的对象进行功能的增强时,可以定义一个类将已有的对象传入,基于已有的功能提供加强功能,然后定义的类也称为装饰类。

装饰通常通过构造方法接收被装饰的对象,装饰模式比继承更灵活避免了继承的臃肿,而且降低了类与类之间的关系​

​(三)字节流

字节流主要是操作byte(字节)的类型数据:​

字节输出流:OutputStream

字节输入流:InputStream

字节流和字符流在使用上的代码结构都是非常类似的,但是其内部本身也是有区别的,因为在进行字符流操作的时候会使用到缓冲区(内存中),而字节流操作的时候是不会使用到缓冲区的

在输出的时候,OutputStream类即使最后没有关闭内容也可以输出。但是如果是Writer的话,则如果不关闭,最后一条内容是无法输出的,因为所有的内容都是保存在了缓冲区之中,每当调用了close()方法就意味着清空缓冲区了。那么可以证明字符流确实使用了缓冲区:

字节流:程序 → 文件

字符流:程序 → 缓冲区(内存中) → 文件

​两者相比,肯定使用字节流更加的方便,而且在程序中像图片、MP3等都是采用字节的方式的保存,那么肯定字节流会比字符流使用的更广泛。如果要是想操作文本的话,字符流肯定是最好使的。

实例2

拷贝图片​

思路

1、用字节流读取流对象和图片关联

2、用字节写入流创建一个图片文件,用于存储获取到的图片数据

3、通过循环读写,写完数据的存储

4关闭资源​

package com.io;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

public class CopyPicDemo {

public static void main(String args[]){

long start = System.currentTimeMillis();

show();

long end = System.currentTimeMillis();

System.out.println((end-start)+"毫秒");

}

public static void show(){

FileOutputStream  fop = null;

FileInputStream   fip = null;

try {

fop = new FileOutputStream("Tulipsuu.jpg");

fip = new FileInputStream("Tulips.jpg");

byte[] by = new byte[1024];

int len = 0;

while((len = fip.read(by))!= -1){

fop.write(by , 0 , len);

}

catch (IOException e) {

throw new RuntimeException("读写异常");

}

finally{

try {

if(fip!=null)

fip.close();

} catch (IOException e2) {

// TODO: handle exception

}

try {

if(fop!=null)

fop.close();

} catch (IOException e) {

// TODO: handle exception

}

}

}

}

 

 

​实例3

演示mp3通过缓冲区复制

​package IO;

import java.io.BufferedInputStream;

import java.io.BufferedOutputStream;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

public class Map3Copy {

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

BufferedInputStream   bfs  = 

new BufferedInputStream(new FileInputStream("c:\\bb.mp3"));

BufferedOutputStream  bos  = 

new BufferedOutputStream(new FileOutputStream("c:\\nn.mp3"));

int lin =0;

while((lin = bfs.read())!=-1){

bos.write(lin);

}

bfs.close();

bos.close();

}

}

​(四)转换流

OutputStreamWriter:把字节输出流对象转成字符输出流对象

InputStreamReader:把字节输入流对象转成字符输入流对象

构建一个字节输出流对象

OutputStream out = newFileOutputStream("");

把字节输出流转成字符输出流

Writer w = new OutputStreamWriter(out);

然后的操作和使用字符输出流的操作一样

---------------------------------------------

构建一个字节输入流对象

InputStream is = newFileInputStream("");

把字节输入流转成字符输入流

Reader r = new InputStreamReader(is);

然后的操作和使用字符输入流的操作一样

 

(五)File类 

流在操作的只有数据,而数据最明显的体现形式就是文件,文件又包含了很多的属性和行为信息, 比如说前缀名、扩展名、文件自己的大小时间等,所以文件是一个复杂的事物而这个事物有很多, 所以java就对文件这类的事物进行了描述,也把它封装成了对象,方面了我们对文件或文件夹的 属性进行操作。而File类的对象也主要用来获取文件本身的一些信息,如文件大小权限等,不涉 及对文件的读写操作。

java提供了三种创建方法来生成一个文件对象。 (1)根据参数指定的文件路径创建一个File文件对象,就是把某个文件封装成对象  File file1  = new File("D:\\abc\\123.txt"); (2)根据给定的目录创建一个File实体对象,其中"d:\\abc"为目录,"123.txt"为文件的名称  File file2  = new File("D:\\abc","123.txt"); (3)可以根据已知的目录文件对象File创建一个新的File实体对象  File d = new File("D:\\abc");  File file3 = new File(d,"123.txt");

 File类所提供的方法中,有的是针对文件的处理,有的是针对目录的处理,可以通过一些方法来 判断文件是否存在以及文件的相对路径和绝对路径等,File类的常见方法有:

 1,创建。  boolean createNewFile():在指定位置创建文件,如果该文件已经存在,则不创建,返回false。和输出流不一样,输出流对象一建立创建文件。而且文件已经存在,会覆盖。  

boolean mkdir():创建目录文件夹。

boolean mkdirs():创建多级文件夹。

 2,删除。  boolean delete():删除失败返回false。如果文件正在被使用,则删除不了返回falsel。 

 void deleteOnExit();在程序退出时删除指定文件。

 3,判断。  boolean exists() :文件是否存在. 

 isFile(): 是否为文件  

isDirectory();是否为目录 

 isHidden(); 是否是隐藏文件

 isAbsolute();是否是绝对路径

 4,获取信息。 

 getName()://获取文件名  

getPath()://获取相对路径  

getParent()://返回的绝对路径的文件父目录

 getAbsolutePath() //获取绝对路径 

 long lastModified()  

long length() 

文件列表: listRoots()    列出可用的文件系统根

List() 列出制定文件夹下的文件名称

ListFiles()返回当前文件夹下的文件及文件夹的对象​


递归:函数自身调用自身的方法

实例

package IO;

import java.io.File;

public class FileDemo {

public static void main(String[] args) {

File dir =new File("D:\\com");

dirShow(dir);

}

private static void dirShow(File dir) {

System.out.println(dir);

      File[]  ff =dir.listFiles();

      for (int x = 0; x < ff.length; x++) {

if(ff[x].isDirectory()){

dirShow(ff[x]);\\调用自己的方法

}

else {

System.out.println(ff[x]);

}

}

}

}

​(六)IO包中的其他类类

Properties类

 Properties是hashtable的子类。一个可以将键值进行持久化存储的对象。 也就是说它具备map集合的特点。而且它里面存储的键值对都是字符串。

 是集合中和IO技术相结合的集合容器。  该对象的特点:可以用于键值对形式的配置文件。

 那么在加载数据时,需要数据有固定格式:键=值。

 特点: 1:可以持久化存储数据。 2:键值都是字符串。 3:一般用于配置文件。   |-- load():将流中的数据加载进集合。    原理:其实就是将读取流和指定文件相关联,并读取一行数据,因为数据是规则的key=value,所以获取一行后,通过 = 对该行数据进行切割,左边就是键,右边就是值,将键、值存储到properties集合中。  |-- store():写入各个项后,刷新输出流。  |-- list():将集合的键值数据列出到指定的目的地。

 打印流 

 PrintWriter与PrintStream 可以直接操作输入流和文件。该流提供了打印方法,可以将各种数据类  型的数据都原样打印。

 字节打印流:PrintStream    

构造函数可以接收的参数类型:   1,file对象。File   2,字符串路径。String   3,字节输出流。OutputStream

 字符打印流:PrintWriter  

 构造函数可以接收的参数类型:   1,file对象。File   2,字符串路径。String   3,字节输出流。OutputStream   4,字符输出流,Writer。   

序列流   SequenceInputStream 

对多个流进行合并,它的构造函数接收的是两个输入流,或者是接收一个输入流的枚举。

实例1

对图片的分段切割和合并

package com.io;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.SequenceInputStream;

import java.util.ArrayList;

import java.util.Enumeration;

import java.util.Iterator;

public class SequenceSplitDemo {

//切割后再合并

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

show();

show2();

}

public static void show()throws IOException{

FileInputStream fis = new FileInputStream("E:\\javalianxi\\新建文件夹\\lang\\DSC00129.JPG");

FileOutputStream fos = null;

byte[] buf = new byte[1024*1024];

int len = 0;

int count=1;

while((len = fis.read(buf))!=-1){

fos = new FileOutputStream("E:\\javalianxi\\lianxi\\"+(count++)+".part");

fos.write(buf,0,len);

fos.close();

}

fis.close();

}

public static void show2() throws IOException{

ArrayListal = new ArrayList();

for (int x = 1; x <=5; x++) {

al.add(new FileInputStream("E:\\javalianxi\\lianxi\\"+x+".part"));

}

final Iteratorit = al.iterator();

Enumerationen = new Enumeration() {

public boolean hasMoreElements(){

return it.hasNext();

}

public FileInputStream nextElement(){

return it.next();

}

};

SequenceInputStream ss = new SequenceInputStream(en);

FileOutputStream fos = new FileOutputStream("E:\\javalianxi\\lianxi\\pic\\0.JPG");

byte[] buf = new byte[1024*1024];

int len= 0;

while((len = ss.read(buf))!=-1){

fos.write(buf,0,len);

}

ss.close();

fos.close();

}

}

 

​直接操作对象的流bjectInputStream与ObjectOutputStream 


 管道流  PipedInputStream和PipedOutputStream输入输出可以直接进行连接,通过结合线程使用。

 管道输入流应该连接到管道输出流;管道输入流提供要写入管道输出流的所有数据字节。通常,数据  由某个线程从 PipedInputStream 对象读取,并由其他线程将其写入到相应的 PipedOutputStream。  不建议对这两个对象尝试使用单个线程,因为这样可能死锁线程。管道输入流包含一个缓冲区,可在  缓冲区限定的范围内将读操作和写操作分离开。如果向连接管道输出流提供数据字节的线程不再存在,  则认为该管道已损坏。 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值