普通IO(BIO)/ NIO
字节流
字节输入流
--InputStream
int available() 返回流中可用的字节数
void close()
abstract int read() 读取一个字节
int read(byte[] b) 读取一个字节数组
int read(byte[] b, int off, int len) 读取字节数组的一部分
long skip(long n) 跳过多n个字节读取
//子类
--FileInputStream
FileInputStream(File file)
/*通过打开一个到实际文件的连接来创建一个 FileInputStream,
该文件通过文件系统中的 File 对象 file 指定。*/
FileInputStream(FileDescriptor fdObj)
/*通过使用文件描述符 fdObj 创建一个 FileInputStream,
该文件描述符表示到文件系统中某个实际文件的现有连接。*/
FileInputStream(String name)
/*通过打开一个到实际文件的连接来创建一个 FileInputStream,
该文件通过文件系统中的路径名 name 指定。 */
-- BufferedInputStream
//能够提高读写效率
字节输出流
--OutputStream
void close() 关闭此输出流并释放与此流有关的所有系统资源。
void flush() 将数据从内存中刷新到文件系统中
void write(byte[] b) 写一个字节数组
void write(byte[] b, int off, int len) 写一个字节数组的一部分
abstract void write(int b) 写一个字节
//子类
--FileOutputStream
FileOutputStream(File file)
//创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
FileOutputStream(File file, boolean append)
//创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
FileOutputStream(FileDescriptor fdObj)
/*创建一个向指定文件描述符处写入数据的输出文件流,
该文件描述符表示一个到文件系统中的某个实际文件的现有连接。*/
FileOutputStream(String name)
创建一个向具有指定名称的文件中写入数据的输出文件流。
FileOutputStream(String name, boolean append)
创建一个向具有指定 name 的文件中写入数据的输出文件流。
--BufferedOutputStream
//能够提高读写效率
字符流
字符输入流
Reader
...
转换流: InputStreamReader
1.处理编码
2.将字节流转化成字符流
FileReader是InputStreamReader子类
高效缓冲字符输入流 BufferedReader
readLine() 读取一行
字符输出流
Writer
...
转换流: OutputStreamWriter
1.处理编码
2.将字节流转化成字符流
FileWriter是OutputStreamWriter子类
高效缓冲字符输出流 BufferedWriter
newLine() 写一个换行符
九种方式拷贝文件
文件拷贝的方式和原理:
1.FileInputStream/FileOutputStream一次性读取一个字节
2.FileInputStream/FileOutputStream一次性读取一个字节数组
3.BufferedInputStream/BufferedOutputStream一次性读取一个字节
4.BufferedInputStream/BufferedOutputStream一次性读取一个字节数组
5.FileReader/FileWriter一次性读取一个字符
6.FileReader/FileWriter一次性读取一个字符数组
7.BufferedReader/BufferedWriter一次性读取一个字符
8.BufferedReader/BufferedWriter一次性读取一个字符数组
9.BufferedReader/BufferedWriter一次性读取一行
代码如下:
package com.sxt.homework;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
/**
* 使用至少9种方式拷贝文件
* 文件拷贝的方式和原理:
* 1.FileInputStream/FileOutputStream一次性读取一个字节
* 2.FileInputStream/FileOutputStream一次性读取一个字节数组
* 3.BufferedInputStream/BufferedOutputStream一次性读取一个字节
* 4.BufferedInputStream/BufferedOutputStream一次性读取一个字节数组
* 5.FileReader/FileWriter一次性读取一个字符
* 6.FileReader/FileWriter一次性读取一个字符数组
* 7.BufferedReader/BufferedWriter一次性读取一个字符
* 8.BufferedReader/BufferedWriter一次性读取一个字符数组
* 9.BufferedReader/BufferedWriter一次性读取一行
* @author berger
*
*/
public class Homework01 {
public static void main(String[] args) {
}
//1.FileInputStream/FileOutputStream一次性读取一个字节
public static void copy1(String srcFileName, String descFileName) {
try (FileInputStream f1 = new FileInputStream(srcFileName);
FileOutputStream f2 = new FileOutputStream(descFileName)){
int by = 0;
while ((by = f1.read()) != -1) {
f2.write(by);
f2.flush();
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
//2.FileInputStream/FileOutputStream一次性读取一个字节数组
public static void copy2(String srcFileName, String descFileName) {
try (FileInputStream f1 = new FileInputStream(srcFileName);
FileOutputStream f2 = new FileOutputStream(descFileName)){
byte [] by = new byte[8192];
int len = 0;
while ((len = f1.read(by)) != -1) {
for (byte b : by) {
f2.write(b);
f2.flush();
}
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
//3.BufferedInputStream/BufferedOutputStream一次性读取一个字节
public static void copy3(String srcFileName, String descFileName) {
try (BufferedInputStream f1 = new BufferedInputStream(new FileInputStream(srcFileName));
BufferedOutputStream f2 = new BufferedOutputStream(new FileOutputStream(descFileName))){
int by = 0;
while ((by = f1.read()) != -1) {
f2.write(by);
f2.flush();
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
//4.BufferedInputStream/BufferedOutputStream一次性读取一个字节数组
public static void copy4(String srcFileName, String descFileName) {
try (BufferedInputStream f1 = new BufferedInputStream(new FileInputStream(srcFileName));
BufferedOutputStream f2 = new BufferedOutputStream(new FileOutputStream(descFileName))){
byte [] by = new byte[8192];
int len = 0;
while ((len = f1.read(by)) != -1) {
for (byte b : by) {
f2.write(b);
f2.flush();
}
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
//5.FileReader/FileWriter一次性读取一个字符
public static void copy5(String srcFileName, String descFileName) {
try (FileReader f1 = new FileReader(srcFileName);
FileWriter f2 = new FileWriter(descFileName)){
int by = 0;
while ((by = f1.read()) != -1) {
f2.write(by);
f2.flush();
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
//6.FileReader/FileWriter一次性读取一个字符数组
public static void copy6(String srcFileName, String descFileName) {
try (FileReader f1 = new FileReader(srcFileName);
FileWriter f2 = new FileWriter(descFileName)){
char [] by = new char[8192];
int len = 0;
while ((len = f1.read(by)) != -1) {
for (char c : by) {
f2.write(c);
f2.flush();
}
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
//7.BufferedReader/BufferedWriter一次性读取一个字符
public static void copy7(String srcFileName,String descFileName) {
try(Reader f1 = new BufferedReader(new FileReader(srcFileName));
Writer f2 = new BufferedWriter(new FileWriter(descFileName))){
int by = 0;
while ((by = f1.read()) != -1) {
f2.write(by);
f2.flush();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}
}
//8.BufferedReader/BufferedWriter一次性读取一个字符数组
public static void copy8(String srcFileName, String descFileName) {
try (BufferedReader f1 = new BufferedReader(new FileReader(srcFileName));
BufferedWriter f2 = new BufferedWriter(new FileWriter(descFileName))){
char [] ch = new char[8192];
int len = 0;
while ((len = f1.read(ch)) != -1) {
for (char c : ch) {
f2.write(c);
f2.flush();
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
//9.BufferedReader/BufferedWriter一次性读取一行
public static void copy9(String srcFileName, String descFileName) {
try (BufferedReader f1 = new BufferedReader(new FileReader(srcFileName));
BufferedWriter f2 = new BufferedWriter(new FileWriter(descFileName))){
while ((f1.readLine()) != null) {
f2.write(f1.readLine());
f2.newLine();
f2.flush();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
基本数据类型流
可以读写基本数据类型
数据输入流:DataInputStream
DataInputStream(InputStream in)
数据输出流:DataOutputStream
DataOutputStream(OutputStream out)
特点:
- 该流是一个字节流,可以读写字节的同时,还能够读写基本数据类型
- 通过数据类型输出流写入到文件中,使用文本文件打开是不能阅读,提高了基本数据类型在文件中保存的安全性
- 读的时候必须和写的顺序保持一致,提高了基本数据类型在文件中保存的安全性
PrintWriter / PrintStream
概述:
向文本输出流打印对象的格式化表示形式。此类实现在 PrintStream 中的所有 print 方法。
特点:
只能写数据,不能读取数据。
可以操作任意类型的数据。
如果启动了自动刷新,能够自动刷新。
输入输出流
系统流不需要我们自己创建,直接使用即可
代码演示如下:
public class OtherIODemo03 {
public static void main(String[] args) throws IOException {
PrintStream ps = System.out;
ps.append("hello");
System.out.println("HelloWorld");
ps.println(new Object());
PrintStream ps2 = System.err;
ps2.println("great");
InputStream in = System.in;
byte[] bys = new byte[10];
int len = in.read(bys);
System.out.println(new String(bys, 0, len));
// java.util.InputMismatchException
Scanner input = new Scanner(System.in);
double d = input.nextDouble();
System.out.println(d);
InputStream in = System.in;
InputStreamReader isr = new InputStreamReader(in);
BufferedReader br = new BufferedReader(isr);
System.out.print("请输入数据:");
String line = br.readLine();
double d = Double.parseDouble(line);
System.out.println("您输入的数据是: " + d);
MyScanner input = new MyScanner(System.in);
System.out.print("请输入字符串: ");
String line = input.nextLine();
System.out.println("数据: " + line);
System.out.print("请输入小数: ");
double d = input.nextDouble();
System.out.println("小数: " + d);
}
}
// 自定义Scanner类
class MyScanner {
// 通过外界传入输入流
private InputStream is;
public MyScanner() {}
public MyScanner(InputStream is) {
this.is = is;
}
public String nextLine() {
BufferedReader br = new BufferedReader(new InputStreamReader(is));
try {
String line = br.readLine();
return line;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public double nextDouble() throws InputMismatchException {
String line = this.nextLine();
try {
double d = Double.parseDouble(line);
return d;
} catch (NumberFormatException e) {
throw new InputMismatchException("hey! 你要输入小数啊!!!!");
}
}
}
RandomAccessFile
概述:此类的实例支持对随机访问文件的读取和写入。
特点:
- RandomAccessFile类不属于流,是Object类的子类。
- 包含了InputStream和OutputStream的功能。
- 能够读写基本类型
- 支持对随机访问文件的读取和写入。 getFilePointer/seek
long getFilePointer()
long length()
void seek(long pos)
void setLength(long newLength)
public class OtherIODemo04 {
public static void main(String[] args) throws Exception {
// write();
read();
}
private static void read() throws Exception {
RandomAccessFile raf = new RandomAccessFile("raf.txt", "rw");
System.out.println(raf.length());
raf.seek(4);
byte[] bys = new byte[5];
int len = raf.read(bys);
System.out.println(new String(bys, 0, len));
// int i = raf.readInt();
// System.out.println(i);
System.out.println(raf.getFilePointer());
raf.close();
}
private static void write() throws Exception {
RandomAccessFile raf = new RandomAccessFile("raf.txt", "rw");
raf.writeInt(100);
raf.write("中国".getBytes());
raf.close();
}
}
序列化流与反序列化流(ObjectOutputStream ObjectInputStream)
ObjectOutputStream 将 Java 对象的基本数据类型和图形写入 OutputStream。
可以使用 ObjectInputStream 读取(重构)对象。通过在流中使用文件可以实现对象的持久存储。
如何实现序列化?
类通过实现 java.io.Serializable 接口以启用其序列化功能。
未实现此接口的类将无法使其任何状态序列化或反序列化,该接口没有任何方法,是一个标机接口。
未实现序列化抛出未序列化异常:NotSerializableException。
序列化数据后,再次修改类文件,读取数据会出问题,如何处理?
使用transient关键字声明不需要序列化的成员变量。
java.io.Not Serializable Exception
java.io.InvalidClassException: com.sxt.otheriodemo.Student;
local class incompatible:
stream classdesc serialVersionUID = 7512677611218988631,
local class serialVersionUID = -6596699813872332589
第一次写入的是后 class文件对应的序列化ID是123456 流中的序列化ID是123456
第一次从流中读取学生对象
流中的序列化ID是123456 = class文件对应的序列化ID是123456
第二次从流中读取学生对象
local class serialVersionUID = -6596699813872332589
流中的序列化ID是123456
Properties
概述:
Properties 类表示了一个持久的属性集;Properties 可保存在流中或从流中加载;属性列表中每个键及其对应值都是一个字符串。
Properties可以当做Map集合类使用
Properties的特殊遍历功能
public Object setProperty(String key,String value)
public String getProperty(String key)
public Set<String> stringPropertyNames()
Properties和IO流结合使用
public void load(Reader reader)
public void store(Writer writer,String comments)
配置文件:
- Properties 轻量级,在网络中传输带宽小,本地存储数据量简单,就是键值对结构,理解为一个类似于map的文件
- XML 重量级,结构化清晰,可读性强,能够存储复杂结构的数据