Java基础篇之IO流(2)

字节缓冲区流概述与使用:

字节缓冲流 :

BufferedOutputStream:字节缓冲输出流

BufferedInputStream:字节缓冲输入流

BufferedOutputStream(OutputStream out)

使用这种构造方法,它提供了一个默认的缓冲区大小,所以一般我们使用默认缓冲区

为什么构造方法传递的是一个:OutputStream,而不是具体的文件或者路径呢

字节缓冲区流仅仅提供缓冲区,而真正的底层的读写数据还得需要基本的流对象进行操作

import java.io.*;

public class BufferedStreamDemo {
    public static void main(String[] args) throws IOException {
        //FileOutputStream fos = new FileOutputStream("a.txt");
        //BufferedOutputStream bos = new BufferedOutputStream(fos);
        //上面两句和下面一句效果相同
//        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("a.txt"));
//        bos.write("hello".getBytes());
//        bos.close();
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("a.txt"));
        //方式一一次读取一个字节
//        int by;
//        while ((by=bis.read())!=-1){
//            System.out.println((char)by);
//        }
        byte []bys = new byte[1024];
        int len;
        while ((len = bis.read(bys))!=-1){
            System.out.print(new String(bys,0,len));
        }
        bis.close();
    }
}

字节流四种方式复制JPG并测试效率:

复制文件时间计算可System类方法实现

public static long currentTimeMillis():返回以毫秒为单位的当前时间。

426  1  7  1

import java.io.*;

public class CopyAviTest {
    public static void main(String[] args) throws IOException {
        //记录开始时间
        long start = System.currentTimeMillis();
        //记录结束时间
        method1();
        method2();
        method3();
        method4();
        long end = System.currentTimeMillis();
        System.out.println("共"+(end - start)+"毫秒");
    }
    private static void method4() throws IOException {
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("d:\\timg.jpg"));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy.jpg"));
        byte[]bys = new byte[1024];
        int len;
        while ((len = bis.read(bys))!=-1){
            bos.write(bys,0,len);
        }
        bis.close();
        bos.close();
    }
    private static void method3() throws IOException {
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("d:\\timg.jpg"));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy.jpg"));
        int by;
        while ((by = bis.read())!=-1){
            bos.write(by);
        }
        bis.close();
        bos.close();
    }
    private static void method2() throws IOException {
        FileInputStream fis = new FileInputStream("d:\\timg.jpg");
        FileOutputStream fos = new FileOutputStream("copy.jpg");
        byte []bys = new byte[1024];
        int len;
        while ((len = fis.read(bys))!=-1) {
            fos.write(bys, 0, len);
        }
        fis.close();
        fos.close();

}
    private static void method1() throws IOException {
        FileInputStream fis = new FileInputStream("d:\\timg.jpg");
        FileOutputStream fos = new FileOutputStream("copy.jpg");
        int by;
        while ((by = fis.read())!=-1){
            fos.write(by);
        }
        fis.close();
        fos.close();
    }
}

可通过分别注释方法获取时间分别为

426  1  7  1

笔者此处是用的jpg格式不大,所以方法2和方法4相差不大

但多试验其他格式

会发现带缓冲字节流效率最高,即第四种方法

转换流出现的原因:

字节流一次读取一个字节的方式读取带有汉字的文件是有问题的,因为你读取一个字节后就转为字符输出了,而汉字是由两个字节组成的,所以会出问题。

文件复制时,字节流读取 一个字节,写入一个字节,这个未出现问题,是因为最终底层会根据字节做拼接,得到汉字。

汉字存储规则:

左边的字节数据肯定是负数,右边的字节数据可能是负数,也可能是正数,大部分情况下是负数

由于字节流操作中文不是特别方便,Java就提供了转换流

转换流 = 字节流+编码表

文件内容如下:

import java.util.Arrays;

public class FileDemo {
    public static void main(String[] args) {
String s ="你好";
byte[]bys =s.getBytes();
        System.out.println(Arrays.toString(bys));
    }
}

输出结果:

[-28, -67, -96, -27, -91, -67]

编码表概述:

编码表:

由字符及其对应的数据组成的一张表

ASCII:

‘a’  97

‘A’  65

‘0’  48

常见的编码表:

ASCII:美国标准信息交换码,用一个字节的7位表示数据

ISO-8859-1:欧洲码表,用一个字节的8位表示数据,兼容ASCII

GB2312:中文码表,兼容ASCII

GBK:中文码表的升级版,融合了更多的中文文字符号,兼容ASCII

UTF-8:是一种可变长度的字符编码,用1-3个字节表示数据,又称为万国码,兼容ASCII。用在网页上可以统一页面中的中文简体繁体和其他语言的显示。

