注:本文章由本人整理笔记。参考韩顺平IO流专题链接在此
目录
IO流,就是Input流 (输入流) 和Output流 (输出流) 的简写。Java
IO流根据处理数据类型的不同分为字符流和字节流,根据数据流向不同分为输入流和输出流,对输入流只能进行读操作,对输出流只能进行写操作,程序中需要根据待传输数据的不同特性而使用不同的流。
1、文件
文件 :文件,对我们并不陌生,文件是保存数据的地方,比如大家经常使用的word文档,txt文件,excel文件..都是文件。它既可以保存一张图片也可以保持视频,声音...
创建文件:
创建文件对象相关构造器和方法 ➢ 相关方法
new File(String pathname) //根据路径构建一个File对象
new File(File parent,String child) //根据父目录文件+子路径构建
new File(String parent,String child) //根据父目录+子路径构建
createNewFile创建新文件
package IO.Demo;
import java.io.File;
import java.io.IOException;
public class MakeFile {
public static void main(String[] args) {
//创建文档。 方式一: new File(String pathname);
// createNewFile();
File file = new File("f:\\first.txt");
try {//IO异常
file.createNewFile(); //返回一个boolean值
System.out.println("创建成功");
} catch (IOException e) {
e.printStackTrace();
System.out.println("创建失败");
}
method2();
method3();
}
// 方法二 : new File(File parent,String child) //根据父目录文件 + 子路径构建
// f:\\second.txt
public static void method2() {
File file = new File("f:\\");
File file1 = new File(file, "second.txt");
//一个file对象 只是一个对象
// 只有执行了 createNewFile 方法后 才会真正的 在磁盘中 创建这个文件
//也可以以直接 File file = new File("f:\\second.txt");
try {
file1.createNewFile();
System.out.println("创建成功");
} catch (IOException e) {
e.printStackTrace();
System.out.println("创建失败");
}
}
方式三 : new File(String parent , String child) //根据父目录+子路径构建
public static void method3() {
String parentpath = "f:\\";
String fileName = "third.doc";
File file = new File(parentpath, fileName);
try {
file.createNewFile();
System.out.println("创建成功");
} catch (IOException e) {
e.printStackTrace();
System.out.println("创建失败");
}
}
}
2、获取文件信息
//先创建文件
File file = new File("f:\\test.txt");
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
//调用对应方法,得到对应信息
//getName、getAbsoLutePath、 getParent、 Length、 exists、 isFile、 isDirectory
System.out.println("文件的名字是:"+file.getName());
System.out.println("文件的绝对路径是:"+file.getAbsolutePath());
System.out.println("文件的父级路径是:"+file.getParent());
System.out.println("文件的大小(字节)是:"+file.length());
//exists() 返回Boolean值 文件是否存在
System.out.println("文件是否存在:"+file.exists());
System.out.println("是不是一个文件:"+file.isFile());
System.out.println("是不是一个目录:"+file.isDirectory());
System.out.println("是不是一个目录:"+file.isAbsolute()); //如果此抽象路径名是绝对的,则该方法返回true,否则该方法返回false。
3、目录操作
//mkdir 创建一级目录
//mkdirs 创建多级目录
File file = new File("f:\\demo\\a\\b\\c");
file.mkdirs(); //创建目录
file.delete(); //删除
4、IO流原理和分类
Java IO流原理
IO是 Input/Output 的缩写, I/O技术是非常实用的技术, 用于处理数据传输。
如读/写文件,网络通讯等。
Java程序中, 对于数据的输入/输出操作以”流(stream)"的方式进行。
java.io包 下提供了各种 "流"类和接口, 用以获取不同种类的数据,并通过方 法输入或输出数据
下面四个都是抽象类
1) Java的I0流共涉及40多个类,实际上非常规则,都是从如上4个抽象基类派生的。
2)由这四个类派生出来的子类名称都是以其父类名作为子类名后缀。
InputStream //字节输入流
OutputStream //字节输出流Writer //字符输出流
Reader //字符输入流
5、字符输入流
* 演示FileInputStream的使用 (字节输入流) 文件 --> 程序
* FilelnputStream应用实例FileInputStream .java
* 要求:请使用FileInputStream读取hello.txt文件,并将文件内容显示到控制台.
* 单个字节的读取, 效率比较低
String path = "f:\\hello.txt";
int readData = 0; //用于存放读取文件的内容
FileInputStream fileInputStream = null;
try {
//创建对象 用于读取文件
fileInputStream = new FileInputStream(path);
//从该输入流读取一个字节的数据。 如果没有输入可用,此方法将阻止
//如何返回-1 ,表示读取完毕
while ((readData = fileInputStream.read()) != -1) {
System.out.print((char) readData);
// 读取出来的是ASCLL码。强制转换为 char 类型
}
}
catch (IOException e) {
e.printStackTrace();
}
finally {
//关闭文件流,释放资源
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
int readData = 0; //用于存放读取文件的内容
FileInputStream fileInputStream = new FileInputStream(path);
//读取单个字节, 存放到readData中
readData = fileInputStream.read()
6、 字符输出流
使用FileoutputStream 将数据写入文件,如果文件不存在 就 自动创建文件
语法大同小异
//注:
// new FileOutputStream(path); 是 覆盖方式
// new FileOutputStream(path,true); 是 追加方式
String path = "f:\\testOut.txt";
FileOutputStream fileOutputStream = null;
try {
//创建对象
fileOutputStream = new FileOutputStream(path,true); //追加写入
//写入一个字节
fileOutputStream.write('a');
//写入一个字符串 str.getBytes() 可以把一个字符串 转换成 字节数组
String str = "我是xxx";
fileOutputStream.write(str.getBytes());
System.out.println("写入成功");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
String path = "f:\\testOut.txt";
FileOutputStream fileOutputStream = null;
try {
//创建对象
fileOutputStream = new FileOutputStream(path,true); //追加写入
//写入一个字节
fileOutputStream.write('a');
//写入一个字符串 str.getBytes() 可以把一个字符串 转换成 字节数组
String str = "我是麻辣香锅";
fileOutputStream.write(str.getBytes());
System.out.println("写入成功");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
案例:复制粘贴文件
把 f盘的 拉克丝 文件 拷贝 到 f盘的拉克丝 文件夹中 。因为图片是二进制文件,所以我们用字节流。InputStream和OutputStream
String path = "f:\\拉克丝.png";
FileInputStream inputStream = null;
FileOutputStream outputStream = null;
String path2 = "f:\\拉克丝\\拉克丝.png";
File file2 = new File(path2);
int readData = 0;
try {
inputStream = new FileInputStream(path); //输入流 把文件从F盘 输入到 java程序
//这里采用覆盖方式输出,
//如果用追加方式,不会生成多个文件,而会增加文件内存大小
//输出流, 把文件 输出到 目标地址
outputStream = new FileOutputStream(path2);
while ((readData = inputStream.read()) != -1) {
outputStream.write(readData); //将读取到的 文件 写入 新的地址
}
if (file2.exists()) { //如果新的地址存在 (成功写入)
System.out.println("COPY成功");
} else {
System.out.println("copy失败");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
//关闭流
inputStream.close();
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
可见,F盘里的拉克丝图片,已经复制到F盘的 拉克丝文件夹下。
7、FileWriter 和 FileReader
FileWriter 和 FileReader是 字符流Writer 和 Reader 的子类
FileWriter可以写入中文
String path = "f:\\hello.txt";
FileWriter fileWriter = null;
String arr = "风雨之后,定见彩虹"; //写入字符串
char[] x = {'1', '2', '3'};
try {
fileWriter = new FileWriter(path, true);
//4) write (string) :写入整个字符串
fileWriter.write(arr);
//1) write(int):写入单个字符
fileWriter.write('H'); //写入单个字符
//2) write(char[]):写入指定数组
fileWriter.write(x);
//3) write(char[], off,Len):写入指定数组的指定部分
//从0 开始 写两个
fileWriter.write(x, 0, 2);
//5) write (string, off,Len):写入字符串的指定部分
fileWriter.write(arr, 0, 4);
System.out.println("写入成功");
//数据量大的情况下,可以使用循环
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
结果
FileReader可以读取中文
String path = "f:\\hello.txt";
FileReader fileReader = null;
int FileData = 0 ; //用于存放 文件内容
//创建FileReader 对象
try {
try {
fileReader = new FileReader(path);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
while ((FileData = fileReader.read()) != -1){
System.out.print((char) FileData);
}
} catch (IOException e) {
e.printStackTrace();
}
结果:
8、节点流和处理流
用BufferedWriter/BufferedReader 可以有Writer / Reader 的 功能。 还可以拓展功能。
8.1、BufferedWriter
import java.io.*;
public class BufferedWriter_ {
public static void main(String[] args) throws IOException {
String path = "f:\\hello.txt";
//创建对象
BufferedWriter bf = new BufferedWriter(new FileWriter(path));
//追加写入
// BufferedWriter bf = new BufferedWriter(new FileWriter(path,true));
bf.write("你好1.我是熊大!");
//插入一个和系统相关的换行符
bf.newLine();
bf.write("你好2.我是熊二!");
bf.newLine();
bf.write("你好3.我是光头强!");
System.out.println("写入成功!");
//关闭外层流即可,传入的new FileWriter(path) , 会在底层关闭
bf.close();
}
}
8.2、BufferedReader
import java.io.*;
public class BufferedReader_ {
public static void main(String[] args) throws IOException
{
String path = "f:\\hello.txt";
//创建BufferedReader 对象
// 用BufferedReader来包装一个 FileReader 对象
BufferedReader bf = new BufferedReader(new FileReader(path));
// 按行 读取
String line; //按行读取 效率高
/**
* 说明
* bf.readLine(); 是按行读取文件
* 当返回null时 表示文件读取完成
*/
//可以按行读取
while ((line = bf.readLine()) != null) {
System.out.println(line);
}
bf.close();
}
}
8.3、Buffered拷贝
复制字符
(1). read()
public static void main(String[] args) throws IOException {
//实现字符的复制(字符流)
String path1 = "f:\\hello.txt";
String path2 = "f:\\拉克丝\\copy.txt";
BufferedReader bfr = new BufferedReader(new FileReader(path1));
BufferedWriter bfw = new BufferedWriter(new FileWriter(path2));
int readData = 0 ; //用于存放读取的数据
while ((readData = bfr.read()) != -1 ){
bfw.write(readData);
}
System.out.println("复制成功");
bfr.close();
bfw.close();
}
(2). readLine()
//不抛出异常的 要用try catch 来包围
public static void main(String[] args) {
//实现字符的复制(字符流)
String path1 = "f:\\hello.txt";
String path2 = "f:\\拉克丝\\copy.txt";
BufferedReader bfr = null;
BufferedWriter bfw = null;
String readLine = ""; //用于存放读取 一行 的 数据
try {
bfr = new BufferedReader(new FileReader(path1));
bfw = new BufferedWriter(new FileWriter(path2));
while ((readLine = bfr.readLine()) != null) {
bfw.write(readLine);
bfw.newLine(); //换行两次
bfw.newLine();
}
} catch (IOException e) {
System.out.println(e);
} finally {
try {
//关闭流
if (bfr != null) {
bfr.close();
}
if (bfw != null) {
bfw.close();
}
} catch (IOException e) {
System.out.println(e);
}
}
}
(3). 复制图片(或复制字节)
/**
* 利用Buffered
* 将F盘中的 拉克丝.png 复制到 F盘中拉克丝文件夹中(字节流)
*/
String path1 = "f:\\拉克丝.png";
String path2 = "f:\\拉克丝\\拉克丝.png";
//用于存放读取的数据
int readData = 0;
//将 拉克丝图片 以二进制流(字节流) 读取过来
BufferedInputStream bfinput = new BufferedInputStream(new FileInputStream(path1));
BufferedOutputStream bfoutput = new BufferedOutputStream(new FileOutputStream(path2));
while ((readData = bfinput.read()) != -1) {
//写入
bfoutput.write(readData);
}
System.out.println("复制成功");
//关闭流
bfinput.close();
bfoutput.close();
}
9、对象处理流
➢序列化和反序列化
1.序列化就是在保存数据时,保存数据的值和数据类型 2.反序列化就是在恢复数据时,恢复数据的值和数据类型 3.需要让某个对象支持序列化机制,则必须让其类是可序列化的,为了让某个类是可序列化的,该 类必须实现如下两个接口之一: ➢Serializable // 这是一个标记接口 ➢Externalizable
9.1、序列化
public class ObjectInputStream_ {
public static void main(String[] args) throws Exception {
String path = "f:\\object.obj";
//创建流对象
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(path));
//读取,注意顺序
//读取的顺序必须要和写入的顺序一致
System.out.println(ois.readInt());
System.out.println(ois.readBoolean());
System.out.println(ois.readChar());
System.out.println(ois.readDouble());
System.out.println(ois.readUTF());
Object dog = ois.readObject();
System.out.println("运行的类型"+dog.getClass());
System.out.println("狗的信息"+dog);
ois.close();
}
}
//如果需要序列化某个对象,要实现Serializable 接口
class Dog implements Serializable {
private String name;
private int age;
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
这样会出现乱码
9.2、反序列化
public class ObjectOutputStream_ {
public static void main(String[] args) throws IOException {
//序列化后,保存的文件格式,不是存文本,而是按照他的格式来保存
// String path = "f:\\object.obj";
String path = "f:\\object.obj";
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(path));
//序列化数据 到 path
oos.writeInt(100); //int -> Integer 实现了Serializable
oos.writeBoolean(true); //boolean -> Boolean 实现了Serializable
oos.writeChar('a'); // char -> character 实现了Serializable
oos.writeDouble(7.9); // double -> Double 实现了Serializable
oos.writeUTF("我是lmh"); //String 实现了Serializable
//保存一个dog对象
oos.writeObject(new Dog("旺财",20));
//关闭流
oos.close();
System.out.println("保存完毕(序列化形式)");
}
}
//如果需要序列化某个对象,要实现Serializable 接口
class Dog implements Serializable{
private String name;
private int age;
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
结果: