一.IO流 概述
1. 定义
从【程序】到【文件/数据库/网络】两端,数据的输入和输出
二.文件IO
操作步骤:
- 创建文件(接收器)
- (选择)IO流(抽象类与实现类)
- 选择I/O操作(读/写)
- 关闭流
1. 创建文件(接收器)
java.io.File
- 首先:创建文件对象,才能通过对象使用相关功能
- 创建文件
File file=new File("D:\\IOTest.txt");
file.createNewFile();
file.renameTo(new File("D:\\IOTest2.txt"));
- 创建文件夹
File f= new File("d://a//b//c");
f.mkdir();
创建此抽象路径名指定的目录。例如如果上述文件中已有d://a//b文件夹,则在此基础上,再建一个子文件夹c;如果没有d://a//b,则不报错但创建失败
f.mkdirs();
创建此抽象路径名指定的目录,包括所有必需但不存在的父目录。不管d://a//b是否存在,都会创建d://a//b//c文件夹
注:File 类的实例是不可变的;也就是说,一旦创建,File 对象表示的抽象路径名将永不改变
文件默认false自动覆盖,new File(“d://c.txt”),true)进行续写
- 代码示例
package java_20191208;
import java.io.File;
import java.io.IOException;
public class TestFile {
public static void main(String[] args) throws IOException {
//构造方法,在改路径进行声明,此时在D盘并未真正创建
File file=new File("D:\\IOTest.txt");
// File file=new File("d://IOTest.txt"); 这样也可以
// File file=new File("d:"+File.separator+"c.txt");
if(!file.exists()) {
// 通过此对象方法,在系统创建该文件
file.createNewFile();
System.out.println("创建成功");
}
else {
// 删除将该文件对象:"D:\\IOTest.txt"-删除
// file.delete();
// 重命名已存在文件夹
file.renameTo(new File("D:\\IOTest2.txt"));
System.out.println("该文件已存在,新创建了D:\\IOTest2.txt");
}
File f= new File("d://a//b//c");
f.mkdirs();
}
}
2.(选择)IO流—抽象类
- IO流分类
(1)按方向分 :输入流,输出流
Input和Read
Output和Write
(2)按传输单位分 : 字节流 ,字符流
Input、Output
Write、Read
(3)按功能分: 节点流, 处理流
Input、Output
Buffer、Change、Data、Object、Print - JDK提供的4大抽象流
(抽象类不能实例化,他们底层还需实现类构造对象)
(1)OutputStream/InputStream
此抽象类是表示输入/输出字节流的所有类的超类。输入/输出流接受输入/输出字节并将这些字节发送到某个接收器。
(2)Writer/Reader
写入/读出字符流的抽象类。Writer子类必须实现的方法仅有 write(char[], int, int)、flush() 和 close()。但是,多数子类将重写此处定义的一些方法,以提供更高的效率和/或其他功能。
read()&write()
write(1):
// 实例代码:向文件夹中写26个字母
// for(int i=97;i<123;i++) {
// 指定要写入字符的 int值
// os.write(i);
// }
write(2):
// 将事先声明好的byte数组写入构造os对象的File文件
// byte[] b= {1,2,3};
// os.write(b);
read(1):无参的read方法返回值为类型,表示【从输入流读取一个数据字节,返回int类型变量】
// 实例代码:向系统写回26个字母
// for(int j=0;j<f.length();j++){
// int i=is.read();
// System.out.println((char)i+" ");
// }
read(2):int read(byte[] bs)方法返回值表示【读入缓冲区的字节总数,如到达文件末尾则返回 -1】,参数表示【存储读取数据的缓冲区】
// byte[] b=new byte[5];
// int i=is.read(b);
// System.out.println((char)b[0]); //输出第一个:a!!
// System.out.println(i); //输出数组大小:5
3.(选择)IO流—实现类
1. 文件字节流:FileOutputStream&FileInputStream
package java_20191208;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class IOputStream {
public static void main(String[] args) throws IOException {
//1.创建文件
File f=new File("D://a.txt");
//2.选择IO流
// OutputStream os=new OutputStream(f); Error:抽象类不能直接创建对象
// 注:如果文件不存在:向文件写内容时,系统会自动创建;但读文件时,系统会报异常
OutputStream os=null;
InputStream is=null;
try {
//3.创建输出流实现类对象,并进行写操作
os=new FileOutputStream(f);
//向文件夹中写26个字母
for(int i=97;i<123;i++) {
os.write(i);
}
}catch (IOException e) {
e.printStackTrace();
}finally {
//4.关闭输出流
os.close();
}
try {
//3.创建输入流实现类对象,并进行写操作
is=new FileInputStream(f);
//向系统写回26个字母
for(int j=0;j<f.length();j++){
//read():如果已达文件末尾,则返回-1,可用于循环判断条件
int i=is.read();
System.out.println((char)i+" ");
}
}catch (IOException e) {
e.printStackTrace();
}finally {
//4.关闭输入流
is.close();
}
}
}
2. 文件字符流:FileWriter&FileReader
package java_20191208;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.Math;
public class IOFileWR {
public static void main(String[] args) throws IOException {
File f=new File("D://IOFileWR.txt");
FileWriter fw=new FileWriter(f);
for(int i=0;i<5;i++) {
fw.write((int) (Math.random()*50+10));
//刷新字符流缓冲,所有字符流类写入后必须调用此方法
fw.flush();
}
FileReader fr=new FileReader(f);
int n=0;
while((n=fr.read())!=-1) {
System.out.println(n);
}
fw.close();
fr.close();
}
//控制台输出五个10~60的随机数
}
3.缓冲流: BufferedWriter&BufferedReader
package java_20191208;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class IOBuffer {
public static void main(String[] args) throws IOException {
//Buffered流:面向行的输入输出
//将文本写入字符输出流,缓冲区暂存字符/字节,达到一定量再进行传输
//缓冲区大小可以指定,但一般默认的就足够使用
FileWriter f=null;
BufferedWriter bw=null;
FileReader r=null;
BufferedReader br=null;
try {
f=new FileWriter("D://IOBuffer.txt");
bw=new BufferedWriter(f);
//跨平台换行
bw.newLine();
bw.write("从明天起,做一个幸福的人");
bw.newLine();
bw.write("喂马,劈柴,周游世界");
bw.newLine();
bw.write("从明天起,关心粮食和蔬菜");
bw.newLine();
bw.write("我有一所房子,面朝大海,春暖花开");
//刷新字符流缓冲,所有字符流类写入后必须调用此方法
bw.flush();
} catch (Exception e) {
e.printStackTrace();
}
finally {
bw.close();
}
try {
r=new FileReader("D://IOBuffer.txt");
br=new BufferedReader(r);
while(true){
String s;
s=br.readLine();
if(s==null) break;
System.out.println(s);
}
} catch (IOException e) {
e.printStackTrace();
}
finally {
br.close();
}
}
}
4. 数据流:DataOutputStream&DataInputStream
package java_20191208;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class IODate {
public static void main(String[] args) throws IOException {
// Date流:输入,输出 字节流
// 特点: 能够读写——java的基本数据类型
DataOutputStream dop=null;
DataInputStream dip=null;
try {
//装饰模式声明流对象
dop=new DataOutputStream(new FileOutputStream(new File("D://IODate.txt"),true)); //续写
dop.writeInt(1234);
dop.flush();
} catch (IOException e) {
e.printStackTrace();
}finally {
dop.close();
}
try {
dip=new DataInputStream(new FileInputStream(new File("D://IODate.txt")));
int i=dip.readInt();
System.out.println(i);
} catch (IOException e) {
e.printStackTrace();
}finally {
dip.close();
}
}
}
5. 对象流:ObjectOutputStream&ObjectInputStream
package java_20191208;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class IOObject {
public static void main(String[] args) {
// Object流:输入输出对象
// 对象必须被序列化
Student stu =new Student();
stu.name="jim";
stu.age=10;
stu.num=101;
ObjectOutputStream os =null;
// 装饰模式
try {
os =new ObjectOutputStream(new FileOutputStream(new File("d://c.txt")));
os.writeObject(stu);
os.flush();
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
//Serializable接口:将类实例对象序列化
class Student implements Serializable{
String name;
int age;
// 不想写在文件里面的属性:transient
transient int num;
}
6. 转换流:OutputStreamWriter&InputStreamReader
package java_20191208;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
public class IOChange {
public static void main(String[] args) {
// OutputStreamWriter:转换流
// 提供字符到字节的转换
// 可以改变编码
// 确定自己电脑编码
System.out.println(System.getProperty("file.encoding"));
String str="2020年马上到来";
System.out.println(str);
// 改变编码
byte[] b=str.getBytes();
try {
String str1=new String(b,"Big5");
System.out.println(str1);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
changeIO();
}
public static void changeIO(){
OutputStreamWriter os =null;
try {
os =new OutputStreamWriter(new FileOutputStream(new File("d://c.txt"),true));
os.write("我爱你中国");
os.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
7. 单向输出流:PrintStream
package java_20191208;
import java.io.FileNotFoundException;
import java.io.PrintStream;
public class IOPrint {
public static void main(String[] args) {
PrintStream ps = null;
try {
System.out.println("1.输出到控制台");
ps = new PrintStream("D://IOPrint");
ps.print("2.输出到文件");
System.out.println("3.输出到控制台");
// 系统重定向方法setOut,重新分配默认输出位置
System.setOut(ps);
System.out.println("4.输出到文件");
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
ps.close();
}
}
}
4.关闭流
三.代码实例
1.用指定的编码格式,将文章输入文件夹
package java_20191208_homeWork;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class Poem_BufferedWriter {
public static void main(String[] args) throws IOException {
//创建面向行输出的IO流对象
BufferedWriter bw=new BufferedWriter(new FileWriter("d://test.txt"));
//先输出原文件编码格式
System.out.println(System.getProperty("file.encoding"));
//用字符串存储一行数据
String s1= "床前明月光";
//将字符串转换为字节,存入数组
byte[] b1=s1.getBytes();
//创建字符串对象,并使用GBK编码方式
String str1=new String(b1,"GBK");
String s2= "疑是地上霜";
byte[] b2=s2.getBytes();
String str2=new String(b2,"GBK");
String s3= "举头望明月";
byte[] b3=s3.getBytes();
String str3=new String(b3,"GBK");
String s4= "低头思故乡";
byte[] b4=s4.getBytes();
String str4=new String(b4,"GBK");
//将编码方式规定好的字符串一行一行写入
bw.write(str1);
//跨平台换行
bw.newLine();
bw.write(str2);
bw.newLine();
bw.write(str3);
bw.newLine();
bw.write(str4);
bw.newLine();
//刷新流,关闭流
bw.flush();
bw.close();
}
}
2.将上述输入的文章,反向输出出来
package java_20191208_homeWork;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.Stack;
public class Poem_ChangeInputStream {
public static void main(String[] args) throws IOException {
//创建对象行的字符流对象,可实现字符与字节的转换,以及行IO
BufferedReader br=null;
BufferedWriter bw=null;
//反向输出,我们使用栈进行存储,先入后出
Stack<String> stack=null;
try {
br=new BufferedReader(new InputStreamReader(new FileInputStream(new File("d://test.txt"))));
bw=new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File("d://test2.txt"))));
stack=new Stack<String>();
//此处我们刚开始使用的是while(br.readLint!=null)
//此方法结果正好读一半的数据,因为在判断时就读取了一行数据,但并未写入文件
//采用这种循环方式,我们就避免了这种情况
while(true) {
String s=br.readLine();
if(s==null) break;
//将读取到的数据行,用一个字符串对象存储,并压入栈
stack.push(s);
}
//刷新缓冲流
bw.flush();
//此处我们在控制台检验一下栈是否读入了数据
System.out.println(stack);
//循环:如果堆栈非空
while(!stack.empty()) {
//取出堆栈数据,每次一个,写进新的文件
bw.write(stack.pop());
//跨平台换行
bw.newLine();
}
} catch (IOException e) {
e.printStackTrace();
}finally {
//关闭流
br.close();
bw.close();
}
}
}
3.利用字节流,输入文件语句,并输出出来
package java_20191208_homeWork;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileIOS {
public static void main(String[] args) throws IOException {
File f=null;
FileOutputStream fos=null;
FileInputStream fis=null;
//创建字节流,字节对应ASCII码字母为:Hello World
byte[] b= {72,101,108,108,111,32,87,111,114,108,100};
try {
//新建文件test3
f=new File("d://test3.txt");
//如果文件不存在,则创建文件夹
if(!f.exists()) {
f.createNewFile();
fos=new FileOutputStream((f));
System.out.println("文件创建成功");
}
//如果文件存在,则对原文件续写
else {
fos=new FileOutputStream((f),true);
System.out.println("文件已经存在,继续续写");
}
//将字节数组写入文件
fos.write(b);
} catch (Exception e) {
e.getStackTrace();
} finally {
fos.close();
}
try {
fis=new FileInputStream((f));
//读取文件中字节总长度的数据,即全部数据
for(int j=0;j<b.length;j++){
//将数据读入,并存储为int变量,然后转换为char字符串,输出出来
int i=fis.read();
System.out.print((char)i+" ");
}
} catch (Exception e) {
e.getStackTrace();
} finally {
fis.close();
}
}
}