JAVA进阶版:IO
程序员文章站
2022-05-04 09:55:41
...
文章目录
IO流的种类图:
1. File
1.1 FileInputStream(文件字节输入流)
:从硬盘中输入到内存中
(1)读取字节时,超过的字节都输出-1
package javase.jingjie.IO;
/**
* java.io.InputStream;
* java.io.FileInputStream;文件字节输入流
* 按照字节方式读取文件
* */
import java.io.*;
public class FileInputStreamTest01 {
public static void main(String[] args) {
FileInputStream fis=null;
try {
//1.要读取文件,先与这个文件创建一个“输入流”
//相对路径(所有的相对都是基于根目录/项目javase.jingjie)
String filePath="src/javase/jingjie/IO/text.txt";//相对路径(相对的是根目录/项目javase.jingjie)
//绝对路径:加上盘符E等
//String filePath="E:\\java\\java chengxu\\java duixiang\\eclipse chengxu02\\src\\javase\\jingjie\\IO\\text.txt";
//String filePath="E:/java/java chengxu/java duixiang/eclipse chengxu02/src/javase/jingjie/IO/text.txt";
fis= new FileInputStream(filePath);
//2.开始读,
for(int n=0;n<8;n++) {
int i=fis.read();
System.out.println(i);//以字节的方式读取,如果已经读取到文件的末尾,没有值时,则读取-1
}
}catch(FileNotFoundException e) {
e.printStackTrace();
}catch(Exception e) {
e.printStackTrace();
}
finally {
//为了保证流一定会释放,所以在finally语句块中执行
if(fis!=null) {
try {
fis.close();
}catch(Exception e) {
e.printStackTrace();//打印异常的语句,常出现在catch语句块中
}
}
}
}
}
下面是text.txt
abcedf
结果:97
98
99
101
100
102
-1
-1
(2)以text.txt为读取
package javase.jingjie.IO;
import java.io.*;
public class FileInputStreamTest02 {
public static void main(String[] args) throws Exception {
// 1.创建流
FileInputStream fis=new FileInputStream("src/javase/jingjie/IO/text.txt");
//2.开始读
int temp=0;
while((temp=fis.read())!=-1) {
System.out.println(temp);
}
//关闭
fis.close();
}
}
abcedf
结果:97
98
99
101
100
102
(3) read读取字节
package javase.jingjie.IO;
/**
* int read(byte [] bytes)
* 读取之前在内存中准备一个byte数组,每次读取多个字节存储到byte数组中
* 一次读取多个字节,不是单个字节,效率变高了
* */
import java.io.*;
public class FileInputStreamTest03 {
public static void main(String[] args) throws Exception{
//1.创建输入流
FileInputStream fis= new FileInputStream("src/javase/jingjie/IO/jh.txt");
//2.开始读,准备一个byte数组
byte [] bytes = new byte[3];//每一次最多读取3个字节
//int read(byte[] bytes);该方法返回的it类型的值代表的是,读取了多少个字节
int i1=fis.read(bytes);//3个字节
//将byte数组转换成字符串
System.out.println(new String(bytes));//abc
int i2=fis.read(bytes);//3个字节
System.out.println(new String(bytes));//def
int i3=fis.read(bytes);//2个字节
//System.out.println(new String(bytes));//ghf
//真正的读取是2个字节 gh
System.out.println(new String(bytes,0,i3));//gh 0开始,i3代表长度
int i4=fis.read(bytes);//-1,已经到文件的末尾,返回-1
System.out.println(i1);
System.out.println(i2);
System.out.println(i3);
System.out.println(i4);
//关闭
fis.close();
}
}
(4)new String(bytes,0,temp)数据转换成字符串输出
package javase.jingjie.IO;
//循环读取
import java.io.*;
public class FileInputStreamTest04 {
public static void main(String[] args) throws Exception{
FileInputStream fis = new FileInputStream("src/javase/jingjie/IO/FileInputStreamTest04.java");
//循环读取
byte[] bytes= new byte[1024];//每次读取1KB
while(true) {
int temp=fis.read(bytes);
if(temp==-1)break;
//将byte数组中有效的数据转换成字符串
System.out.println(new String(bytes,0,temp));
}
//升级循环
int temp=0;
while((temp=fis.read(bytes))!=-1) {
System.out.println(new String(bytes,0,temp));
}
fis.close();
}
}
(5)fis.available() 读取剩余字节数 / fis.skip() 跳过字节数
package javase.jingjie.IO;
import java.io.*;
public class FileInputStreamTest05 {
public static void main(String[] args) throws Exception{
//1.创建流
FileInputStream fis=new FileInputStream("src/javase/jingjie/IO/text.txt");
System.out.println(fis.available());//6, 返回6个字节
System.out.println(fis.read());//97
//int available();//返回流中剩余的估计字节数
System.out.println(fis.available());//5 读取一个字节97,还剩5个
//跳过2个字节
fis.skip(2);
System.out.println(fis.read());//101, abcedf读取一个,跳过2个,读到e为101
fis.close();
}
}
1.2 FileOutputStream(文件字节输出流)
:从内存输出到硬盘中
package javase.jingjie.IO;
/**
* java.io.OutputStream;
* java.io.FileOutputStream;文件字节输出流
* 将计算机内存中的数据写入硬盘文件中
* */
import java.io.*;
public class FileOutputStreamTest01 {
public static void main(String[] args) throws Exception{
//1.创建文件字节输出流,谨慎使用,会将源文件内容覆盖
//FileOutputStream fos =new FileOutputStream("src/javase/jingjie/IO/temp02.txt");
//以追加方式append写入
FileOutputStream fos =new FileOutputStream("src/javase/jingjie/IO/temp02.txt",true);
//2.开始写
String msg="HelloWorld!中国人";
//将String转换成byte数组
byte[] bytes=msg.getBytes();
//将byte数组中的全部数据写入
fos.write(bytes);//HelloWorld!中国人
//将byte数组中的部分数据写入
fos.write(bytes,0,3);//Hel 从0位置开始,读3个字节
//推荐最后的时候为了保证数据完全写入硬盘,所以要刷新
fos.flush();//强制写入
//关闭流
fos.close();
}
}
运行多次的结果:
HelloWorld!HelHelloWorld!HelHelloWorld!HelHelloWorld!HelHelloWorld!HelHelloWorld!HelHelloWorld!HelHelloWorld!HelHelloWorld!HelHelloWorld!HelHelloWorld!HelHelloWorld!HelHelloWorld!HelHelloWorld!HelHelloWorld!HelHelloWorld!HelHelloWorld!HelHelloWorld!HelHelloWorld!HelHelloWorld!HelHelloWorld!HelHelloWorld!中国人Hel
1.3 FileReader(文件字符输入流)
package javase.jingjie.IO;
/**
* java.io.Reader;
* java.io.InputStreamReader;转换流(字节输入流-->字符输入流)
* java.io.FileReader;文件字符输入流
* */
import java.io.*;
public class FileReaderTest01 {
public static void main(String[] args) {
// 创建文件字符输入流
FileReader fr =null;
try {
fr= new FileReader("src/javase/jingjie/IO/FileReaderTest01.java");
//开始读
char [] chars=new char[512];//1KB是1024个字节,1个字符占2个字节,所以为512个字符
int temp=0;
while((temp=fr.read(chars))!=-1) {
//将char数组有效部分转换成字符串
System.out.println(new String(chars,0,temp));
}
}catch(Exception e) {
e.printStackTrace();
}finally {
if(fr!=null) {
try {fr.close();
}catch(Exception e) {
e.printStackTrace();
}
}
}
}
}
1.4 FileWriter(文件字符输出流)
package javase.jingjie.IO;
/**
* java.io.Writer;
* java.io.OutputStreamWriter;转换流(字节输出流-->字符输出流)
* java.io.FileWriter;文件字符输出流
* */
import java.io.*;
public class FileWriterTest01 {
public static void main(String[] args) throws Exception{
// 创建文件字符输出流
//FileWriter fw= new FileWrite("src/javase/jingjie/IO/temp03.txt");//覆盖
FileWriter fw= new FileWriter("src/javase/jingjie/IO/temp03.txt",true);//追加
//开始写
fw.write("我爱我的祖国!");
//将char数组的一部分写入
char[] chars= {'我','是','中','国','人','!','*','#'};
fw.write(chars,0,5);
//刷新
fw.flush();
//关闭
fw.close();
}
}
结果:
我爱我的祖国!我是中国人
2. Buffered
- 1.字节
BufferedInputStream;
BufferedOutputStream; - 2.字符
BufferedReader;//带有缓冲区的字符输入流
BufferedWriter;//带有缓冲区的字符输出流 - 3.Buffered里面的循环while((temp=br.readLine())!=null)为null,不再是为-1;为readLine()是一行一行的读,不再是read(),一个个读。
2.1 BufferedReader
(1)带有缓冲区的字符输入流
package javase.jingjie.IO;
import java.io.*;
public class BufferedReaderTest01 {
public static void main(String[] args) throws Exception{
// 创建带有缓冲区的字符输入流
//FileReader fr= new FileReader("src/javase/jingjie/IO/BufferedReaderTest01.java");
//BufferedReader br= new BufferedReader(fr);
//根据流出现的位置,流又可以分为:包装流或者处理流和节点流
//FileReader fr是节点流。BufferedReader br包装流
BufferedReader br= new BufferedReader(new FileReader("src/javase/jingjie/IO/BufferedReaderTest01.java"));
//开始读,readLine()是一行一行的读
String temp=null;
while((temp=br.readLine())!=null) {
System.out.println(temp);
}
//关闭
//注意:关闭的时候只需要关闭最外层的包装流
br.close();
}
}
(2)字节流转换成字符流:InputStreamReader
package javase.jingjie.IO;
import java.io.*;
/**
* BufferedReader
* 利用转换流InputStreamReader
* */
public class BufferedReaderTest02 {
public static void main(String[] args) throws Exception{
/*
// 创建带有缓冲区的字符输入流
FileInputStream fis=new FileInputStream("src/javase/jingjie/IO/BufferedReaderTest02.java");//文件字节输入流
//转换流(将字节流转换成字符流)
InputStreamReader isr =new InputStreamReader(fis);
BufferedReader br=new BufferedReader(isr);//isr是字符流
*/
//简化
BufferedReader br=new BufferedReader(new InputStreamReader(new FileInputStream("src/javase/jingjie/IO/BufferedReaderTest02.java")));
//开始读
String temp=null;
while((temp=br.readLine())!=null) {
System.out.println(temp);
}
//关闭
//注意:关闭的时候只需要关闭最外层的包装流
br.close();
}
}
(3)接收用户键盘输入:System.in
package javase.jingjie.IO;
/**
* 接收用户键盘输入
* */
import java.io.*;
import java.util.*;
public class BufferedReaderTest03 {
public static void main(String[] args) throws Exception{
/*
//以前的方式
Scanner s= new Scanner(System.in);//System.in是一个标准的输入流(Reader抽象),默认接收键盘的输入
String str=s.next();
System.out.println("您输入了: "+str);
*/
//使用BufferedReader用来接收用户的输入,空格和空格之后的字符串也能输出
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
//接收输入(每一次都接收一行)
String str=br.readLine();
System.out.println("您输入了:"+str);
br.close();
}
}
2.2 BufferedWriter
带有缓冲区的字符输出流
package javase.jingjie.IO;
/**
* BufferedWriter
* */
import java.io.*;
public class BufferedWriterTest01 {
public static void main(String[] args) throws Exception{
//BufferedWriter bw= new BufferedWriter(new FileWriter("src/javase/jingjie/IO/Temp04.txt"));
//OutputStreamWriter--> 字节转换字符; 通过追加,获取多个结果
BufferedWriter bw= new BufferedWriter(new OutputStreamWriter(new FileOutputStream("src/javase/jingjie/IO/Temp04.txt",true)));
bw.write("大家好!我来自中国");
//写入一个行分隔符
bw.newLine();
bw.write("我来自美国");
//输出流 才有刷新
bw.flush();
//关闭
bw.close();
}
}
结果(运行多次的结果):
大家好!我来自中国
我来自美国大家好!我来自中国
我来自美国大家好!我来自中国
我来自美国大家好!我来自中国
我来自美国大家好!我来自中国
我来自美国大家好!我来自中国
我来自美国大家好!我来自中国
我来自美国
2.3 装饰者
package javase.jingjie.IO;
public class 装饰者 {
public static void main(String[] args) {
/*1.创建被装饰者
FileReader1 fr= new FileReader1();
2.创建装饰者
BufferedReader1 br= new BufferedReader1(fr);
*/
BufferedReader1 br= new BufferedReader1(new FileReader1());
//3.通过执行装饰者中的方法间接去执行被装饰者中的方法
br.close();
}
}
abstract class Reader1{
public abstract void close();
}
/**
* 使用BufferedReader1对FileReader1中的close方法进行扩展
* 1.装饰者模式要求:装饰者中含有被装饰者的引用。
* 2.装饰者模式要求:装饰者和被装饰者应该实现同一个类型
* */
class BufferedReader1 extends Reader1{//BufferedReader1装饰者
//关联关系
Reader1 reader;//FileReader1就是被装饰者,也继承Reader1中所有属性
//构造器
BufferedReader1(Reader1 reader){
this.reader=reader;
}
//对FileReader1中的close方法进行扩展
public void close() {
//扩展
System.out.println("扩展代码1");
reader.close();
System.out.println("扩展代码2");
}
}
/**
* 思考:
* 对FileReader1中的close方法进行扩展:
* 1.继承(不推荐,代码耦合度太高,不利于项目扩展)
* 2.装饰者模式。
* */
class FileReader1 extends Reader1{
public void close() {
System.out.println("FileReader1 closed!");
}
}
3. Data
3.1 DataInputStream(数据字节输入流)
package javase.jingjie.IO;
/**
* DataInputStream
* */
import java.io.*;
public class DataInputStreamTest01 {
public static void main(String[] args) throws Exception{
// 创建数据字节输入流
DataInputStream dis=new DataInputStream(new FileInputStream("src/javase/jingjie/IO/temp05.txt"));
//读。注意:要使用该流读取数据,必须提前知道该文件中数据的存储格式,顺序。
//读的顺序必须和写入的顺序(dos.writeByte.......等)相同。
byte b= dis.readByte();
short s= dis.readShort();
int i=dis.readInt();
long l=dis.readLong();
float f= dis.readFloat();
double d=dis.readDouble();
boolean o=dis.readBoolean();
char c=dis.readChar();
//将temp05.txt的内容输出到控制台
System.out.println(b);
System.out.println(s);
System.out.println(i);
System.out.println(l);
System.out.println(f);
System.out.println(d);
System.out.println(o);
System.out.println(c);
}
}
结果:10
11
20
19
123.9
234.5
true
s
3.2 DataOutputStream(数据字节输出流)
package javase.jingjie.IO;
/**
* java.io.DataOutputStream;数据字节输出流
*
* 可以将内存中的“int i=10;”写入到硬盘文件中,写进去的不是字符串
* 写进去的是二进制数据,带类型
* */
import java.io.*;
public class DataOutputStreamTest01 {
public static void main(String[] args) throws Exception{
// 创建数据字节输出流
DataOutputStream dos = new DataOutputStream(new FileOutputStream("src/javase/jingjie/IO/temp05.txt"));
//准备数据
byte b= 10;
short s= 11;
int i=20;
long l=19L;
float f= 123.9f;
double d=234.5;
boolean o=true;
char c='s';
//写
dos.writeByte(b);
dos.writeShort(s);
dos.writeInt(i);
dos.writeLong(l);
dos.writeFloat(f);
dos.writeDouble(d);
dos.writeBoolean(o);
dos.writeChar(c);
dos.flush();
dos.close();
}
}
4. Object
4.1 反序列化ObjectInputStream
package javase.jingjie.IO;
/**
* 反序列化
* 结果:User[name=胡歌,霍建华,袁弘,null] 加过transien后 age为null
* */
import java.io.*;
public class ObjectInputStreamTest01 {
public static void main(String[] args) throws Exception{
//1.创建反序列化流
ObjectInputStream ois=new ObjectInputStream(new FileInputStream("src/javase/jingjie/IO/temp06.txt"));
//2.反序列化,readObject()是Object类型
Object o=ois.readObject();//User[name=胡歌,霍建华,袁弘]
//输出到控制台
System.out.println(o);
ois.close();
}
}
4.2 序列化ObjectOutputStream
注意:
1.Serializable接口:该接口是一个“可序列化的”,起到标识作用
2. transien:如果不想让该属性参加序列化,需要使用transient关键词修饰, transient String age;//加过transien后,序列化值为null,空
package javase.jingjie.IO;
/**
* java.io.ObjectOutputStream;序列化java对象到硬盘(serial)
* java.io.ObjectInputStream;将硬盘中的数据“反序列化”到jvm内存(deserial)
*
* Compile 编译(java-->class)
* DeCompile 反编译(class-->java)
* */
import java.io.Serializable;//该接口是一个“可序列化的”,只是一个标识接口,接口中没有任何方法
import java.io.*;
public class ObjectOutputStreamTest01 {
public static void main(String[] args) throws Exception{
//1.创建java对象
User u1=new User("胡歌,霍建华,袁弘","35岁");
//2.创建输出流(序列化流) (JVM中的java对象状态保存到硬盘)
ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("src/javase/jingjie/IO/temp06.txt"));
//3.写
oos.writeObject(u1);//u1必须进行过序列化,否则编不出来
oos.flush();
oos.close();
}
}
class User implements Serializable{//该接口是一个“可序列化的”,起到标识作用
String name;
//如果不想让该属性参加序列化,需要使用transient关键词修饰
transient String age;//加过transien后,序列化值为null,空
User(String name,String age){
this.name=name;
this.age=age;
}
public String toString() {
return "User[name="+name+","+age+"]";
}
}
5. Print
- java.io.PrintStream;标准的输出流,默认打印到控制台,以字节方式
- java.io.PrintWriter;以字符方式
5.1 PrintStream(标准的输出流)
package javase.jingjie.IO;
import java.io.*;
import java.text.*;
import java.util.*;
public class PrintStreamTest01 {
public static void main(String[] args) throws Exception{
//默认是输出到控制台的
System.out.println("Hello,World");//Hello,World
//上面的是下面的简写,一般用上面的
PrintStream ps= System.out;
ps.println("JAVA Is Good!!!");//JAVA Is Good!!!
//可以改变输出方向,不再是输出到控制台,而是文本
//此处出现异常
System.setOut(new PrintStream(new FileOutputStream("src/javase/jingjie/IO/log.txt")));
System.out.println("绝地反击");
//通常我们使用上面的这种方式记录日志
//需求:记录日志,m1方法开始执行的时间和结束的时间,记录到log文件中
SimpleDateFormat sdf= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:sss");//日期格式
System.out.println("m1方法开始执行:"+sdf.format(new Date()));//new Date()现在时间 format()日期-->字符串
m1();
System.out.println("m1方法结束执行:"+sdf.format(new Date()));
}
public static void m1() {
System.out.println("m1方法正在执行");
}
}
结果:
绝地反击
m1方法开始执行:2019-10-25 15:55:14:014
m1方法正在执行
m1方法结束执行:2019-10-25 15:55:14:014
6.Copy复制
(1) 输入流和输出流同时用:复制粘贴
package javase.jingjie.IO;
/**
* 关于文件复制粘贴
* */
import java.io.*;
public class copy {
public static void main(String[] args) throws Exception{
//创建输入流
FileInputStream fis= new FileInputStream("src/javase/jingjie/IO/text.txt");
//创建输出流
FileOutputStream fos=new FileOutputStream("e:/text.txt");//把该文件复制粘贴到E盘
//一边读,一边写
byte [] bytes= new byte[1024];//1kb
int temp=0;
while((temp=fis.read(bytes))!=-1) {
//将byte数组中的内容直接写入
fos.write(bytes,0,temp);
}
//刷新
fos.flush();
//关闭
fis.read();
fis.close();
}
}
(2) 复制纯文本文件
package javase.jingjie.IO;
import java.io.*;
/**
* 文件复制
* 只能复制纯文本文件
* */
public class copy02 {
public static void main(String[] args) throws Exception{
// 创建字符输入流、输出流
FileReader fr=new FileReader("src/javase/jingjie/IO/copy02.java");
FileWriter fw=new FileWriter("e:/copy02.java");//复制到E盘
char[] chars=new char[512];
int temp=0;
while((temp=fr.read(chars))!=-1) {
fw.write(chars,0,temp);
}
fw.flush();
fr.close();
fw.close();
}
}
(3) BufferedReader和BufferedWriter完成复制
package javase.jingjie.IO;
/**
* 使用BufferedReader和BufferedWriter完成复制
* */
import java.io.*;
public class copy03 {
public static void main(String[] args) throws Exception{
//创建流
BufferedReader br=new BufferedReader(new FileReader("src/javase/jingjie/IO/copy03.java"));
BufferedWriter bw=new BufferedWriter(new FileWriter("e:/copy03.java"));
String temp=null;
while((temp=br.readLine())!=null) {
bw.write(temp);
bw.newLine();//每次都保证一行后换行
}
bw.flush();
br.close();
bw.close();
}
}