java学习笔记之IO流

1、IO流分类

1)流向:(以程序为中心)
输入流:数据流进程序
输出流:数据流出程序
2)数据:
字节流:二进制,可以处理一切文件,比如纯文本、音频、视频等
字符流:字符,只能处理纯文本
3)功能:
节点流:包裹源头,读取或写出数据(跟数据源或目的地打交道)
处理流:包裹节电流,增强功能,提供性能(与其它的流打交道)

2、IO四大抽象类

1)抽象类:InputStream、OutputStream、Reader、Writer
2)具体类:
a、以InputStream或Reader结尾的为输入流,以OutputStream或Writer结尾的为输出流。
b、以Stream结尾为字节流,以Reader或Writer结尾为字符流。
c、以InputStream结尾的为字节输入流,以OutputStream结尾的为字节输出流;以Reader结尾的为字符输入流,以Writer结尾的为字符输出流。

3、具体类

java学习笔记之IO流_第1张图片

1)节点流:
文件:FileInputStream、FileOutputStream
FileReader、FileWriter
数组:ByteArrayInputStream、ByteArrayOutputStream
CharArrayReader、CharArrayWriter
键盘:System.in
显示屏:System.out
2)处理流:
缓冲流:增强性能,内部有一个缓冲池(如何提高性能)
BufferedInputStream、BufferedOutputStream
BufferedReader、BufferedWriter
转换流:将字节转换为字符
如果使用非默认编码保存文件或者读取文件时,需要用到转换流,因为转换流的重载构造方法中有指定编码格式的参数,而FielReader 与 FileWriter 是默认编码的文本文件
InputStreamReader、OutputStreamWriter
数据流:基本类型(8大基本类型和字符串)+数据,允许直接写入或读取基本类型数据
对象流:引用类型+数据,允许直接写入或读取对象
必须序列化的对象才能读取和写入(即必须实现java.io.Serializable接口);
序列化的类中,如果某成员变量不允许序列化,可在该成员变量类型前加trasient关键字。
打印流:可以方便的打印,并且可以格式化输出
PrintStream、PrintWriter

代码示例:

1)将基本数据+类型写入到数组中,并从数组中读取

分析:目的地:数组
数据源:数组
要求保留数据+类型,且为基本数据
选择流:节点流:ByteArrayOutputStream、ByteArrayInputStream
处理流:DataOutputStream、DataInputStream(保留数据+类型)
BufferedOutputStream、BufferedInputStream(提高性能,可要可不要)

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;

/**
 * 数据流,保留数据和类型
 * 
 * 1)数据+类型-->数组  
 * 2)数组-->数据+类型
 * 
 * @author ly1
 *
 */
public class TestDataStream {
    public static void main(String[] args) throws IOException {
         read(write());
    }

    //将数据+类型读取到数组中
    public static byte[] write() throws IOException{
        int a = 100;
        long b = 2323L;
        String str = "hello";

        byte[] dest = null;

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        DataOutputStream dis = new DataOutputStream(new BufferedOutputStream(baos));

        dis.writeInt(a);
        dis.writeLong(b);
        dis.writeUTF(str);

        dis.flush();  //记得输出数据的时候,手动flush,这里不flush会出错([详情](http://bbs.csdn.net/topics/391834931))
        dest = baos.toByteArray();
        dis.close();
        baos.close();

        return dest;
    }

    //从数组中读取数据+类型
    public static void read(byte[] src) throws IOException{
        DataInputStream dis = new DataInputStream(new BufferedInputStream(new ByteArrayInputStream(src)));  

        int readInt = dis.readInt();
        long readLong = dis.readLong();
        String readUTF = dis.readUTF();

        System.out.println(readInt);
        System.out.println(readLong);
        System.out.println(readUTF);

        dis.close();


    }
}

结果:100
     2323
     hello

2)将Student对象数据+类型写入到文件中,并从文件中读取

