目录
下面是一些需要掌握的IO知识,通过这些可以对IO流有一个基本的了解
/**
* IO流
* 字节输出流 字节输入流 (视频)
* OutputStream InputStream 抽象类
* FileOutputStream FileInputStream 基本流
* BufferedOutputStream BufferedInputStream 缓冲流
* ObjectOutputStream ObjectInputStream 对象字节输出,输入流
* PrintStream 打印流
* 字符输入流 字符输出流 (文本)
* Reader Writer 抽象类
* FileReader FileWriter 基本流
* BufferedReader BufferedWriter 缓冲流
* InputStreamReader OutputStreamWriter 转换流
* PrintWriter 打印流
* 都是抽象类
*/
OutputStream,InputStream,Reader,Writer都是抽象类需要使用它们的实现类来创建对象
也就是需要FileOutputStream,FileInputStream
字节流适合做一切文件数据的拷贝 因为任何文件的底层都是字节,拷贝是一字不漏进行转移字节,只要文件格式,编码一致没有任何问题。而字符流适合做文本操作
基本流
一:我们首先来介绍字节流中的字节输入流FileInputStream 的一些基本使用
/**
* 进行文字的编码与解码
*/
public class CharSet {
public static void main(String[] args) throws UnsupportedEncodingException {
String date = "清明节又称踏青节、行清节、三月节、祭祖节等,是中华民族传统的重大春祭节日," +
"属于慎终追远、礼敬祖先、弘扬孝道的一种文化传统节日。清明节既是一个扫墓祭祖的肃穆日子," +
"也是人们亲近自然、踏青游玩、享受春天乐趣的节日。清明节在传承发展中杂糅了多地多种民俗为一体," +
"具有极为丰富的文化内涵。扫墓祭祖都是清明节期间最重要的节日内容,此外还有踏青、荡秋千、放风筝" +
"、植树、插柳等习俗。";
byte[] bytes = date.getBytes();//以当前代码默认字符集进行编码(UTF-8)
System.out.println(bytes.length);
System.out.println(Arrays.toString(bytes));
byte[] bytes1 = date.getBytes("GBK");//指定编码(GBK)
System.out.println(Arrays.toString(bytes1));
//解码 编码前与编码后的字符集必须一致
String s=new String(bytes);
System.out.println(s);
String s1 = new String(bytes1, "GBK");//指定解码(GBK)
System.out.println(s1);
}
}
public class IODemo {
public static void main(String[] args) throws Exception {
System.out.println("==============OutputStream===================");
InputStream is=new FileInputStream("D:\\resoare\\data.txt");//多态的写法,创建了一个字节输出流对象
//读取一个字节返回
int b=is.read();
System.out.println(b);
int n;
while ((n= is.read())!=-1){
System.out.print((char) n);
}
// 读取字节数组
byte[] bytes=new byte[3];
int len= is.read(bytes);
String rs=new String(bytes);
System.out.println(rs);
//前面的读取流的方法太麻烦下面采用循环来进行
//注意前面已经读取了一段流想要输出完整的数据要把前面读取操作注释调
byte[]bytes2=new byte[3];//每次读三个字节
int len2;//定义一个len,记录每次读取的数据
while ((len2=is.read(bytes2))!=-1){
System.out.print(new String(bytes2,0,len2));
}
// 字节流读取文本容易出现中文乱码问题,
// 下面提供了一些解决方法
byte [] b1 =is.readAllBytes();
System.out.println(new String(b1));
// is.flush();//刷新数据,仍然可以使用is来写数据
is.close();//关闭通道,释放资源,不可以在写数据
}
}
二:字节流中的字节输出流 OutputStream 的一些基本使用
public class IODemo2 {
public static void main(String[] args) throws Exception {
System.out.println("=========================OutputStream===========================");
//创建一个文件字节输出流管道与目标文件连接
File f=new File("D:\\resoare\\data02.txt");
OutputStream is=new FileOutputStream(f);//创建后会清空文件之前的数据
// OutputStream os1=new FileOutputStream(f,true);//不会清空
//写数据进去
//写一个字节出去
is.write('a');
is.write(97);
is.write(98);
is.write('学');//会出现乱码,因为中文字符是三个字节,这里只是读一个
is.write("\r\n".getBytes());//换行
//写一个字节数组出去
byte[] bytes={'a',97,99,'c'};
is.write(bytes);
is.write("\r\n".getBytes());//换行
is.write("初雪春落".getBytes());
is.write("\r\n".getBytes());//换行
//写一个字节数组的一部分
byte[] bytes1={'a',97,99,'c'};
is.write(bytes1,0,2);//从0开始写两个
is.write("\r\n".getBytes());//换行
//
// is.flush();//刷新数据,仍然可以使用os来写数据
is.close();//关闭通道,释放资源,不可以在写数据
}
}
三:字符流中的字符输入流 FileReader 的一些基本使用
先介绍一下编码与解码
计算机中储存信息都是使用二进制,我们平常在电子设备上看到的各种文字,符号都是计算机经过编码后呈现在屏幕上的,我们将字符以某种规则储存到计算机上的过程称为编码。将计算机中储存的数据按照相应的规则展现出来成为解码操作。编码与解码要使用相同的规则来进行否则会出现乱码问题。
常见的编码类型有:Unicode、ASCII、GBK、GB2312、UTF-8。
/**
* 进行文字的编码与解码
*/
public class CharSet {
public static void main(String[] args) throws UnsupportedEncodingException {
String date = "清明节又称踏青节、行清节、三月节、祭祖节等,是中华民族传统的重大春祭节日," +
"属于慎终追远、礼敬祖先、弘扬孝道的一种文化传统节日。清明节既是一个扫墓祭祖的肃穆日子," +
"也是人们亲近自然、踏青游玩、享受春天乐趣的节日。清明节在传承发展中杂糅了多地多种民俗为一体," +
"具有极为丰富的文化内涵。扫墓祭祖都是清明节期间最重要的节日内容,此外还有踏青、荡秋千、放风筝" +
"、植树、插柳等习俗。";
byte[] bytes = date.getBytes();//以当前代码默认字符集进行编码(UTF-8)
System.out.println(bytes.length);
System.out.println(Arrays.toString(bytes));
byte[] bytes1 = date.getBytes("GBK");//指定编码(GBK)
System.out.println(Arrays.toString(bytes1));
//解码 编码前与编码后的字符集必须一致
String s=new String(bytes);
System.out.println(s);
String s1 = new String(bytes1, "GBK");//指定解码(GBK)
System.out.println(s1);
}
}
/**
*字符输入流
*/
public class FileReader {
public static void main(String[] args) throws Exception {
Reader r=new java.io.FileReader("D:\\resoare\\data0202.txt");
//读取一个字符
// int a=r.read();
// System.out.println((char) a);
//使用循环来读取
// int data;
// while ((data=r.read())!=-1){
// System.out.print((char) data);
// }
//使用一个字符数组来读取
char [] chars=new char[1024];
int len;
while ((len=r.read(chars))!=-1){
String s=new String(chars,0,len);//进行解码操作
System.out.print(s);
}
r.close();
}
}
四:字符流中的字符输出流 FileWriter 的一些基本使用
/**
* 字符输出流
*/
public class FileWriter {
public static void main(String[] args) throws Exception {
Writer r=new java.io.FileWriter("D:\\resoare\\dataWriter.txt");
r.write('a');
r.write(97);
r.write("序");
r.write("我爱华夏");
char[]chars={'a',99,'甘'};
r.write(chars);
r.write(chars,0,2);//读取指定字符数组的内容
r.close();
}
}
练习
案例:拷贝文件到指定路径
/**
* 字节流适合做一切文件数据的拷贝
* 因为任何文件的底层都是字节,拷贝是一字不漏进行转移字节,只要文件格式,编码一致没有任何问题
*/
public class IODemo04 {
public static void main(String[] args) {
//在IODemoResource中为了释放资源所进行的代码太过繁琐
//以下是另一种方法
try (//这里只能放资源,资源是指实现了Closeable/AutoCloseable接口的类的对象
//创建输入流
InputStream is=new FileInputStream("D:\\图片\\SearchPictureTool" +
"\\LiveWallpaperCache\\VIDEO\\1428D89BBC25BF63448B165D5C046749" +
"\\碧蓝航线 长门神子的休憩.mp4");
//创建输出流
OutputStream os=new FileOutputStream("D:\\图片\\new.mp4");
) {
//创建一个数组来作为中转站
byte[]bytes=new byte[1024];
int len;//记录每次读取的字节数
while ((len=is.read(bytes))!=-1){
os.write(bytes,0,len);
}
// System.out.println(10/0);
} catch (Exception e) {
e.printStackTrace();
}
}
}
缓冲流
一:缓冲流(缓冲流的性能更高一些)(借用上面的拷贝文件案例来介绍缓冲流,提高性能)(字符缓冲流基本与字节缓冲流的使用方法差不多,都是要把低级流的对象进行包装来提高性能)
public class IOBufferedInOut {
public static void main(String[] args) {
//目标:使用缓冲流来进行文件拷贝
try(
InputStream is=new FileInputStream("D:\\图片\\new.mp4");
//把字节输入流管道包装为高级的缓冲流管道
InputStream bis=new BufferedInputStream(is);
OutputStream os=new FileOutputStream("D:/图片/aa.mp4");
//把字节流输出管道包装为高级的缓冲流管道
OutputStream bos=new BufferedOutputStream(os);
) {
//准备一个字节数组
byte[] bytes=new byte[1024];
int len;
while ((len=bis.read(bytes))!=-1){
bos.write(bytes,0,len);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
转换流
当文件中有中文,数字,英文等,使用字节流显示时中文字符会出现乱码,这时可以使用转换流把字节流转换为字符流来进行显示
转换流:InputStreamReader OutputStreamWriter实现字节流和字符流之间的转换。
public class IOInputStreamReader {
public static void main(String[] args) throws Exception {
//
InputStream is=new FileInputStream("D:\\resoare\\data03.txt");
Reader re=new InputStreamReader(is,"GBK");//字符输入转换流,指定编码
//缓冲流包装
BufferedReader bre=new BufferedReader(re);
Writer we=new BufferedWriter(new FileWriter("D:\\resoare\\data0303.txt"));
String line;
while ((line=bre.readLine())!=null){
System.out.println(line);
we.write(line);
}
bre.close();
we.close();
}
}
对象序列化与反序列化
序列化将程序运行时内存中的对象以字节码的方式保存在磁盘中,或直接通过网络进行传输
反序列化 把字节序列恢复为对象的过程称为对象的反序列化 。
对象被转换成“字节流”后可以存入文件,内存,亦或者是数据库内进行持久化保存。然后通过“反序列化”可以把“字节流”转换成实际的Java对象。
transient修饰的成员变量不参与序列化
如果对象要序列化,就必须实现Serializable序列化接口
public class IOObjectOutputStream {
//学会对象序列化,使用ObjectOutputStream,把内存的对象存入到磁盘文件中
public static void main(String[] args) {
//创建学生对象,
Student s=new Student("小雪","1234123523",18,699);
//对象序列化,使用ObjectOutputStream包装字节输出流管道
try {
FileOutputStream fe=new FileOutputStream("D:/resoare/obj.txt");
ObjectOutputStream os=new ObjectOutputStream(fe);
//调用序列化方法
os.writeObject(s);
System.out.println("序列化完成");
os.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
/**
* 如果对象要序列化,就必须实现Serializable序列化接口
*/
class Student implements Serializable {
public static final long serialVersionUID=1;
private String name;
private transient String studentCode;
private int age;
private double score;
public Student() {
}
public Student(String name, String studentCode, int age, double score) {
this.name = name;
this.studentCode = studentCode;
this.age = age;
this.score = score;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getStudentCode() {
return studentCode;
}
public void setStudentCode(String studentCode) {
this.studentCode = studentCode;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", studentCode='" + studentCode + '\'' +
", age=" + age +
", score=" + score +
'}';
}
}
public class ObjectInputStream {
//对象的反序列化
//transient修饰的成员变量不参与序列化
public static void main(String[] args) throws Exception {
//使用对象输出流来包装字节输出流
java.io.ObjectInputStream is=new java.io.ObjectInputStream(new FileInputStream("D:/resoare/obj.txt"));
Student s=(Student) is.readObject();
System.out.println(s);
}
}
打印流 PrintStream PrintWriter
打印流提供了非常方便的打印功能,可以打印任何的数据类型,例如:小数、整数、字符串等等。
//两种打印流的打印功能是一样的但PrintStream支持写字节 ,而PrintWriter支持写字符
public class IOPrintStream {
//打印流可以更高效,方便的打印数据
public static void main(String[] args) throws FileNotFoundException {
//
// PrintStream ps=new PrintStream(new FileOutputStream("D:\\resoare\\data.txt"));
// PrintStream ps=new PrintStream("D:\\resoare\\data.txt","GBK");
PrintStream ps=new PrintStream("D:\\resoare\\data.txt");
ps.println(99);
ps.println(97);
ps.println("我爱中国");
ps.println("我爱中华");
ps.println('陈');
ps.println(true);
System.out.println("庄生晓梦迷蝴蝶");
System.out.println("望帝春心托杜鹃");
ps.close();
long stareTime=System.currentTimeMillis();
//输出语句的重定向
File f=new File("D:\\resoare\\data06.txt");
PrintStream pss=new PrintStream(f);
System.setOut(pss);
System.out.println("锦瑟无端五十弦");
System.out.println("一弦一柱思华年");
long endTime=System.currentTimeMillis();
System.out.println((endTime-stareTime)+"ms");
}
}
Properties
Properties代表的是一个属性文件,可以把自己对象中的键值对信息存入到另一个属性文件中去
public class MapPeoperties02 {
public static void main(String[] args) throws Exception {
//读取属性文件中的键值对信息
Properties properties=new Properties();
System.out.println(properties);
properties.setProperty("agcsc","13515");
properties.setProperty("adscc","845212");
properties.load(new FileReader("D:\\resoare\\data08.txt"));
System.out.println(properties);
String data=properties.getProperty("agcsc");
System.out.println(data);
}
}
/**
* Properties是继承自HashMap
*/
public class MapProperties {
public static void main(String[] args) throws IOException {
//Properties代表的是一个属性文件,可以把自己对象中的键值对信息存入到另一个属性文件中去
// Map m=new Properties();//一般不会这样写,我们需要Properties的独有方法
Properties properties=new Properties();
//properties.put("adas","15323");//put是Properties继承过来的方法,对于Properties有属于
//他自己的添加数据的方法,但这种方法的本质是不变的
properties.setProperty("agcsc","13515");
properties.setProperty("adscc","845212");
System.out.println(properties);
//把键值对信息存入到属性文件中去
BufferedWriter writer=new BufferedWriter(new FileWriter("D:\\resoare\\data07.txt"));
// properties.store(new FileWriter("D:\\resoare\\data07.txt"),"这个参数没什么用,自己想写什么写什么,也可以不写");
properties.store(writer,"这个参数没什么用,自己想写什么写什么,也可以不写");
writer.close();
}
}
最后介绍一下IO框架,它里面有相当的方法可以来处理IO流的许多问题;
下面是其官网