IO流
一、IO流概述
* 可以将这种数据传输的操作,看作一种数据的流动,按照流动的方向分为输入Input和输出Output
* Java中的IO操作主要指的是,Java。io包下的一些常用类的使用
* 通过这些常用类对数据进行读取(输入Input) 和写出(输出Output)
二、IO流的分类
按照流的方向来分,可以分为:输入流和输出流 (输出输入可以看作是相对于控制台的输出输入)
* 按照流动的数据类型来分,可以分为:字节流和字符流
* 字节流:
* - 输入流: InputStream
* - 输出流: OutStream
* 字符流:
* - 输入流: Reader
* - 输出流: Writer
一切皆字节:
* 计算机中的任何数据(文本,图片,视频,音乐等等)都是以二进制的形式存储的
* 在数据传输时 也都是以二进制的形式存储的
* 后续学习的任何流 , 在传输时底层都是二进制
三、字节流
01.Java.io.OutputStream
方法摘要
02.FileOutputStream(从控制台写出)输出流
构造方法
方法摘要
案例
public static void main(String[] args) throws IOException {
//FileOutputStream
//创建流 (如果重新构建流(创建对象)在进行写入会让原来文件内容覆盖)
FileOutputStream fos = new FileOutputStream("d://a.txt"); //没有会自动创建
fos.write(65); //写入字节 A
byte[] bytes = {65,66,67,68};
fos.write(bytes); //内容追加在A后面
fos.close();//关闭流
System.out.println("已经写出");
}
// FileOutputStream fos = new FileOutputStream("d://a.txt",true);
//True 会直接在原文件中的内容后面追加,不会覆盖
03.FileInputStream(从文件中读取) 输入流
构造方法
方法摘要
案例
a.读取一个字节
//读取一个字节内容
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("d://a.txt");
/* byte read = (byte) fis.read(); // 返回的是int 强转为字节
System.out.println(read); // 读第一个字节
byte read2 = (byte) fis.read(); // 返回的是int 强转为字节
System.out.println(read2);//读第二个*/
//用循环读取所有内容
while (true){
byte read= (byte) fis.read(); // 返回的是int 强转为字节
System.out.println(read);
if (read == -1){ // 地层中当读取到末尾返回-1
break;
}
}
fis.close();
}
}
b.读取一组字节
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("d://a.txt");
//读取一组字节(开发中常用)
int len; //定义变量,接受读取的个数。
byte[] bytes = new byte[10];
len = fis.read(bytes);//一次读十个
//输出读取的从0到len结尾的字节,防止末尾多读取
System.out.println(new String(bytes,0,len)); //将字节数组,转为字符串输出
len = fis.read(bytes);//一次读十个
System.out.println(new String(bytes,0,len)); //将字节数组,转为字符串输出
len = fis.read(bytes);//一次读十个
System.out.println(new String(bytes,0,len)); //将字节数组,转为字符串输出
fis.close();
//也可以根据读取到尾返回-1,进行设计
}
c.字节流读取文字
public static void main(String[] args) throws IOException {
//此路径为相对路径,项目文件的txt,默认编码为UTF-8,
// 如果使用绝对路径,由于编码和本地计算机的不同,可能会出现乱码的现象
FileInputStream fis = new FileInputStream("b.txt");
//用字节流读取时候,读取的字节存入大小不够,会出现,只读取半个文字的符号问题。
byte[] bytes = new byte[1000];
int len = fis.read(bytes);
System.out.println(new String(bytes,0,len));
fis.close();
}
//后面将介绍字符流读取
四.字符流
01.Writer
用于写入字符流的抽象类。 子类必须实现的唯一方法是write(char [],int,int),flush()和close()。 但是,大多数子类将覆盖此处定义的一些方法,以提供更高的效率,附加功能或两者兼而有之。
方法摘要
02.FileWriter 输出流
FileWriter的Writer的子类,可以使用Writer的所有方法。
使用默认缓冲区大小将文本写入字符文件。 从字符到字节的编码使用指定的charset或平台的default charset 。
文件是否可用或是否可以创建取决于底层平台。 特别是某些平台允许一次仅打开一个文件以供写入FileWriter (或其他文件写入对象)。 在这种情况下,如果涉及的文件已经打开,则此类中的构造函数将失败。
FileWriter用于编写字符流。
构造方法
03.字符的输出(写入到外部文件 write)
public static void main(String[] args) throws IOException {
/* FileWriter fw = new FileWriter("d://a.txt"); //没有会自动创建
fw.write("牛的"); //输出到文件
fw.append("酷酷酷"); //构造中没有ture,文件中内容会直接被覆盖
fw.close();*/
FileWriter fw2 = new FileWriter("d://b.txt",true); //有true就可以内容后面用append去追加
fw2.write("牛的"); //输出到文件
fw2.append("酷酷酷"); //在文件内容后面追加
fw2.append("aaa").append("bbb").append("666");
//fw2.flush(); 注意刷新管道,不然内存的内容显示不到文件中。
// 因为close()方法会自动刷新管道,所以内容可以被写进去,但是如果两者都没有则,内容不会保存到文件中
fw2.close();
}
04.Reader
用于读取字符流的抽象类。 子类必须实现的唯一方法是read(char [],int,int)和close()。 但是,大多数子类将覆盖此处定义的一些方法,以提供更高的效率,附加功能或两者兼而有之。
方法摘要
05.FileReader 输入流
FileReader是Reader的子类。
FileReader用于读取字符流。
构造方法
04.字符的读取(从文件中读取)
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("b.txt"); //读取相对路径的文件
//一次读取一个字符
/* int read = fr.read();
System.out.println((char)read); 将读取到的内容转为字符*/
/*
循环去读一个一个字符
*
* */
while (true){
int c = fr.read();
if (c == -1){ //当读取到最后的字符为-1
break;
}
System.out.print((char) c); // 循环结束打印
}
/*
一次读一个数组
* */
char[] chars = new char[100];
int len = fr.read(chars); // 将读取到的内容放到字符数组中
// 为了不浪费读取空间,将读取长度设置为0到len 所读取到的实际长度,而不是整个字符数组
System.out.println(new String(chars,0,len)); //转为字符串输出
fr.close();
}
五、字节转换字符流
01.将字节输入流,转换为字符输入流
public static void main(String[] args) throws IOException {
//字节流 ‘装饰’ 为字符流 :使用了装饰者设计模式
FileInputStream fis = new FileInputStream("d://a.txt");
//将字节输入流,转换为字符输入流
// 参数1:要转换的字节流
//参数2:指定编码名称
InputStreamReader isr = new InputStreamReader(fis, "gbk");
while (true){
int read = fis.read();
if(read == -1){
break;
}
System.out.println((char) read);
}
}
02.字节输出流,转换为字符输出流
public static void main(String[] args) throws IOException {
//字节输出流,转换为字符输出流
FileOutputStream fos = new FileOutputStream("d://a.txt");
//将字节转字符流
OutputStreamWriter osw = new OutputStreamWriter(fos);
osw.write("牛的牛的");
osw.flush(); //用write刷新管道
osw.close();
}
六、Print与BufferedReader
public static void main(String[] args) throws IOException {
/*
* 字符输出(打印流)
* */
PrintStream ps = new PrintStream("d://a.txt");
ps.println("勇敢牛牛!");
ps.println("不怕困难!");
PrintWriter pw = new PrintWriter("d://a.txt");
pw.println("勇敢牛牛!");
pw.println("不怕困难!");
pw.flush(); //需要刷新管道
pw.close();
// 字节输出流转字符输出(打印流)
FileOutputStream fos = new FileOutputStream("d://a.txt");
PrintWriter pw3 = new PrintWriter(fos);
pw3.println("勇敢牛牛!");
pw3.println("不怕困难!");
pw3.flush(); // 刷新管道
pw3.close();
/*
* 缓存读取流,将字符输入流 转换为带有缓存 可以一次读取一行的缓存字符读取流
* */
FileReader fr = new FileReader("d://a.txt");
BufferedReader br = new BufferedReader(fr);
String s = br.readLine();
System.out.println(s);
fr.close();
br.close();
}
七、properties
public static void main(String[] args) throws IOException {
//Properties 文件 与 Properties;
Properties ppt = new Properties();
//也是以 map 集合进行存储(键=值)
//存
ppt.put("name","中国");
ppt.put("info","上下五千年!!!");
FileWriter fw = new FileWriter("d://Ch.properties"); // 文件后缀要是properties
ppt.store(fw,"简介"); // 传入文件,还有文件的首行注释
fw.close();
//读取
Properties ppt2 = new Properties();
FileReader read = new FileReader("d://Ch.properties");
ppt2.load(read); //调用读取的方法
//通过键来获取值
System.out.println(ppt2.getProperty("name")); // ppt2.get() 也是一样通过键获取值
System.out.println(ppt2.getProperty("info"));
read.close();
}
八、序列化与反序列化
public class demo{
public static void main(String[] args) throws IOException,ClassNotFoundException {
//序列化
Book b = new Book("金苹果","讲述了种植过程");
//输出流文件后坠随便取
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("c://book.jianjie"));
oos.writeObject(b); //传入要写入的对象
oos.close();
//反序列化
ObjectInputStream oos = new ObjectOutputStream(new FileInputStream("c://book.jianjie"));
Object 0 = Ois.readObject();
System.out.println(o);
Book o = (Book)Ois.readObject();
System.out.println(o。getInfo());
}
static class Book implements Serializable { //要有Serializable标记才可以进行序列化
private String name;
private String info;
public Book(String name, String info) {
this.name = name;
this.info = info;
}
public Book() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", info='" + info + '\'' +
'}';
}
}
}
//Externalizable继承自Serializable,使用Externalizable接口需要实现readExternal方法和writeExternal方法来实现序列化和反序列化。
01.部分属性序列化
a.使用transient修饰符,修饰的属性不能被序列化
b.使用static修饰符,修饰的属性不能序列化,可以通过set方法进行复制
c.默认方法writeObjiec和readObject
d.Externalizable中实现的方法也可进行部分序列化