IO

IO结构

IO流:用于处理设备上的数据,即:InputStream,OutputStream

IO流的具体分类:
1,根据处理的数据类型不同分为:字节流与字符流
2,根据流的方向不同分为:输出流与输入流

字符流的由来:
因为文件的编码不同,而有了对字符进行高效操作的字符流对象
原理:其实就是基于字节流读取数据时,去查了 指定编码表

字节流与字符流的区别
1,字节流读取的 时候,读取一个字节就返回一个字节,
字符流使用了字节流读取到一个或多个字节流时,先去查指定的编码 表,将查到的字符返回
2,字节流能够读取所有的类型数据,而字符流只能处理字符类型

一.File

  • 目录列表
    假设我们想查看目录列表,可使用list()方法查看File对象下所有的目录,但是如果想查看类型为.java类的文件,那么我们就使用“目录过滤器”
package File;
import java.io.File;
import java.io.FilenameFilter;
import java.util.Arrays;
import java.util.regex.Pattern;
public class DirList {
    public static void main(String[] args) {
        File file = new File(".");
        String[] list;
        list = file.list(new DirFilter(".*"));
        Arrays.sort(list,String.CASE_INSENSITIVE_ORDER);
        for(String str : list){
            System.out.println(str);
        }
    }
}
package File;
import java.io.File;
import java.io.FilenameFilter;
import java.util.regex.Pattern;
public class DirFilter implements FilenameFilter{
    private Pattern pattern;
    public DirFilter(String filenName){
        pattern = Pattern.compile(filenName);
    }
    @Override
    public boolean accept(File dir, String name) {
        return pattern.matcher(name).matches();
    }
}

DirFilter 这个类存在的原因就是把accept() 方法提供给 list() 使用,使list()可以回调accept() 进而决定哪些文件包含在列表里 这就是策略模式的体现
list()方法会为此目录下的所有的方法都调用accept()方法,来判断此文件是否在内

  • 目录的检查及创建
    File 类不仅仅只代表存在的目录,也可以用File对象来创建不存在的目录,也可以用File查看文件的各种特性

输入流 InputStream

InputStream

