什么是流?
- 概念:内存与存储设备之间的传输数据的通道。
- 水借助管道传输;数据借助流传递
例如:内存中的数据一旦保存后便会存入电脑的某个盘中
流的分类:
按方向:
- 输入流:将存储设备中的内容读入到内存中
- 输出流:将内存中的内容写入到存储设备中
如:将内存中的内容作为中心,输出到存储设备中则为输出流。
按单位:
- 字节流:以字节为单位,可以读写所有数据
- 字符流: 以字符为单位,只能读写文本数据
如:将程序中的字节输出到存储设备中,字节输出流。
按功能:
- 节点流:具有实际传输数据的读写功能。
- 过滤流:在字节流的基础之上增强功能。
如:在字节输出流在表述,具体的传输为节点流,则称为字节输出节点流。
字节流
-
字节流的父类(抽象类):
InputStream:字节输入流 public int read(){} public int read(byte[] b){} public int read(byte[] b ,int off,int len){} OutputStream:字节输出流 public int write(){} public int write(byte[] b){} public int write(byte[] b ,int off,int len){}
字节节点流
- FileOutputStream:
public void write(byte[] b)//一次写多个字节,将b数组中所有字节,写入输出流。 - FileInputStream:
public int read(byte[] b)//从流中读取多个字节,将读到内容存入b数组,返回实际读到的字节数;如果达到文件的尾部,则返回-1
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class TestFileOutPutStream {
public static void main(String[] args) throws IOException {
//1.输出字节流 OutputStream
//2.输出字节节点流,具有实际传输数据的功能(文件路径.boolean append)
//FileOutputStream fos = new FileOutputStream("F:\\java_files\\day31\\target.txt",false);//默认为false重复运行不追加
//此时路径为绝对路径
//路径正确:当文件不存在时,则会自动新建一个文件
//路径错误时,没有盘符
//相对路径: 与上一种形式等价,但此方式为相对于当前项目下寻找路径和文件。
FileOutputStream fos = new FileOutputStream("target.txt",false);
// fos.write(65);//输出单个字节
// fos.write(66);
// fos.write('D');
byte[] bytes = new byte[] {65,66,67,68,'D'};
// fos.write(bytes);//一次输入一组字节 //ABCDD
fos.write(bytes,1,3);//字节数组 起始下标 长度 //BCD
//fos.write('你');//占两个字节,无法直接输出
String s = "你";
byte[] bs = s.getBytes();
System.out.println(bs[0]+"\t"+bs[1]);
fos.write(bs);
}
}
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class TestFileIO {
public static void main(String[] args) throws IOException {
//将指定图片,上传一份到项目里面来
//文件在存储设备中,读到程序中,再从程序中写到存储设备
//输入流
FileInputStream fis = new FileInputStream("D:\\1.png");
//输出流
FileOutputStream fos = new FileOutputStream("2.png");
//byte[] cache = new byte[1024*1024];
//缓冲空间过大过小都不合适
int len = 0;//代表每次读到的字节
while((len = fis.read())!=-1) {
fos.write(len);//读多少写多少
}
//fis.read(cache);
//释放资源;
fis.close();
fos.close();
}
}
字节过滤流
- 缓冲流:BufferedOutputStream/BufferedInputStream
提高IO效率,减少访问磁盘的次数;
数据存储在缓冲区中。flush是将缓存区的内容写入文件中,也可以直接close。 - 对象流:ObjectOutputStream/ObjectInputStream
增强了缓冲区功能
增强了读写8种基本数据类型和字符串功能
增强了读写对象的功能:readObject()、writeObject(Object obj)
使用流传输对象的过程称为序列化、反序列化
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class TestBufferedOutput {
public static void main(String[] args) throws IOException {
//有参构造需要一个字节输出节点流
//先创建字节输出字节流
FileOutputStream fos = new FileOutputStream("buffer.txt");
//增强字节流
BufferedOutputStream bos = new BufferedOutputStream(fos);
//过滤流的write方法,实现写入到缓冲区数组。
bos.write('A');
bos.write('B');
bos.write('C');
bos.write('D');
bos.flush();//刷新缓冲区(将缓冲区的数据一次性写入到文件中,并清空当前缓冲区)
bos.write('E');
bos.write('F');
//bos.flush();
bos.close();//级联的执行了flush方法,释放资源的同时将数据一次性写入到文件里。
FileInputStream fis = new FileInputStream("buffer.txt");
BufferedInputStream bis = new BufferedInputStream(fis);
byte[] bytes = new byte[100];
//bis.read(bytes);
fis.read(bytes);
for(int i = 0 ;i<bytes.length;i++) {
System.out.println((char)bytes[i]);
}
}
}
对象序列化
- 对象序列化的细节:
必须实现Serializable接口
必须保持其所有属性均可序列化
transient修饰为临时属性,不参与序列化
读取到文件尾部的标志:java.io.EOFException
import java.io.EOFException;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
//static依旧属于类的,会影响序列化
//非包装类数据也可以写
public class TestObjectStream {
public static void main(String[] args) throws IOException, ClassNotFoundException{
OutputStream os = new FileOutputStream("obj.txt");
ObjectOutputStream oos = new ObjectOutputStream(os);
Student stu = new Student("kunyan",12,"female",110D,new Address("wuhan","10000"));
Student stu1 = new Student("haha",13,"male",100D,new Address("wuhan","10000"));
oos.writeObject(stu);
oos.writeObject(stu1);
oos.writeInt(30);
InputStream is = new FileInputStream("obj.txt");
ObjectInputStream ois = new ObjectInputStream(is);
//int result = ois.readInt();
//System.out.println(result);
// Object obj = ois.readObject();
//Student s = (Student)obj;
// System.out.println(obj);
//System.out.println(s.name);
while(true) {
try {
Object obj = ois.readObject();
System.out.println(obj.toString());
}catch(Exception e){
break;//到达文件末尾哦。获得EOFException,就停止循环---
}
}
oos.flush();
}
}
//对象自身要支持序列化
//属性也要支持序列化
//transient修饰为临时属性,不参与序列化
class Student implements Serializable{
String name;
Integer age;
String sex;
Double score;
transient Address add;
public Student(String name, Integer age, String sex, Double score,Address add) {
super();
this.name = name;
this.age = age;
this.sex = sex;
this.score = score;
this.add = add;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + ", sex=" + sex + ", score=" + score + ", add=" + add + "]";
}
}
class Address implements Serializable{
String postion;
String zipCode;
public Address(String postion, String zipCode) {
super();
this.postion = postion;
this.zipCode = zipCode;
}
@Override
public String toString() {
return "Address [postion=" + postion + ", zipCode=" + zipCode + "]";
}
}
File类
- 概念:代表物理盘符中的一个文件或者文件夹
- 方法:
createNewFile()//创建一个新文件
Mkdir()//创建一个新目录
Detele()//删除文件或空目录
Exists()//判断File对象所代表的对象是否存在
getAbsolutePath()//获取文件的绝对路径
getName()//取得名字
getParent()//获取文件/目录所在的目录
isDirectory()//是否是目录
isFile()//是否是文件
length()//获取文件的长度
listFiles()//列出目录中的所有内容
renameTo()//修改文件名为
import java.io.File;
import java.io.IOException;
public class TestFiles {
public static void main(String[] args) throws Exception {
File file = new File("F:\\test\\testfiles.txt");
// System.out.println(file.canExecute());//文件是否存在
// System.out.println(file.canWrite());//能不能修改文件
// System.out.println(file.canRead());//能不能执行文件
// System.out.println(file.createNewFile());//文件已存在则返回false,文件不存在则true并新建
// System.out.println(file.delete());
// Thread.sleep(3000);
// file.deleteOnExit();//jvm终止时,则执行删除文件
// System.out.println(file.exists());
// System.out.println(file.getAbsolutePath());//绝对路径
// System.out.println(file.getPath());//相对路径
// System.out.println(file.getName());//名字加后缀
// System.out.println(file.getFreeSpace()/1024/1024/1024);//获取硬盘的空闲空间
// System.out.println(file.getTotalSpace()/1024/1024/1024);//总空间
// System.out.println(file.getParent());//指定文件的父级目录
// System.out.println(file.isDirectory());//判断是否为文件夹
// System.out.println(file.isFile());//判断是否是文件
// System.out.println(file.isHidden());//判断是否隐藏
// System.out.println((System.currentTimeMillis()-file.lastModified())/1000/60);//获取文件最后一次获取时间
// System.out.println(file.length());//文件内容的字节
// System.out.println(file.mkdirs());
System.out.println(file.createNewFile());
}
}
import java.io.File;
public class TestFileList {
public static void main(String[] args) {
File file = new File("F:\\java_files");
// String[] fileName = file.list();//获取文件夹中的所有文件(包含文件夹)的名字 String类型
// for(String fname:fileName) {
// System.out.println(fname);
// }
File[] files = file.listFiles();
for(File f:files) {
if(f.isFile()) {
if(f.getName().endsWith(".docx")) {
System.out.println(f.getName());
}
}
}
}
}
FileFilter接口
-
public interface FileFilter
boolean accept(File pathname) -
当调用File类中的listFiles()方法时,支持传入FileFilter接口接口实现类,对获取文件进行过滤,只有满足条件的文件的才可出现在listFiles()的返回值中。
import java.io.File;
import java.io.FileFilter;
import java.io.ObjectOutputStream;
public class TestFileList {
public static void main(String[] args) {
File file = new File("F:\\java_files");
// String[] fileName = file.list();//获取文件夹中的所有文件(包含文件夹)的名字 String类型
// for(String fname:fileName) {
// System.out.println(fname);
// }
File[] files = file.listFiles(new MyFilter());
for(File f:files) {
// if(f.isFile()) {
// if(f.getName().endsWith(".docx")) {
System.out.println(f.getName());
// }
// }
}
}
}
class MyFilter implements FileFilter{
@Override
public boolean accept(File pathname) {
if(pathname.isFile()) {
if(pathname.getName().endsWith(".docx")) {
return true;
}
}
return false;
}
}
import java.io.File;
import java.io.FileFilter;
public class TestShowAllFiles {
static int count = 0;
public static void main(String[] args) {
//1.遍历F盘下,所有是.class为结尾的文件
File file = new File("F:\\");
showall(file);
System.out.println("一共"+count+"个文件");
}
public static void showall(File dir) {
File[] file = dir.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
if(pathname.isDirectory()) {//文件夹保存
return true;
}
if(pathname.isFile()) {//符合要求的文件
if(pathname.getName().endsWith(".class")) {
return true;
}
}
return false;
}
});
if(file!=null) {
for(File f:file) {
if(f.isFile()) {
count++;
System.out.println(f.getName());
}else {
showall(f);
}
}
}
}
}
字符编码
- ISO-8859-1 收录除ASCII外,还包括西欧、希腊语、泰语、阿拉伯语 希伯来语对应的文字符号
- UTF-8 针对Unicode的可变长度字符编码
- GB2312 简体中文
- GBK 简体中文、扩充
- BIG5 台湾,繁体中文
当编码方式和解码方式不一致时,会出现乱码
import java.io.UnsupportedEncodingException;
public class TestEncoding {
public static void main(String[] args) throws UnsupportedEncodingException {
String str = "你好世界123abc陶喆";//文本内容
//byte[] bs = str.getBytes();//获得字符的二进制表现形式
byte[] bs = str.getBytes("GBK");
for(int i = 0 ; i<bs.length;i++) {
System.out.println(bs[i]);
}
//解码二进制
String str2 = new String(bs,"BIG5");
System.out.println(str2);
byte[] bs2 = str2.getBytes("BIG5");
String str3 = new String(bs2,"GBK");
System.out.println(str3);
}
}
字符流
- 字符流的父类(抽象类):
Reader:字符输入流
public int read(){}
public int read(char[] c){}
public int read(char[] b ,int off,int len){}
Writer:字符输出流:
public int write(int n){}
public int write(String str){}
public int write(char[] c){}
字符节点流
- FileWriter:
public void write(String str)//一次写多个字符,将b数组中所有字符,写入输出流。 - FileReader:
public int read(char[] c)//从流中读取多个字符,将读到内容存入到c数组,返回实际读到的字符数;如果达到文件的尾部,则返回-1.
import java.io.FileReader;
import java.io.FileWriter;
//但记事本中没有换行
public class TestWriter {
public static void main(String[] args) throws Exception {
FileWriter fw = new FileWriter("chars.txt");
char[] chars = new char[] {'举','头','望','明','月'};
fw.write("床前明月光");
fw.write("疑是地上霜");
fw.write(chars);
fw.flush();
FileReader fr = new FileReader("chars.txt");
char[] cache = new char[5];
while(true) {
int n = fr.read(cache);
if(n==-1) {
break;
}
for(int i = 0;i<n;i++) {
System.out.print(cache[i]);
}
System.out.println();
}
}
}
字符过滤流
-
缓冲流:BufferedWrite/BufferedReader
支持输入换行符
可一次写一行、读一行 -
PrintWriter:
封装了print()/println()方法,支持写入后换行。
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class TestBuffer {
public static void main(String[] args) throws Exception {
FileWriter fw = new FileWriter("buf.txt");
BufferedWriter bw = new BufferedWriter(fw);
bw.write("床前明月光");
bw.newLine();//根据平台提供换行符
bw.write("疑是地上霜");
bw.flush();
}
}
//过滤流比BufferedWriter更为方便,提供println打印后换行的方法
//字符流读到末尾返回null
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.PrintWriter;
public class TestPrinter {
public static void main(String[] args) throws Exception {
FileWriter fw = new FileWriter("prints.txt");
PrintWriter pw = new PrintWriter(fw);
pw.println("床前明月光");
pw.println("疑似地上霜");
pw.println("举头望明月");
pw.println("低头思故乡");
pw.flush();
FileReader fr = new FileReader("prints.txt");
BufferedReader br = new BufferedReader(fr);
while(true) {
String str = br.readLine();
if(str == null) {
break;
}
System.out.println(str);
}
}
}
字符节点流
- 桥转换流:InputStreamReader/OutputStreamWriter
可将字节流转换为字符流
可设置字符的编码方式
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
public class TestConvertStream {
public static void main(String[] args) throws Exception {
//OutputStream os = new FileOutputStream("convert.txt");//字节输出流
//编码
//OutputStreamWriter osw = new OutputStreamWriter(os,"UTF-8");//指定输出的数据编码格式
//PrintWriter pw = new PrintWriter(osw);
PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream("convert.txt"),"UTF-8") );
pw.println("床前明月光");
pw.println("疑似地上霜");
pw.println("举头望明月");
pw.println("低头思故乡");
pw.flush();
InputStream is = new FileInputStream("convert.txt");
//解码
InputStreamReader isr = new InputStreamReader(is,"UTF-8");
BufferedReader br = new BufferedReader(isr);
while(true) {
String str = br.readLine();
if(str == null) {
break;
}
System.out.println(str);
}
// char[] chars = new char[5];
// isr.read(chars);
// for(int i = 0 ;i<chars.length;i++) {
// System.out.print(chars);
// }
// System.out.println();
}
}
使用步骤
- 创建节点流
- [创建过滤流 设置字符编码集]
- 封装过滤流
- 读写数据
- 关闭流