目录
一.IO流
作用: (对于程序而言)用于读写数据(本地数据, 网络数据)
二.IO流体系
1.字节输出流
2.字节输入流
3.文件拷贝
3.字符集
字符流
字符输入流
字符输出流
缓冲流
转换流
序列化流
编辑反序列流
打印流
一.IO流
I: input O: output 流: 想流水一样传输数据
作用: (对于程序而言)用于读写数据(本地数据, 网络数据)
(写)输出流(output): 程序-------->文件
(读)输入流(input): 文件--------->程序
IO流按照操作文件的类型可以分类为:
字节流: 可以操作所有类型的文件
字符流: 只能操作纯文本文件(用window系统自带的记事本打开并且能够读懂的文件)
二.IO流体系
1.字节输出流
FileOutputStream
代码示范:
import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; public class IODemo1 { public static void main(String[] args) throws IOException { FileOutputStream fos = new FileOutputStream("C:\\Users\\怪\\Desktop\\abc\\b.txt"); fos.write(97); fos.close(); } }
结果展示:
注意:
(1)创建字节输出流对象, 参数可以是字符串代表的路径或File对象
(2)创建字节输出流对象, 如果文件不存在会创建一个新的文件,不过要保证父级路径存在
(3)创建字节输出流对象, 如果文件已经存在,会先清空文件
(4)在写数据时, write方法的参数时整数, 但实际上存进去的是ASCII码值对应的字符
(5)释放资源, 每次使用完流后都要释放资源
FileOutputStream写数据的3种方式
方法名称 说明
void write(int b) 一次写一个字节数据
void write(byte[ ] b) 一次写一个字节数组数据
void write(byte[ ] b,int off,int len) 一次写一个字节数组的部分数据
代码示范:import java.io.FileOutputStream; import java.io.IOException; public class IODemo2 { public static void main(String[] args) throws IOException { FileOutputStream fos = new FileOutputStream("D:\\Java\\java\\Demo2_12_4\\src\\a.txt"); //1.write(int b) //fos.write(97); //2.write(byte[]) byte[] bt1 = {97,98,99,100,101,102}; //fos.write(bt1); //3.write(byte[],int off,int len) //int off起始索引 int len 个数 fos.write(bt1,0,3); fos.close(); } }
运行write(byte[ ] b)结果展示:运行write(byte[ ] b, int off, int len)结果展示:
如何换行写?
代码示范:
import java.io.FileOutputStream; import java.io.IOException; public class IODemo3 { public static void main(String[] args) throws IOException { FileOutputStream fos = new FileOutputStream("D:\\Java\\java\\Demo2_12_4\\src\\a.txt"); //将字符串转化为字节类型 String s1 = "abc"; byte[] bytes1 = s1.getBytes(); fos.write(bytes1); //换行操作 String s2 = "\r\n"; byte[] bytes2 = s2.getBytes(); fos.write(bytes2); //在添加字符 String s3 = "123"; byte[] bytes3 = s3.getBytes(); fos.write(bytes3); fos.close(); } }
结果展示:
如何实现续写?
在创建FileOutputStream对象的第二个参数写上true(表示打开续写, 默认为false)
2.字节输入流
FileInputStream: 操作本地文件的字节输入流, 可以把本地文件的数据读取到程序中来
代码示范:
import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; public class IOStreamDemo1 { public static void main(String[] args) throws IOException { FileInputStream fis = new FileInputStream("D:\\Java\\java\\Demo1_12_5\\src\\IOStreamDemo\\b.txt"); int read1 = fis.read();//返回的是对应的ASCII码值 System.out.println(read1); int read2 = fis.read(); System.out.println((char)read2); int read3 = fis.read(); System.out.println((char)read3); int read4 = fis.read(); System.out.println(read4); fis.close(); } }
结果展示:
注意: 读到末尾就是-1
FileInputStream的循环读取
代码示范:
import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; public class IOStreamDemo2 { public static void main(String[] args) throws IOException { FileInputStream fis = new FileInputStream("D:\\Java\\java\\Demo1_12_5\\src\\IOStreamDemo\\b.txt"); //创建一个变量来存储 int a = 0; //read: 读取数据,并将下标移动的下一位 //利用末尾是-1来作为结束标志 while((a = fis.read())!=-1){ System.out.println((char)a); } fis.close(); } }
结果展示:
3.文件拷贝
核心思想: 边读边写
代码示范:
import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; public class IOStreamDemo3 { public static void main(String[] args) throws IOException { FileInputStream fis = new FileInputStream("C:\\Users\\怪\\Desktop\\abc\\aa.txt"); FileOutputStream fos = new FileOutputStream("D:\\Java\\java\\Demo1_12_5\\src\\IOStreamDemo\\b.txt"); int a = 0; while((a = fis.read()) != -1){ fos.write(a); } //释放资源 //先创建的后释放 fos.close(); fis.close(); }
结果展示:
FileInputStream一次读取多个字节
代码示范:
import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; public class IOStreamDemo4 { public static void main(String[] args) throws IOException { FileInputStream fis = new FileInputStream("D:\\Java\\java\\Demo1_12_5\\src\\IOStreamDemo\\b.txt"); //一次读取多个字节数据,有数组长度决定 byte[] by1 = new byte[2]; //本次读取了多少个字节 int len1 = fis.read(by1); System.out.println(len1); String str1 = new String(by1,0,len1); System.out.println(str1); int len2 = fis.read(by1); System.out.println(len2); String str2 = new String(by1,0,len2); System.out.println(str2); int len3 = fis.read(by1); System.out.println(len1); String str3 = new String(by1,0,len3); System.out.println(str3); fis.close(); } }
结果展示:
3.字符集
GBK字符集
1.在计算机中,任意数据都是以二进制的形式来存储的
2.计算机中最小的存储单元是一个字节
3.ASCII字符集中,一个英文占一个字节
4.简体中文版Windows,默认使用GBK字符集
5.GBK字符集完全兼容ASCII字符集
一个英文占一个字节,二进制第一位是0
一个中文占两个字节,二进制高位字节的第一位是1Unicode字符集
1.Unicode字符集的UTF-8编码格式(UTF-8是Unicode中的一种编码方式,不是字符集)
一个英文占一个字节,二进制第一位是0,转成十进制是正数一个中文占三个字节,二进制第一位是1,第一个字节转成十进制是负数
产生乱码的原因:
1. 不要用字节流读取文本文件
2. 编码解码时使用同一个码表,同一个编码方式编码和解码方法
编码
String类中的方法 说明
public byte[ ] getBytes() 使用默认方式进行编码
public byte[ ] getBytes(string charsetName) 使用指定方式进行编码
解码
String类中的方法 说明
string(byte[] bytes) 使用默认方式进行解码
string(bytel] bytes,string charsetName) 使用指定方式进行解码
代码示范:import java.io.UnsupportedEncodingException; import java.util.Arrays; public class Demo1 { public static void main(String[] args) throws UnsupportedEncodingException { String str1 = "ni们好"; //默认UTF-8 byte[] bytes1 = str1.getBytes(); System.out.println(Arrays.toString(bytes1)); //GBK byte[] bytes2 = str1.getBytes("GBK"); System.out.println(Arrays.toString(bytes2)); //解码 //默认 String str2 = new String(bytes1); System.out.println(str2); //GBK String str3 = new String(bytes1,"GBK"); System.out.println(str3);//为什么会乱码? //因为bytes1是用UTF-8进行编码的 //而str3是用GBK进行解码的,所以会乱码 } }
结果展示:
字符流
字符流的底层其实就是字节流
字符流 = 字节流 + 字符集
特点:
输入流:一次读一个字节,遇到中文时,一次读多个字节输出流:底层会把数据按照指定的编码方式进行编码,变成字节再写到文件中
注意:
只能对纯文本文件进行读写操作字符输入流
步骤:
第一步:创建对象
public FileReader(File file) 创建字符输入流关联本地文件public FileReader(String pathname)创建字符输入流关联本地文件
第二步: 读取数据public int read() 读取数据,读到末尾返回-1
public int read(char[] buffer) 读取多个数据,读到末尾返回-1
第三步:释放资源
public void close() 释放资源/关流代码示范:无参read( )
import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; public class FileReaderDemo1 { public static void main(String[] args) throws IOException { FileReader fr = new FileReader("D:\\Java\\java\\Demo1_12_6\\src\\c.txt"); //读取数据 int ch; while ((ch = fr.read()) != -1) { System.out.print((char)ch); } //释放资源 fr.close(); } }
结果展示:
注意:ch表示的不是二进制的数值,而是对应十进制的数值
代码示范: 有参read(char[ ] 变量名)
import java.io.FileReader; import java.io.IOException; public class FileReaderDemo2 { public static void main(String[] args) throws IOException { FileReader fr = new FileReader("D:\\Java\\java\\Demo1_12_6\\src\\c.txt"); //一次读取多个数据 char[] ch1 = new char[3]; int len; //有参read方法 while ((len = fr.read(ch1)) != -1) { System.out.print(new String(ch1,0,len)); } //释放资源 fr.close(); } }
结果展示:
字符输出流
步骤:
第一步:创建对象
public FileWriter(File file) 创建字符输出流关联本地文件
public Filewriter(String pathname) 创建字符输出流关联本地文件
public FileWriter(File file, boolean append) 创建字符输出流关联本地文件, 可续写
public Filewriter(string pathname, boolean append) 创建字符输出流关联本地文件,可续写
第二步:读取数据
void write(int c) 写出一个字符
void write(string str) 写出一个字符串
void write(String str, int off, int len) 写出一个字符串的一部分
void write(char[] cbuf) 写出一个字符数组
void write(char[] cbuf, int off, int len) 写出字符数组的一部分
第三步:释放资源
public void close() 释放资源/关流代码示范:
import java.io.FileWriter; import java.io.IOException; public class FileWriteDemo1 { public static void main(String[] args) throws IOException { //true表示打开续写 FileWriter fw = new FileWriter("D:\\Java\\java\\Demo1_12_6\\src\\c.txt",true); //写入数据 fw.write("字节"); char[] ch1 = {'1','a','c'}; fw.write(ch1); //释放资源 fw.close(); } }
结果展示:
缓冲流
缓冲流可以提高性能,如何提高性能?
缓冲流自带8192的缓冲区
可以提高字节流的读写性能
对字符流就没有那么明显, 但有两个特有方法
字符输出流特有的方法: BufferedReader: readLine( )(读取一行代码, 没有数据可以读取就返回null)
字符输出流特有的方法: BufferedWriter: newLine( )(跨平台换行)
字节缓冲流拷贝文件
代码示范:
import java.io.*; public class BufferedStreamDemo1 { public static void main(String[] args) throws IOException { //利用字节缓冲流拷贝文件 //创建对象 BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:\\Java\\java\\Demo1_12_7\\src\\BufferedInputStreamDemo1\\a.txt")); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("D:\\Java\\java\\Demo1_12_7\\src\\BufferedInputStreamDemo1\\copy.txt")); //循环读取 int b = 0; while((b = bis.read()) != -1){ bos.write(b); } //释放资源 bos.close(); bis.close(); } }
结果展示:
字符缓冲流特有方法
readLine( )代码示范:
import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; public class Test1 { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new FileReader("D:\\Java\\java\\Demo1_12_7\\src\\BufferedInputStreamDemo1\\a.txt")); String str = br.readLine(); System.out.println(str); br.close(); } }
结果展示:
newLine( )代码示范:
import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; public class Test2 { public static void main(String[] args) throws IOException { BufferedWriter bw = new BufferedWriter(new FileWriter("D:\\Java\\java\\Demo1_12_7\\src\\BufferedInputStreamDemo1\\copy1.txt")); String s1 = "繁星"; bw.write(s1); bw.newLine(); String s2 = "春水"; bw.write(s2); bw.newLine(); bw.close(); } }
结果展示:
转换流
InputStreamReader
OutStreamWriter
作用: 让字节流可以使用字符流中的方法
代码示范: 让字节流使用字符缓冲流
import java.io.*; public class Test2 { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("D:\\Java\\java\\Demo2_12_7\\src\\InputStreamReaderDemo1\\aa.txt"))); String str = br.readLine(); System.out.println(str); br.close(); } }
结果展示:
序列化流
可以把Java中的对象写到本地文件中
构造方法
public Objectoutputstream(Outputstream out) 把基本流包装成高级流
成员方法
public final void writeobject(object obi) 把对象序列化(写出)到文件中去
代码示范:第一段是类的代码,第二段是测试代码import java.io.Serializable; public class Student implements Serializable { private String name; private int age; public Student() { } public Student(String name, int age) { this.name = name; this.age = age; } /** * 获取 * @return name */ public String getName() { return name; } /** * 设置 * @param name */ public void setName(String name) { this.name = name; } /** * 获取 * @return age */ public int getAge() { return age; } /** * 设置 * @param age */ public void setAge(int age) { this.age = age; } public String toString() { return "Student{name = " + name + ", age = " + age + "}"; } }
import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; public class Test3 { public static void main(String[] args) throws IOException { Student stu = new Student("张三",65); //创建对象 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\\Java\\java\\Demo2_12_7\\src\\InputStreamReaderDemo1\\a.txt")); //使用成员方法 oos.writeObject(stu); //释放资源 oos.close(); } }
结果展示:
注意:
类要实现Serializable接口,不然就会报错(Serializable接口里面是没有抽象方法,是标记型接口
一旦实现了这个接口,那么就表示当前的类可以被序列化)
反序列流构造方法
public objectInputstream(Inputstream out) 把基本流变成高级流
成员方法
public object readObject() 把序列化到本地文件中的对象,读取到程序中来代码示范:
import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.ObjectInputStream; public class Test4 { public static void main(String[] args) throws IOException, ClassNotFoundException { //创建对象 ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:\\Java\\java\\Demo2_12_7\\src\\InputStreamReaderDemo1\\a.txt")); //使用方法 Object o1 = ois.readObject(); System.out.println(o1); //释放资源 ois.close(); } }
结果展示:
打印流
作用:打印流可以实现方便、高效的打印数据到文件中去
打印流一般是指: PrintStream,PrintWriter
可以实现打印什么数据就是什么数据,例如打印整数97写出去就是97,打印boolean的true,写出去就是true。
PrintStream
构造方法 说明
public PrintStream(Outputstream os) 打印流直接通向字节输出流管道
public PrintStream(File f) 打印流直接通向文件对象
public PrintStream(String filepath) 打印流直接通向文件路径
方法
public void print(Xxx xx) 打印任意类型的数据出去代码示范:PrintStream( )
import java.io.FileNotFoundException; import java.io.PrintStream; import java.io.PrintWriter; public class PrintStreamDemo1 { public static void main(String[] args) throws FileNotFoundException { //创建对象 PrintStream ps = new PrintStream("D:\\Java\\java\\Demo3_12_7\\src\\a.txt"); //添加数据 ps.println(123); ps.println("abc"); ps.println(123.456); ps.println(true); //释放资源 ps.close(); } }
结果展示:
PrintWriter( )和PrintStream的打印基本一致