什么是流?
在Java中,所有数据都是使用流写的.流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象. 数据在两设备之间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作.


输入输出流

输入就是将数据从各种设备中读取到内存
输出则是相反,是将数据写入到各种输出设备


字节流:数据流中最小的数据单元是字节 。InputStream、OutputStream
字符流:数据流中最小的数据单元是字符, Java中的字符是Unicode编码,一个字符占用两个字节
Reader、Writer


从字节流中读取字符

public class InputDemo {
    public static void main(String[] args) throws IOException {
        InputStream is = 获取一个输入字节流();
        String message = 从一个输入字节流中得到最终的字符(is);
        System.out.println(message);
    }

    private static String 从一个输入字节流中得到最终的字符(InputStream is) 
    throws IOException {
        //手动从字节流中读,假设流的长度小于8192
        byte[] buffer = new byte[8192];
        int len = 8192;
        for (int i = 0; i < buffer.length; i++) {
            int b = is.read();
            if (b == -1){
            	//b = -1 说明读完了
                len = i;
                break;
            }
            buffer[i] = (byte) b;
        }
        String s = new String(buffer,0,len,"UTF-8");
        return s;
    }

    private static InputStream 获取一个输入字节流() throws IOException {
        InputStream is;
        is = new FileInputStream("本地文件.txt");
        return is;
    }
}

我是一个本地文件内容
我是UTF-8编码


用一个reader 读一个字符流/reader读到缓冲区返回长度!

		//用一个字节流得到字符流(字节流是该字符流的源码)
		private static String 从一个输入字节流中得到最终的字符(InputStream is) 
		throws IOException{
        Reader reader = new InputStreamReader(is,"UTF-8");
        char[] buffer = new char[1024];
        int len = reader.read(buffer);//读到缓冲区!!!!!!!
        return new String(buffer,0,len);
    }

我是一个本地文件内容
我是UTF-8编码


带缓冲区的BufferedReader可以有效提升效率

		private static String 从一个输入字节流中得到最终的字符(InputStream is) throws IOException{
        Reader reader = new InputStreamReader(is,"UTF-8");
        BufferedReader bufferedReader = new BufferedReader(reader);
        return bufferedReader.readLine();//读一行数据
    }

从字符流读,和从字符流读

private static String 从一个输入字节流中得到最终的字符(InputStream is) throws IOException{
        Reader reader = new InputStreamReader(is,"UTF-8");
        StringBuilder sb1 = new StringBuilder();
        char[] buffer = new char[1024];
        int len;
        while ((len = reader.read(buffer))!= -1){
            //调试后发现,只进入了一次循环,reader.read(buffer)直接返回了21,然后sb1就append了
            //然后发现到结尾了(即流结尾返回-1)不进入循环;
            sb1.append(buffer,0,len);
        }
        System.out.println(sb1.toString());

        StringBuilder sb2 = new StringBuilder();
        int c;
        while ((c = reader.read())!= -1){
            char cb = (char) c;
            sb2.append(cb);
        }
        System.out.println(sb2.toString());

        return "";
    }

这里需要注意,new一个String里面的buffer可用是char[]也可以是byte[],但是StringBuilder append只能append char[] 类型的数组


通过Scanner去读

		private static String 从一个输入字节流中得到最终的字符(InputStream is) throws IOException{
        Scanner scanner = new Scanner(is,"UTF-8");
        return scanner.nextLine();
    }

InputStream(abs class) 一次一个字节/一次一组字节
Reader(abs class) 一次一个字符/一次一组字符
BufferReader(继承自Reader) 一次一个字符/一次一组字符/一次一行

Reader和Writer是字符流
InputString和OutputString是字节流


内存中的源ByteArrayInputStream:这也是个字符流

class 内存中的源{
    public static void main(String[] args) throws IOException{
        byte[] source = "中国 人民 站起来 了".getBytes("UTF-8");//转成了字节
        InputStream is = new ByteArrayInputStream(source);
        Scanner s = new Scanner(is,"UTF-8");
        while (s.hasNext()){
            System.out.println(s.next());
        }
        s.close();
    }
}