乱码问题:

针对同一个数据采用的编码和解码的解码表不一致导致的。

字符串中的编码解码问题:

编码

把看得懂的变成看不懂的

public byte[] getBytes(String charsetName) throws UnsupportedEncodingException

使用指定的字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中。

解码

把看不懂的变成看得懂的

public String(byte[] bytes, String charsetName)

通过使用指定的 charset解码指定的 byte 数组,构造一个新的 String。

重点强调 :  编码和解码的方式需要一致

import java.io.UnsupportedEncodingException;
import java.util.Arrays;

public class n {
    public static void main(String[] args) throws UnsupportedEncodingException {
        String s = "你好";
        //编码
//        byte[]bys = s.getBytes("GBK");
        //输出:[-60, -29, -70, -61]
        byte[]bys = s.getBytes("UTF-8");
        //[-28, -67, -96, -27, -91, -67]
//        byte[]bys = s.getBytes("UTF-8");
        System.out.println(Arrays.toString(bys));
        String ss = new String(bys,"UTF-8");
        System.out.println(ss);
    }
}

转换流中编码与解码问题:

转换流其实就是一个字符流。

转换流 = 字节流+编码表

OutputStreamWriter 字符输出流

public OutputStreamWriter(OutputStream out)

                根据默认编码把字节流的数据转换为字符流

public OutputStreamWriter(OutputStream out,String charsetName)

                根据指定编码把字节流数据转换为字符流

InputStreamReader 字符输入流

public InputStreamReader(InputStream in)

                用默认的编码读数据

public InputStreamReader(InputStream in,String charsetName)

import java.io.*;

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

        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("osw.txt"),"UTF-8");
        osw.write("你好");
        osw.close();
        InputStreamReader isr = new InputStreamReader(new FileInputStream("osw.txt"),"UTF-8");
        int ch;
        while ((ch=isr.read())!=-1){
            System.out.print((char)ch);
        }
        isr.close();
    }
}

字符流OutputStream写数据方法:

OutputStreamWriter写数据方法

public void write(int c):写一个字符

public void write(char[] cbuf):写一个字符数组

public void write(char[] cbuf,int off,int len):写一个字符数组的一部分

public void write(String str):写一个字符串

public void write(String str,int off,int len):写一个字符串的一部分

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;

public class OutputStreamDemo {
    public static void main(String[] args) throws IOException {
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("o.txt"));
//        osw.write(97);
//        osw.write('a');
        //写完数据后没有发现数据
        //1字符等于2字节
        //文件中数据存储的基本单位是字节刷新该流的缓冲
        //字符数组
//        char[]chs = {'a','b','c','d'};
//        osw.write(chs,1,2);
        //字符串
//        osw.write("hello");
        osw.write("hello",0,3);
        //osw.flush();//刷新
        osw.close();//释放资源前先做刷新,防止数据丢失
    }
}

字符流InputStreamReader读数据的方式:

public int read():一次读取一个字符

public int read(char[] cbuf):一次读取一个字符数组

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;

public class newtest {
    public static void main(String[] args) throws IOException {
        InputStreamReader isr = new InputStreamReader(new FileInputStream("o.txt"));
//        int ch;
//        while ((ch = isr.read())!=-1){
//            System.out.print((char)ch);
        char []ch = new char[1024];
        int len;
        while ((len = isr.read(ch))!=-1){
            System.out.println(new String(ch,0,len));
        }
    }
}

字符流练习之复制Java文件:

import java.io.*;

public class Demo2 {
    public static void main(String[] args) throws IOException {
        InputStreamReader isr = new InputStreamReader(new FileInputStream("D:\\IdeaProjects\\Mybuffered\\src\\Day_14\\OutputStreamDemo.java"));
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("copy.java"));
//        int ch;
//        while ((ch = isr.read())!=-1){
//            osw.write(ch);
//        }
        char []cha = new char[1024];
        int len;
        while ((len = isr.read(cha))!=-1){
            osw.write(cha,0,len);
        }
        osw.close();
        isr.close();
    }
}

字符流的练习之复制java文件改进版:

转换流名字较长,为简化书写,提供了

FileWriter:用来写入字符文件的便捷类

FileReader:用来读取字符文件的便捷类

import java.io.*;

public class Demo2 {
    public static void main(String[] args) throws IOException {
        InputStreamReader isr = new InputStreamReader(new FileInputStream("D:\\IdeaProjects\\Mybuffered\\src\\Day_14\\OutputStreamDemo.java"));
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("copy.java"));
//        int ch;
//        while ((ch = isr.read())!=-1){
//            osw.write(ch);
//        }
        char []cha = new char[1024];
        int len;
        while ((len = isr.read(cha))!=-1){
            osw.write(cha,0,len);
        }
        osw.close();
        isr.close();
    }
}

字符缓冲区流的概述和使用:

BufferedWriter

将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。

可以指定缓冲区的大小,或者接受默认的大小。在大多数情况下,默认值就足够大了。

构造方法:

BufferedWriter(Writer out)

BufferedReader

从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。

可以指定缓冲区的大小,或者可使用默认的大小。大多数情况下,默认值就足够大了。

构造方法:

BufferedReader(Reader in)

import java.io.*;

public class BufferedDemo {
    public static void main(String[] args) throws IOException {
//        BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt"));
//        bw.write("hello");
//        bw.close();
        BufferedReader br = new BufferedReader(new FileReader("b.txt"));
//        int by;
//        while ((by = br.read())!=-1){
//            System.out.print((char)by);
//        }
        char []ch = new char[1024];
        int len;
        while ((len = br.read(ch))!=-1){
            System.out.print(new String(ch,0,len));
        }
        br.close();
    }
}

字符缓冲区流之复制文本文件:

把项目目录下的a.txt内容复制到项目目录下的b.txt中

数据源:

a.txt---读数据---字符流---InputStreamReader---FileReader---BufferedReader

目的地:

b.txt---写数据---字符流---OutputStreamWriter---FileWriter---BufferedWriter

字符缓冲区特殊功能:

BufferedWriter

void newLine():写入一个行分隔符,这个行分隔符是由系统决定的

 BufferedReader

String readLine():包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null

import java.io.*;

public class BufferedDemo {
    public static void main(String[] args) throws IOException {
//        BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt"));
//        for (int x = 0;x<3;x++){
//            bw.write("hello");
        bw.write("\r\n");
//            bw.newLine();
//            bw.flush();
//        }
//        bw.close();

        BufferedReader br = new BufferedReader(new FileReader("b.txt"));
        //读取一次
//        String line = br.readLine();
//        System.out.println(line);
        String line;
        while ((line = br.readLine())!=null){
            System.out.println(line);
        }
        br.close();
    }
}

字符缓冲流特殊功能复制Java文件:

数据源:

BufferedStreamDemo.java---BufferedReader

目的地:

Copy.java---BufferedWriter

 

import java.io.*;

public class BufferedDemo {
    public static void main(String[] args) throws IOException {
        BufferedWriter bw = new BufferedWriter(new FileWriter("b.java"));
        BufferedReader br = new BufferedReader(new FileReader("copy.java"));
        String line;
        while ((line=br.readLine())!=null){
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        bw.close();
        br.close();
    }
}

字符流的5种方式复制文本文件:

基本字符流一次读写一个字符

基本字符流一次读写一个字符数组

缓冲字符流一次读写一个字符

缓冲字符流一次读写一个字符数组

缓冲字符串一次读写一个字符串

重点掌握第五种方法

public class CopyFileTest {
	public static void main(String[] args) throws IOException {
		method1();
		// method2();
		// method3();
		// method4();
		// method5();
	}
	
	//缓冲字符流一次读写一个字符串
	private static void method5() throws IOException {
		BufferedReader br = new BufferedReader(new FileReader("d:\\林青霞.txt"));
		BufferedWriter bw = new BufferedWriter(new FileWriter("窗里窗外.txt"));
		
		String line;
		while((line=br.readLine())!=null) {
			bw.write(line);
			bw.newLine();
			bw.flush();
		}
		
		bw.close();
		br.close();
	}
	
	//缓冲字符流一次读写一个字符数组
	private static void method4() throws IOException {
		BufferedReader br = new BufferedReader(new FileReader("d:\\林青霞.txt"));
		BufferedWriter bw = new BufferedWriter(new FileWriter("窗里窗外.txt"));
		
		char[] chs = new char[1024];
		int len;
		while((len=br.read(chs))!=-1) {
			bw.write(chs, 0, len);
		}
		
		bw.close();
		br.close();
	}
	
	//缓冲字符流一次读写一个字符
	private static void method3() throws IOException {
		BufferedReader br = new BufferedReader(new FileReader("d:\\林青霞.txt"));
		BufferedWriter bw = new BufferedWriter(new FileWriter("窗里窗外.txt"));
		
		int ch;
		while((ch=br.read())!=-1) {
			bw.write(ch);
		}
		
		bw.close();
		br.close();
	}
	
	// 基本字符流一次读写一个字符数组
	private static void method2() throws IOException {
		FileReader fr = new FileReader("d:\\林青霞.txt");
		FileWriter fw = new FileWriter("窗里窗外.txt");

		char[] chs = new char[1024];
		int len;
		while((len=fr.read(chs))!=-1) {
			fw.write(chs, 0, len);
		}

		fw.close();
		fr.close();
	}

	// 基本字符流一次读写一个字符
	private static void method1() throws IOException {
		FileReader fr = new FileReader("d:\\林青霞.txt");
		FileWriter fw = new FileWriter("窗里窗外.txt");

		int ch;
		while ((ch = fr.read()) != -1) {
			fw.write(ch);
		}

		fw.close();
		fr.close();
	}
}

字符流的练习之把集合中的字符串数据存储到文本文件:

思路:

A:创建集合对象

B:往集合中添加字符串元素

C:创建字符缓冲输出流对象

D:遍历集合,得到每一个字符串元素,把字符串元素作为数据写入到文本文件

E:释放资源

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;

public class ArraylistTest {
    public static void main(String[] args) throws IOException {
        ArrayList<String>array = new ArrayList<String>();
        array.add("hello");
        array.add("world");
        array.add("java");
        BufferedWriter bw = new BufferedWriter(new FileWriter("aaa.txt"));
        for (String s :array){
            bw.write(s);
            bw.newLine();
            bw.flush();
        }
        bw.close();
    }
}

从文本文件中读取数据到集合:

需求: 从文本文件中读取数据到ArrayList集合中,并遍历集合,每一行数据作为一个字符串元素

分析:

A:创建字符缓冲输入流对象

B:创建集合对象

C:读取数据,每一次读取一行,并把该数据作为元素存储到集合中

D:释放资源

E:遍历集合

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;

public class ADemo {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader("a.txt"));
        ArrayList<String>array = new ArrayList<String>();
        String line;
        while ((line = br.readLine())!=null){
            array.add(line);
        }
        br.close();
        for (String s:array){
            System.out.println(s);
        }
    }
}

字符流的练习之把集合中的学生对象数据存储到文本文件:

需求:

把ArrayList集合中的学生数据存储到文本文件

每一个学生数据作为文件中的一行数据

定义一个学生类。

学生:

学号,姓名,年龄,所在城市

it001,张曼玉,35,北京

it002,王祖贤,33,上海

it003,林青霞,30,西安

分析:

A:创建集合对象

B:创建学生对象

C:把学生对象添加到集合中

D:创建字符缓冲输出流对象

E:遍历集合,得到每一个学生对象,然后把该对象的数据拼接成一个指定格式的字符串写到文本文件

F:释放资源

public class Student {
    private String name;
    private int age;
    private String sid;
    private String city;

    public Student() {
    }

    public Student(String name, int age, String sid, String city) {
        this.name = name;
        this.age = age;
        this.sid = sid;
        this.city = city;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getSid() {
        return sid;
    }

    public void setSid(String sid) {
        this.sid = sid;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }
}
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;

public class Test {
    public static void main(String[] args) throws IOException {
        ArrayList<Student>arr = new ArrayList<Student>();
        Student s1 = new Student("张曼玉",35,"it001","北京");
        Student s2 = new Student("林青霞",33,"it002","上海");
        Student s3 = new Student("王祖贤",30,"it003","南京");
        arr.add(s1);
        arr.add(s2);
        arr.add(s3);
        BufferedWriter bw = new BufferedWriter(new FileWriter("c.txt"));
        for (Student s :arr){
            StringBuilder sb = new StringBuilder();
            sb.append(s.getSid()+","+s.getName()+","+s.getAge()+","+s.getCity());
            bw.write(sb.toString());
            bw.newLine();
            bw.flush();
        }
        bw.close();
    }
}

输出结果:

如图

字符流的练习之把文本文件中的学生对象数据读取到集合:

需求:

从文本文件中读取学生数据到ArrayList集合中,并遍历集合

每一行数据作为一个学生元素

it001,张曼玉,35,北京

要使用String类中的一个方法:split()

分析:

A:创建字符缓冲输入流对象

B:创建集合对象

C:读取数据,每一次读取一行数据,把该行数据想办法封装成学生对象,并把学生对象存储到集合中

D:释放资源

E:遍历集合

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;

public class Test {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader("c.txt"));
        ArrayList<Student>arr = new ArrayList<Student>();
        String line;
        while ((line = br.readLine())!=null){
            String[]stry = line.split(",");
            Student s = new Student();
            s.setSid(stry[0]);
            s.setName(stry[1]);
            s.setAge(Integer.parseInt(stry[2]));
            s.setCity(stry[3]);
            arr.add(s);
        }
        br.close();
        for (Student s :arr){
            System.out.println(s.getSid()+"---"+s.getName()+"---"+s.getAge()+"---"+s.getCity());
        }
    }
}

输出结果:

it001---张曼玉---35---北京
it002---林青霞---33---上海
it003---王祖贤---30---南京

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值