每一种数据源都有相应的InputStream子类,因为InputStream是个处于顶层的类,用来处理各种数据源的类都继承了InputStream类,我们来看看这些类:
ByteArrayInputStream:处理字节数组的类,允许将内存的缓冲区当做InputStream使用。
StringBufferInputStream:将String转换成InputStream,内部实现用的是StringBuffer。
FileInputStream:从文件中读取数据。
PipedInputStream:用于从管道中读取数据。
SequenceInputStream:将多个流对象转化成一个InputStream。
FilterInputStream:装饰器类,为其它InputStream类提供功能。

  • 读取文件内容
 package InputStream;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class BufferedInputFile2 {
    public static String read(String fileName) throws IOException{
        BufferedReader br = new BufferedReader(new FileReader(fileName));
        StringBuilder sb =  new StringBuilder();
        String s = "";
        while((s = br.readLine())!=null){
            sb.append(s+"\n");
        }
        if(br!=null){
            br.close();
        }
        return sb.toString();
    }
    public static void main(String[] args) {
        try {
    System.out.println(read("E:\\WorkSpaceSSH\\Demo_18\\src\\InputStream\\BufferedInputFile.java"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
* DataInputStream类
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class DataOutputStreamDemo{
   public static void main(String[] args) throws IOException{
       File file = new File("d:" + File.separator +"hello.txt");
       DataInputStream input = new DataInputStream(new FileInputStream(file));
       char[] ch = new char[10];
       int count = 0;
       char temp;
       while((temp = input.readChar()) != 'C'){
           ch[count++] = temp;
       }
       System.out.println(ch);
    }
}

输出流 OutputStream

outputstream

OutputStream 是所有的输出字节流的父类,它是一个抽象类。
ByteArrayOutputStream、FileOutputStream是两种基本的介质流,它们分别向Byte 数组、和本地文件中写入数据。PipedOutputStream 是向与其它线程共用的管道中写入数据,
ObjectOutputStream 和所有FilterOutputStream的子类都是装饰流。具体例子跟InputStream是对应的。

  • 文件复制
import java.io.*;
class hello{
   public static void main(String[] args) throws IOException {
       if(args.length!=2){
           System.out.println("命令行参数输入有误,请检查");
           System.exit(1);
       }
       File file1=new File(args[0]);
       File file2=new File(args[1]);
       if(!file1.exists()){
           System.out.println("被复制的文件不存在");
           System.exit(1);
       }
       InputStream input=new FileInputStream(file1);
       OutputStream output=new FileOutputStream(file2);
       if((input!=null)&&(output!=null)){
           int temp=0;
           while((temp=input.read())!=(-1)){
                output.write(temp);
           }
       }
       input.close();
       output.close();
    }
}
* DataOutputStream
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
public class DataOutputStreamDemo{
   public static void main(String[] args) throws IOException{
       File file = new File("d:" + File.separator +"hello.txt");
       char[] ch = { 'A', 'B', 'C' };
       DataOutputStream out = null;
       out = new DataOutputStream(new FileOutputStream(file));
       for(char temp : ch){
           out.writeChar(temp);
       }
       out.close();
    }
}

添加属性和有用的接口

java IO 类库需要多种不同功能的组合,这正是使用装饰器模式的理由所在
这也是java IO类库里存在filter(过滤器)的原因所在,抽象类filter是所有装饰器的基类。装饰器类必须和它所装饰的类具有相同的接口,但它也可以扩展
装饰器在给我们提供许多灵活性的时候也给我们带来了复杂性,我们必须创建许多类 才能得到我们需要的单个的IO对象

Reader 和 Writer

Reader 是所有的输入字符流的父类,它是一个抽象类。
Writer 是所有的输出字符流的父类,它是一个抽象类
设计Reader和Writer主要是为了国际化,老的IO流仅支持8位的字节流,不能很好的支持16位的,所以添加Reader和Writer就是为了所有的IO操作中能很好地 支持Unicode
InputStreamReader 可以把 InputStream 转化为 Reader
OutoutStreamWrite 可以把OutputStream转化为Write

  • 从文件中读取数据
import java.io.*;
class hello{
   public static void main(String[] args) throws IOException {
       String fileName="D:"+File.separator+"hello.txt";
       File f=new File(fileName);
       char[] ch=new char[100];
       Reader read=new FileReader(f);
       int temp=0;
       int count=0;
       while((temp=read.read())!=(-1)){
           ch[count++]=(char)temp;
       }
       read.close();
       System.out.println("内容为"+new String(ch,0,count));
    }
}
  • BufferedReader
    注意:BufferedReader只能接受字符流的缓冲区,因为每一个中文需要占据两个字节,所以需要将System.in这个字节输入流变为字符输入流
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class BufferedReaderDemo{
   public static void main(String[] args){
       BufferedReader buf = new BufferedReader(
                newInputStreamReader(System.in));
       String str = null;
       System.out.println("请输入内容");
       try{
           str = buf.readLine();
       }catch(IOException e){
           e.printStackTrace();
       }
       System.out.println("你输入的内容是:" + str);
    }
}

字节流与字符流的转换

InputStreamReader:字节到字符的桥梁
OutputStreamWriter:字符到字节的桥梁
这两个流对象是字符体系中的成员,它们有转换作用,本身又是字符流,所以在构造的时候需要传入字节流对象进来。

//将字节输出流转化为字符输出流
import java.io.*;
class hello{
   public static void main(String[] args) throws IOException {
       String fileName= "d:"+File.separator+"hello.txt";
       File file=new File(fileName);
       Writer out=new OutputStreamWriter(new FileOutputStream(file));
       out.write("hello");
       out.close();
    }
//将字节输入流变为字符输入流
import java.io.*;
class hello{
   public static void main(String[] args) throws IOException {
       String fileName= "d:"+File.separator+"hello.txt";
       File file=new File(fileName);
       Reader read=new InputStreamReader(new FileInputStream(file));
       char[] b=new char[100];
       int len=read.read(b);
       System.out.println(new String(b,0,len));
       read.close();
    }
}

标准IO流

标准IO模型,java提供了System.in,System.out,System.err
其中System.err和System.out都已报装成了PrintStream 但是System.in
却是一个未被报装过的InputStream,所以在System.in之前要对其进行包装

package OutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Echo {
    public static void main(String[] args) {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        String c = "";
        try {
            while((c=reader.readLine())!=null&&c.length()!=0){
                System.out.println(c);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
  • 将System.out 转换为PrintWrite
    System.out 是一个PrintStream 而PrintStream 是一个OutputStream 而PrintWrite有一个可以接受OutputStream 参数的构造器
PrintWriter out = new PrintWriter(System.out,true);
        out.println("hello ");

压缩

  • 利用GZIP进行简单的压缩
    GZIP接口非常的简单,如果要对单个的数据流进行压缩,GZIP就很合适
package zip;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
public class GIZPcomress {
    public static void main(String[] args) {
        try {
            BufferedReader br = new BufferedReader(
                    new FileReader(
                            "E:\\WorkSpaceSSH\\Demo_18\\src\\InputStream\\BufferedInputFile.java"));
            BufferedOutputStream os = new BufferedOutputStream(
                    new GZIPOutputStream(
                            new FileOutputStream(
                                    "E:\\WorkSpaceSSH\\Demo_18\\src\\InputStream\\BufferedInputFile4.java")));
            System.out.println("write file");
            int c;
            while ((c = br.read()) != -1) {
                os.write(c);
            }
            br.close();
            os.close();
            System.out.println("read file");
            BufferedReader br2 = new BufferedReader(
                    new InputStreamReader(
                            new GZIPInputStream(
                                    new FileInputStream(
                                            "E:\\WorkSpaceSSH\\Demo_18\\src\\InputStream\\BufferedInputFile4.java"))));
            String s = "";
            while ((s = br2.readLine()) != null) {
                System.out.println(s);
            }
        } catch (Exception e) { 
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
  • 用zip 进行压缩 解压
package zip;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.util.zip.Adler32;
import java.util.zip.CheckedInputStream;
import java.util.zip.CheckedOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
//压缩
public class ZipCompress {
    public static void main(String[] args) {
        try {
            FileOutputStream fos = new FileOutputStream("E:\\WorkSpaceSSH\\Demo_18\\src\\InputStream\\BufferedInputFile5.zip");
            CheckedOutputStream cs = new CheckedOutputStream(fos, new Adler32());
            ZipOutputStream zs = new ZipOutputStream(fos);
            BufferedOutputStream bos = new BufferedOutputStream(zs);
            zs.setComment("this is zip file");
            System.out.println("开始压缩");
            BufferedReader reader = new BufferedReader(new FileReader("E:\\WorkSpaceSSH\\Demo_18\\src\\InputStream\\BufferedInputFile.java"));
            zs.putNextEntry(new ZipEntry("E:\\WorkSpaceSSH\\Demo_18\\src\\InputStream\\BufferedInputFile.java"));
            int s = 0;
            while((s=reader.read())!=-1){
                bos.write(s);
            }
            bos.close();
            System.out.println("checkNum:"+cs.getChecksum().getValue());
            System.out.println("开始读文件");
            FileInputStream fis = new FileInputStream("E:\\WorkSpaceSSH\\Demo_18\\src\\InputStream\\BufferedInputFile5.zip");
            CheckedInputStream cis = new CheckedInputStream(fis, new Adler32());
            ZipInputStream zi = new ZipInputStream(fis);
            BufferedInputStream bis = new BufferedInputStream(zi);
            ZipEntry zn = null;
            while((zn = zi.getNextEntry())!=null){
                System.out.println("this file:"+zn);
                int n = 0;
                while((n = bis.read())!=-1){
                    System.out.write(n);
                }
            }
            System.out.println("checkNum:"+cs.getChecksum().getValue());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

序列化

Java平台允许我们在内存中创建可复用的Java对象,但一般情况下,只有当JVM处于运行时,这些对象才可能存在,即,这些对象的生命周期不会比JVM的生命周期更长。但在现实应用中,就可能要求在JVM停止运行之后能够保存(持久化)指定的对象,并在将来重新读取被保存的对象。Java对象序列化就能够帮助我们实现该功能。java 的对象的序列化将那些实现了Serializable接口的对象转换成字节序列,并且能够在以后将字节序列恢复为原来的对象
什么时候用序列化:
a)当你想把的内存中的对象保存到一个文件中或者数据库中时候;
b)当你想用套接字在网络上传送对象的时候;
c)当你想通过RMI传输对象的时候;

package Serializable;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class A {
    private static int i = 10;
    private transient static String s = "java";
    public static void main(String[] args) {
        try {
            User user = new User();
            user.setSex('男');
            user.setUsername("小李");
            user.setUserpass("123");
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("user.out"));
            oos.writeObject(user);
            oos.close();
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream("user.out"));
            User user2 = (User)ois.readObject();
            //String ss = ois.readUTF();
            //System.out.println(ss);
            System.out.println(user2.getUsername());
            System.out.println(user2.getSex());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}
  • 序列化的控制
    有时候我们不想整个对象都序列化,只需要对象的一部分序列化,此时就应该用到:Externalizable
    Externalizable 是一个接口 需要实现两个方法writeExternal(),readExternal()
package Serializable;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
public class Bilp1 implements Externalizable{
    private User user;
    public Bilp1(){
        System.out.println("Bilp1()");
    }
    public Bilp1(User user){
        this.user = user;
    }
    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        // TODO Auto-generated method stub
        //out.writeObject(user);
        System.out.println("writeExternal()");
    }
    @Override
    public void readExternal(ObjectInput in) throws IOException,
            ClassNotFoundException {
        // TODO Auto-generated method stub
        System.out.println("readExternal()");
    }
}
  • transient关键字
    当某个字段被声明为transient后,默认序列化机制就会忽略该字段。此处将User类中的username字段声明为transient
private transient String username;
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容