分析:数据源:文件
目的地:文件
要求保留引用数据+类型
选择流:节点流:FileOutputStream、FileInputStream
处理流:ObjectOutputStream、ObjectInputStream(保留引用数据+类型)
BufferedOutputStream、BufferedInputStream(提高性能,可要可不要)

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;

/**
 * 对象流  
 * 1) 属于处理流
 * 2)输入流   ObjectInputStream    反序列化 
 *    输出流  ObjectOutputStream   序列化
 * 3)先序列化,再反序列化   
 * 4) 只有实现了java.io.Serializable接口的类才能序列化;  
 *      类中不想序列化的属性加 transient 关键字 
 * 
 * @author ly1
 *
 */
public class TestObjectStream {
    public static void main(String[] args) throws ClassNotFoundException, IOException {
        ser();
        read();
    }

    //序列化
    public static void ser() throws IOException{
        Student stu = new Student("张三", 12);

        ObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream("src/text.txt")));
        oos.writeObject(stu);
        oos.flush();    
        oos.close();
    }

    //反序列化
    public static void read () throws IOException, ClassNotFoundException{
        ObjectInputStream ois = new ObjectInputStream(new BufferedInputStream(new FileInputStream("src/text.txt")));

        Object readObject = ois.readObject();
        if(readObject instanceof Student){
            System.out.println(((Student) readObject).name);  //读到的是null,因为该成员变量前有transient关键字
            System.out.println(((Student) readObject).age);

        }

        ois.close();
    }
}

class Student implements Serializable{
    public transient String name;
    public int age;

    public Student(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
}
结果:null
     12

4、注意事项

1)步骤
a、选择流
b、建立连接
c、读取或写入
d、关闭流
2)输出数据后,手动flush
3)如果数据源或目的地为文件的话,关于路径的问题:
两种路径方式:
–绝对路径 带盘符:
–相对路径 相对项目目录下的路径
4)编码与解码
a、编码:将字符转换为字节(二进制)
解码:将字节(二进制)转换为字符
b、以不同的方式编码、解码,就会出现乱码。
c、byte数组、文件都是二进制形式,char数组是字符形式

import java.io.UnsupportedEncodingException;

public class Test {
    public static void main(String[] args) throws UnsupportedEncodingException {
        //将字符串用 GBK 方式编码
        byte[] b = "我是java程序猿".getBytes("GBK");
        //将字符串用 UTF-8  方式解码
        String str = new String(b,"UTF-8");
        //由于编码方式与解码方式不同,出现乱码
        System.out.println(str);
    }
}

结果:????java????

d、每个文件都有自己默认的编码方式,如果用字符流读取,并且默认解码与编码方式不同,就会出现乱码。
两种解决方式:
1、利用转换流,在构造函数中指明解码方式
2、先用字节流,在用new String(byte[] b, String charset)解码
貌似第一种使用转换流更方便。
代码示例:(关于如何更改文件的编码方式)

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;

public class Test01 {
    public static void main(String[] args) throws IOException {
        //文件路径,该文件编码方式为"UTF-8",而eclipse默认解码方式为"GBK"
        String path="C:/Users/ly1/Desktop/test.txt";

        //第一种解码方式:转换流
        //建立连接,使用"UTF-8"构建转换流
        Reader reader = new InputStreamReader(new FileInputStream(path),"UTF-8");
        //读取
        char[] chr= new char[1024];
        reader.read(chr);
        //关闭流
        reader.close();
        //打印结果
        System.out.println(new String(chr));

        //第二种解码方式:字节流  +  new String(byte[] b, String charset)
        //建立连接
        InputStream is = new FileInputStream(path);
        //读取
        byte[] b = new byte[1024];
        is.read(b);
        //关闭流
        is.close();
        //打印结果,使用"UTF-8"将字节数组转换为字符串
        System.out.println(new String(b,"UTF-8"));
    }
}

你可能感兴趣的:(java学习笔记,java,java学习,io流,字符流,编码-解码)