java中的字符流

字符流:就是在字节流的基础上,加上编码,形成的数据流

字符流出现的意义:因为字节流在操作字符时,可能会有中文导致的乱码,所以由字节流引申出了字符流。

字符输入流:Reader

常用子类:FileReader

文件字符输入流常用方法:

read();

read(char[ ]);

read(char[ ] ,offset,len);

字符输出流: Writer

常用子类:文件字符输出流: Filewriter

文件字符输出常用方法:

writer();

writer(char[ ]);

writer(char[ ],offset,len);

writer(string);

flush()刷新缓冲区

注意:close()方法默认调用了flush()方法,但是flush()方法只刷新缓冲区,而close()还会关闭IO流

栗子一:读取文件

package dome8;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

public class ZFL {
    /*
    (a=reader.read()) != -1做了三件事
       1.执行reader.reda(),取文件中读取一个字符
       2.执行ch=reader.read(),将读取到的字符赋值给变量
       3.(ch=reader.read())!=-1,用读取到的字符(内容)和-1进行比较
    * */
    //创建一个文件 文件里面有abc三个字符
    //read()  读一个字符,返回该字符相应的ASCII码值,读不到返回-1
    public static void main(String[] args) throws IOException {
        //创建字符流对象
        Reader reader = new FileReader("T//1.txt");  //需要抛异常
        //以字符流的方式读取文件
//        int a = reader.read();
//        System.out.println(a);
//        int b = reader.read();
//        System.out.println(b);
//        int c = reader.read();
//        System.out.println(c);
//        int d = reader.read();  //如果没有则返回-1
//        System.out.println(d);
        //优化上诉的读法,用循环改进
        //又因为不知道循环次数,所有用while循环
        int a;    //定义变量,用来接收读取到的字符
        while ((a=reader.read()) != -1){
//            a=reader.read();
            System.out.println(a);
        }
        //关闭资源
        reader.close();
    }
}

栗子二:拷贝文件数组

package dome8;

import java.io.*;

public class ZFL3 {
    public static void main(String[] args) throws IOException {
        //创建目标目录
        FileReader reader = new FileReader("T//1.txt");
        //创建对象目录
        FileWriter writer = new FileWriter("T//2.txt");
        char[] b = new char[1024];
        int a;
        while ((a=reader.read(b))!=-1){
            writer.write(b,0,a);   //写入文件
        }
        //释放资源
        reader.close();
        writer.close();
    }
}

字符流与字节流的区别:字符流虽然以字节流为基础创建的,但是字节流可以支持声音,视频,图片,文本等所有文件类型,而字符流只支持文本文件。

带缓冲区的字符流:

BufferedReader/BufferedWriter  带缓冲区的字符输入流与字符输出流。

带缓冲区的字符输入流:BufferedReader:常用方法:readLine()  读取一行,如果为文件末尾,返回值为null。

带缓冲区的字符输出流:BufferedWriter:常用方法:writer(string)将字符串写入 到输出流。  newLine()根据系统的行分割符进行换行。

栗子一:

package dome8;

import java.io.*;

public class ZFL3 {
    public static void main(String[] args) throws IOException {
        //需求:通过字符缓冲流,将1.txt中的内容拷贝到2.txt文件中
        //1.创建字符缓冲流对象,关联数据源文件
        //1.1创建普通字符流对象
        FileReader reader = new FileReader("T//1.txt");
        //1.2创建字符缓冲流对象
        BufferedReader fb = new BufferedReader(reader);
        //简化上述代码
        //BufferedReader fb = new BufferedReader(new FileReader("T//1.txt") );
        //2.创建字符缓冲输出流对象,关联目的地文件
        //2.1创建普通的字符输出流对象
        FileWriter writer = new FileWriter("T//2.txt");
        //2.2创建字符缓冲流对象
        BufferedWriter fw = new BufferedWriter(writer);
        //3.定义变量,记录读取到的数据
        int a;
        //4.循环读取,只要条件满足就一直读,并将读取到的内容赋值给变量
        while ((a=fb.read())!=-1){
            //5.将获取到的数据写入到目的地文件中
            fw.write(a);   
        }
        //6.释放资源

        fb.close();
        fw.close();
    }
}

栗子二:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class Demo8 {

    public static void main(String[] args)throws IOException {
        BufferedWriter bw=new BufferedWriter(new FileWriter("3.txt"));
        BufferedReader br=new BufferedReader(new FileReader("1.txt"));
        String value="";
        while((value=br.readLine())!=null) {
            bw.write(value);
            bw.newLine();  //换行
        }
        bw.close();
        br.close();
    }
}

编码与乱码:

乱码:编码与解码不一致,导致的乱码问题,每一种编码格式都有自己独特的编码,如果编码与解码不一致,势必会导致乱码,例如用Unicode编码,用gbk解码,就会字符与码值不匹配,从而导致乱码。

编码表:编码和解码使用的规则:

ASCII码:美国信息交换标准代码。单字节编码,不支持中文。

gbk:国标码;

Unicode/utf-8  :双字节编码,支持中文(万国码)

代码示例:

public class  读取不同编码的文本文件 {
public static void main(String[] args) throws IOException {
// BufferedReader br=new BufferedReader(new FileReader(new File("C:\Users\Administrator\De
sktop\6.txt")));
// 改进
BufferedReader br=new BufferedReader(new InputStreamReader(new FileInputStream(new File("C:
Users\Administrator\Desktop\6.txt")),"gbk"));
String st = br.readLine();
System.out.println(st);
}
}

转换流
1.InputStreamReader 将字节流转换成字符流 输入
2.OutputStreamWriter 将字节流转换成字符流 输出
3. 构造方法:
① InputStreamReader(InputStream in)
② InputStreamReader(InputStream in, String cs)
③ OutputStreamWriter(OutputStream out)
④ OutputStreamWriter(OutputStream out, String charsetName)
4. 作用:
① 可以将字节流转换成字符流
② 可以使用指定的编码来读取或写入流。

代码示例:

1 public class  转换流 {
2 public static void main(String[] args) throws IOException {
3 InputStreamReader is=new InputStreamReader(new FileInputStream(new File("C:\Users\Administ
4 rator\Desktop\6.txt")),"gbk");
5 char[] c=new char[1024];
6 int value = is.read(c);
7 System.out.println(Arrays.toString(c));
8 }
9 }

字节数组字节输出流
ByteArrayOutputStream
字节数组字节输出流:
特点: 可以将数据写入到 byte 数组中,并且该缓冲区可以随着写入的数据而自增
① 构造方法 :
ByteArrayOutputStream()
② 注意:此类中的方法在关闭此流后仍可被调用,而不会产生任何 IOException
③ 常用方法:
1 》 write(byte[]) 将 byte[] 中的值写入缓冲区字节数组,该缓冲区随着数据的增多而自增。
2 》 toString() 要想获取缓冲区的字节数据,可以通过该方法将其转换为字符串。
代码示例:

 1 public class  字节数组字节输出流 {
 2 public static void main(String[] args) throws IOException {
 3 ByteArrayOutputStream bos = new ByteArrayOutputStream();
 4 String s="abc";
 5 byte[] b=s.getBytes();
 6 System.out.println(Arrays.toString(b));
 7 bos.write(b);
 8 bos.write(b);
 9 bos.close();
10 System.out.println(Arrays.toString(b));
11 System.out.println(bos.toString());
12 }
13 }

对象流 / 序列化与反序列化流
1. 对象流 / 序列化流
ObjectInputStream: 反序列化流
② ObjectOutputStream: 序列化流
1 》常用方法:
writeObject(obj) 将 obj 对象写入到流中
readObject 读取流中的数据
① EOFException 表示读取流意外读到了文件的末尾 ( 就是一个空文件。 )
2 》构造方法
ObjectOutputStream(OutputStream out)
ObjectInputStream(InputStream in)
3 》序列化版本号:
serialVersionUID 序列化版本号:保证序列化流与反序列化流读写一致,保证版本一致性。

栗子一:

public class  用序列化流与反序列化流操作集合 {
public static void main(String[] args) {
ArrayList<Teacher> list=new ArrayList<>();
list.add(new Teacher(" 张三 ", 18, new ClassRoom("0318java")));
list.add(new Teacher(" 李四 ", 18, new ClassRoom("0318java")));
list.add(new Teacher(" 王五 ", 18, new ClassRoom("0318java")));
// writeToFile(list,"stu.txt");
// 读取
System.out.println(readTeacher("stu.txt"));
}
// 带异常处理的 ,序列化
public static void writeToFile(ArrayList<Teacher> list,String fileName) {
// 序列化流进行写入
try(
ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream(new File(fileName)));
){
oos.writeObject(list);
}catch (Exception e) {
e.printStackTrace();
}
}
// 反序列化
public static ArrayList<Teacher> readTeacher(String fileName) {
ArrayList<Teacher> list=null;
// 反序列化流读取文件中的集合
try(
ObjectInputStream ois=new ObjectInputStream(new FileInputStream(new File(fileName)));
){
list = (ArrayList<Teacher>) ois.readObject();
}catch (Exception e) {
e.printStackTrace();
}
return list;
}
}
class Teacher implements Serializable{
/**
*  序列化版本号:默认版本号为 1l
*/
private static final long serialVersionUID = 1L;
private String name;
private int age;
private ClassRoom cn;// 班级
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 ClassRoom getCn() {
return cn;
}
public void setCn(ClassRoom cn) {
this.cn = cn;
}
@Override
public String toString() {
return "Teacher [name=" + name + ", age=" + age + ", cn=" + cn + "]";
}
public Teacher() {
super();
// TODO Auto-generated constructor stub
}
public Teacher(String name, int age) {
super();
this.name = name;
this.age = age;
}
}
public Teacher(String name, int age, ClassRoom cn) {
super();
this.name = name;
this.age = age;
this.cn = cn;
}
}
class ClassRoom implements Serializable{
/**
*  序列化版本号:保证序列化流与反序列化流读写一致
*/
private static final long serialVersionUID = 3359646767342429683L;
private String no;
public ClassRoom() {
super();
// TODO Auto-generated constructor stub
}
public ClassRoom(String no) {
super();
this.no = no;
}
@Override
public String toString() {
return "ClassRoom [no=" + no + "]";
}
public String getNo() {
return no;
}
public void setNo(String no) {
this.no = no;
}// 班级号码
}
View Code

栗子二:

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;

public class Demo9 {

    public static void main(String[] args)throws IOException, Exception {
        ArrayList<Student6> list=new ArrayList<>();
        list.add(new Student6("张三","1001",18));
        list.add(new Student6("李四","1002",19));
        list.add(new Student6("王五","1003",20));
        ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream(new File("4.txt")));
        oos.writeObject(list);
        oos.close();

        ObjectInputStream ois=new ObjectInputStream(new FileInputStream(new File("4.txt") ));
        ArrayList<Student6> list2=(ArrayList<Student6>) ois.readObject();
        Iterator<Student6> it=list2.iterator();
        while(it.hasNext()) {
            Student6 stu=it.next();
            System.out.println("姓名:"+stu.getName()+"	学号:"+stu.getStuNo()+"	年龄+	:"+stu.getAge());
        }
    }
}
class Student6 implements Serializable{
    /**
     *
     */
    private static final long serialVersionUID = 2658878058482366562L;
    private String name;
    private String stuNo;
    private int age;

    public Student6() {
        super();
    }
    public Student6(String name,String stuNo,int age) {
        this.name=name;
        this.stuNo=stuNo;
        this.age=age;

    }
    public void setName(String name) {
        this.name=name;
    }
    public String getName() {
        return name;
    }
    public void setStuNo(String stuNo) {
        this.stuNo=stuNo;
    }
    public String getStuNo() {
        return stuNo;
    }
    public void setAge(int age) {
        this.age=age;
    }
    public int getAge() {
        return age;
    }
    @Override
    public String toString() {
        return "Student6 [name=" + name + ", stuNo=" + stuNo + ", age=" + age + "]";
    }
}
View Code

EOFException表示输入过程中意外地到达文件尾或流尾的信号

字符流写入 要刷新/关流才能写入(刷新也是调用了flush(刷新)方法)
就像水龙头带软管,开水龙头要等一会儿水才能流出来,就和需要刷新一样

字节流不需要刷新,是因为字节流是一个字节一个字节读和写的,而字符流是三个字节或者两个字节读和写的,所以
字符流需要刷新,而字节流不需要刷新

原文地址:https://www.cnblogs.com/zxy6/p/14277761.html