中国
人民
站起来


输出

输出表现在字节流上:OutputStream
表现在字符流上:Writer

public class OutPut {
    public static void main(String[] args) throws IOException {
        OutputStream os = new FileOutputStream("本地输出文件.txt");
        os.write(0x41);// A
        os.write(0x0d);// \r
        os.write(0x0a);// \n
        os.flush();
        os.close();
    }
}

这个文件夹里就有一个A了


转成字符流去写

public class OutPut {
    public static void main(String[] args) throws IOException {
        OutputStream os = new FileOutputStream("本地输出文件.txt");
        Writer writer = new OutputStreamWriter(os,"UTF-8");
        //转成字符流
        writer.write('c');
        writer.write("你好");
        char[] buffer = {'我' ,'在','这'};
        writer.write(buffer,0,buffer.length);
        writer.flush();
        writer.close();
    }
}

public class OutPut {
    public static void main(String[] args) throws IOException {
        OutputStream os = new FileOutputStream("本地输出文件.txt");
        Writer writer = new OutputStreamWriter(os,"UTF-8");
        writer.write('c');
        writer.write("你好");
        char[] buffer = {'我' ,'在','这'};
        writer.write(buffer,0,buffer.length);
        writer.append("\r\n我爱 sing dance rap basketball");
        writer.flush();
        writer.close();
    }
}

在这个文件中
c你好我在这
我爱 sing dance rap basketball


PrintWriter(只能处理字符) vs PrintStream(可以处理字节和字符)

PrintStream

class PrintStream1{
    public static void main(String[] args) throws IOException {
   		//OutputStream os = new FileOutputStream("本地文件.txt");
        //PrintStream out = new PrintStream(os,false,"UTF-8"); 不同的构建方式
        
        PrintStream out = new PrintStream("本地输出文件.txt","UTF-8");
        out.println("我是中国人");
        out.println("我是第二行");
        out.println("我爱 sing dance rap basketball");
        out.flush();
        out.close();
    }
}

PrintWriter

class PrintWriter2{
    public static void main(String[] args) throws IOException {
        PrintWriter out = new PrintWriter("本地输出文件.txt","UTF-8");
        out.printf("你好%n");
        out.println("我是谁");
        out.flush();
        out.close();
    }
}

关于Buffer和Flush

缓冲区(buffer):解决输入输出速度不匹配问题(为什么需要缓冲区):

用read()读取文件时,每读一个字节,访问一次硬盘,效率很低.文件过大时候,操作起来也不是很方便.因此需要用到buffer缓存流,当创建buffer对象,会先创建一个缓冲区数组.先从评判者读到缓冲区,然后直接从缓冲区输出即可.

刷新(flush):全部泄出来


字节流对比字符流

  1. 字节流操作的基本单元是字节;字符流操作的基本单元为Unicode码元
  2. 字节流在操作的时候本身不会用到缓冲区,是与文件本身直接操作的;而字符流在操作的时候使用到缓冲区
  3. 所有文件的存储都是字节(byte)的存储,在磁盘上保留的是字节.
  4. 在使用字节流操作符时候,即使没有关闭资源(close方法)也能输出,但是字符流不使用close方法的话,不会输出任何内容.
  5. 有时候我们需要进行字节流与字符流二者之间的转换,因为这是两种不同的流,所以,在进行转换的时候我们需要用到 OutputStreamWriter 和 InputStreamReader.
  6. InputStreamReader 是从字节流到字符流的桥:它读取字节,并使用指定的 charset 将其解码为字符 。
  7. OutputStreamWriter 是字符的桥梁流以字节流:向其写入的字符编码成使用指定的字节
    charset 。

小结

I/O流的操作

  1. 按照流向分:输入流;输出流
  2. 按照处理数据的单位分:字节流(8位的字节)字符流(16位的字节)
  3. 按照流动的功能分:节点流(低级流)和处理流(高级流)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值