-
IO流,什么是IO?
I : Input
O : Output
通过IO可以完成硬盘文件的读和写。 -
IO流的分类?
有多种分类方式:
一种方式是按照流的方向进行分类: 以内存作为参照物, 往内存中去,叫做输入(Input)。或者叫做读(Read)。 从内存中出来,叫做输出(Output)。或者叫做写(Write)。 另一种方式是按照读取数据方式不同进行分类: 有的流是按照字节的方式读取数据,一次读取1个字节byte,等同于一次读取8个二进制位。 这种流是万能的,什么类型的文件都可以读取。包括:文本文件,图片,声音文件,视频文件等.... 假设文件file1.txt,采用字节流的话是这样读的: a中国bc张三fe 第一次读:一个字节,正好读到'a' 第二次读:一个字节,正好读到'中'字符的一半。 第三次读:一个字节,正好读到'中'字符的另外一半。 有的流是按照字符的方式读取数据的,一次读取一个字符,这种流是为了方便读取 普通文本文件而存在的,这种流不能读取:图片、声音、视频等文件。只能读取纯 文本文件,连word文件都无法读取。 假设文件file1.txt,采用字符流的话是这样读的: a中国bc张三fe 第一次读:'a'字符('a'字符在windows系统中占用1个字节。) 第二次读:'中'字符('中'字符在windows系统中占用2个字节。)
综上所述:流的分类
输入流、输出流
字节流、字符流 -
java IO流这块有四大家族:
四大家族的首领:
java.io.InputStream 字节输入流
java.io.OutputStream 字节输出流java.io.Reader 字符输入流 java.io.Writer 字符输出流 四大家族的首领都是抽象类。(abstract class) 所有的流都实现了: java.io.Closeable接口,都是可关闭的,都有close()方法。 流毕竟是一个管道,这个是内存和硬盘之间的通道,用完之后一定要关闭, 不然会耗费(占用)很多资源。养成好习惯,用完流一定要关闭。 所有的输出流都实现了: java.io.Flushable接口,都是可刷新的,都有flush()方法。 养成一个好习惯,输出流在最终输出之后,一定要记得flush() 刷新一下。这个刷新表示将通道/管道当中剩余未输出的数据 强行输出完(清空管道!)刷新的作用就是清空管道。 注意:如果没有flush()可能会导致丢失数据。
注意:在java中只要“类名”以Stream结尾的都是字节流。以“Reader/Writer”结尾的都是字符流。
-
java.io包下需要掌握的流有16个:
文件专属: java.io.FileInputStream(掌握) java.io.FileOutputStream(掌握) java.io.FileReader java.io.FileWriter 转换流:(将字节流转换成字符流) java.io.InputStreamReader java.io.OutputStreamWriter 缓冲流专属: java.io.BufferedReader java.io.BufferedWriter java.io.BufferedInputStream java.io.BufferedOutputStream 数据流专属: java.io.DataInputStream java.io.DataOutputStream 标准输出流: java.io.PrintWriter java.io.PrintStream(掌握) 对象专属流: java.io.ObjectInputStream(掌握) java.io.ObjectOutputStream(掌握)
package com.bjpowernode.java.io;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/*
FileInputStream类的其它常用方法:
int available():返回流当中剩余的没有读到的字节数量
long skip(long n):跳过几个字节不读。
*/
public class FileInputStreamTest05 {
public static void main(String[] args) {
FileInputStream fis = null;
try {
fis = new FileInputStream("tempfile");
System.out.println("总字节数量:" + fis.available());
// 读1个字节
//int readByte = fis.read();
// 还剩下可以读的字节数量是:5
//System.out.println("剩下多少个字节没有读:" + fis.available());
// 这个方法有什么用?
//byte[] bytes = new byte[fis.available()]; // 这种方式不太适合太大的文件,因为byte[]数组不能太大。
// 不需要循环了。
// 直接读一次就行了。
//int readCount = fis.read(bytes); // 6
//System.out.println(new String(bytes)); // abcdef
// skip跳过几个字节不读取,这个方法也可能以后会用!
fis.skip(3);
System.out.println(fis.read()); //100
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
package com.bjpowernode.java.io;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* 文件字节输出流,负责写。
* 从内存到硬盘。
*/
public class FileOutputStreamTest01 {
public static void main(String[] args) {
FileOutputStream fos = null;
try {
// myfile文件不存在的时候会自动新建!
// 这种方式谨慎使用,这种方式会先将原文件清空,然后重新写入。
//fos = new FileOutputStream("myfile");
//fos = new FileOutputStream("chapter23/src/tempfile3");
// 以追加的方式在文件末尾写入。不会清空原文件内容。
fos = new FileOutputStream("chapter23/src/tempfile3", true);
// 开始写。
byte[] bytes = {97, 98, 99, 100};
// 将byte数组全部写出!
fos.write(bytes); // abcd
// 将byte数组的一部分写出!
fos.write(bytes, 0, 2); // 再写出ab
// 字符串
String s = "我是一个中国人,我骄傲!!!";
// 将字符串转换成byte数组。
byte[] bs = s.getBytes();
// 写
fos.write(bs);
// 写完之后,最后一定要刷新
fos.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
package com.bjpowernode.java.io;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*
使用FileInputStream + FileOutputStream完成文件的拷贝。
拷贝的过程应该是一边读,一边写。
使用以上的字节流拷贝文件的时候,文件类型随意,万能的。什么样的文件都能拷贝。
*/
public class Copy01 {
public static void main(String[] args) {
FileInputStream fis = null;
FileOutputStream fos = null;
try {
// 创建一个输入流对象
fis = new FileInputStream("D:\\course\\02-JavaSE\\video\\chapter01\\动力节点-JavaSE-杜聚宾-001-文件扩展名的显示.avi");
// 创建一个输出流对象
fos = new FileOutputStream("C:\\动力节点-JavaSE-杜聚宾-001-文件扩展名的显示.avi");
// 最核心的:一边读,一边写
byte[] bytes = new byte[1024 * 1024]; // 1MB(一次最多拷贝1MB。)
int readCount = 0;
while((readCount = fis.read(bytes)) != -1) {
fos.write(bytes, 0, readCount);
}
// 刷新,输出流最后要刷新
fos.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
// 分开try,不要一起try。
// 一起try的时候,其中一个出现异常,可能会影响到另一个流的关闭。
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
package com.bjpowernode.java.io;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
/*
使用FileReader FileWriter进行拷贝的话,只能拷贝“普通文本”文件。
*/
public class Copy02 {
public static void main(String[] args) {
FileReader in = null;
FileWriter out = null;
try {
// 读
in = new FileReader("chapter23/src/com/bjpowernode/java/io/Copy02.java");
// 写
out = new FileWriter("Copy02.java");
// 一边读一边写:
char[] chars = new char[1024 * 512]; // 1MB
int readCount = 0;
while((readCount = in.read(chars)) != -1){
out.write(chars, 0, readCount);
}
// 刷新
out.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (out != null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
package com.bjpowernode.java.io;
import java.io.BufferedReader;
import java.io.FileReader;
/*
BufferedReader:
带有缓冲区的字符输入流。
使用这个流的时候不需要自定义char数组,或者说不需要自定义byte数组。自带缓冲。
*/
public class BufferedReaderTest01 {
public static void main(String[] args) throws Exception{
FileReader reader = new FileReader("Copy02.java");
// 当一个流的构造方法中需要一个流的时候,这个被传进来的流叫做:节点流。
// 外部负责包装的这个流,叫做:包装流,还有一个名字叫做:处理流。
// 像当前这个程序来说:FileReader就是一个节点流。BufferedReader就是包装流/处理流。
BufferedReader br = new BufferedReader(reader);
// 读一行
/*String firstLine = br.readLine();
System.out.println(firstLine);
String secondLine = br.readLine();
System.out.println(secondLine);
String line3 = br.readLine();
System.out.println(line3);*/
// br.readLine()方法读取一个文本行,但不带换行符。
String s = null;
while((s = br.readLine()) != null){
System.out.print(s);
}
// 关闭流
// 对于包装流来说,只需要关闭最外层流就行,里面的节点流会自动关闭。(可以看源代码。)
br.close();
}
}
package com.bjpowernode.java.io;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
/*
转换流:InputStreamReader
*/
public class BufferedReaderTest02 {
public static void main(String[] args) throws Exception{
/*// 字节流
FileInputStream in = new FileInputStream("Copy02.java");
// 通过转换流转换(InputStreamReader将字节流转换成字符流。)
// in是节点流。reader是包装流。
InputStreamReader reader = new InputStreamReader(in);
// 这个构造方法只能传一个字符流。不能传字节流。
// reader是节点流。br是包装流。
BufferedReader br = new BufferedReader(reader);*/
// 合并
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("Copy02.java")));
String line = null;
while((line = br.readLine()) != null){
System.out.println(line);
}
// 关闭最外层
br.close();
}
}
- java.io.File类。 File类的常用方法。
package com.bjpowernode.java.io;
import java.io.File;
/*
File
1、File类和四大家族没有关系,所以File类不能完成文件的读和写。
2、File对象代表什么?
文件和目录路径名的抽象表示形式。
C:\Drivers 这是一个File对象
C:\Drivers\Lan\Realtek\Readme.txt 也是File对象。
一个File对象有可能对应的是目录,也可能是文件。
File只是一个路径名的抽象表示形式。
3、需要掌握File类中常用的方法
*/
public class FileTest01 {
public static void main(String[] args) throws Exception {
// 创建一个File对象
File f1 = new File("D:\\file");
// 判断是否存在!
System.out.println(f1.exists());
// 如果D:\file不存在,则以文件的形式创建出来
/*if(!f1.exists()) {
// 以文件形式新建
f1.createNewFile();
}*/
// 如果D:\file不存在,则以目录的形式创建出来
/*if(!f1.exists()) {
// 以目录的形式新建。
f1.mkdir();
}*/
// 可以创建多重目录吗?
File f2 = new File("D:/a/b/c/d/e/f");
/*if(!f2.exists()) {
// 多重目录的形式新建。
f2.mkdirs();
}*/
File f3 = new File("D:\\course\\01-开课\\学习方法.txt");
// 获取文件的父路径
String parentPath = f3.getParent();
System.out.println(parentPath); //D:\course\01-开课
File parentFile = f3.getParentFile();
System.out.println("获取绝对路径:" + parentFile.getAbsolutePath());
File f4 = new File("copy");
System.out.println("绝对路径:" + f4.getAbsolutePath()); // C:\Users\Administrator\IdeaProjects\javase\copy
}
}
package com.bjpowernode.java.io;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
/*
File类的常用方法
*/
public class FileTest02 {
public static void main(String[] args) {
File f1 = new File("D:\\course\\01-开课\\开学典礼.ppt");
// 获取文件名
System.out.println("文件名:" + f1.getName());
// 判断是否是一个目录
System.out.println(f1.isDirectory()); // false
// 判断是否是一个文件
System.out.println(f1.isFile()); // true
// 获取文件最后一次修改时间
long haoMiao = f1.lastModified(); // 这个毫秒是从1970年到现在的总毫秒数。
// 将总毫秒数转换成日期?????
Date time = new Date(haoMiao);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
String strTime = sdf.format(time);
System.out.println(strTime);
// 获取文件大小
System.out.println(f1.length()); //216064字节。
}
}
package com.bjpowernode.java.io;
import java.io.File;
/*
File中的listFiles方法。
*/
public class FileTest03 {
public static void main(String[] args) {
// File[] listFiles()
// 获取当前目录下所有的子文件。
File f = new File("D:\\course\\01-开课");
File[] files = f.listFiles();
// foreach
for(File file : files){
//System.out.println(file.getAbsolutePath());
System.out.println(file.getName());
}
}
}
-
关于对象流 ObjectInputStream ObjectOutputStream
重点:
参与序列化的类型必须实现java.io.Serializable接口。
并且建议将序列化版本号手动的写出来。
private static final long serialVersionUID = 1L; -
IO + Properties联合使用。
IO流:文件的读和写。
Properties:是一个Map集合,key和value都是String类型。
Copy By动力节点老杜Java笔记