本文参考自: 原文地址
1. 字符流:字节流 + 编码表
在写入一个字符时,Java虚拟机会将字符转为文件指定的编码(默认是系统默认编码),在读取字符时,再将文件指定的编码转化为字符。
ASCII: 美国标准信息交换码。用一个字节的7位可以表示。
ISO8859-1: 拉丁码表。欧洲码表,用一个字节的8位表示。。
GB2312: 英文占一个字节,中文占两个字节. 中国的中文编码表。
GBK: 中国的中文编码表升级版,两个字节包含了英文字符和扩展的中文
Unicode: 国际标准码规范,融合了多种文字。所有文字都用两个字节来表示, Java语言使用的就是unicode。
UTF-8: 最多用三个字节来表示一个字符。
eg: "中国".getBytes() 即可得到字符串对应的字节数组是[-42, -48, -71, -6]
2. Reader
int read(char[]):将读到的字符存入指定的数组中,返回的是读到的字符个数。如果读到流的末尾,返回-1.
public class IoTest1_Reader {
public static void main(String[] args) throws Exception {
String path = "c:/a.txt";
// readFileByInputStream(path);
readFileByReader(path);
}
/**使用 字节流 读取文件内容 */
public static void readFileByInputStream(String path) throws Exception {
InputStream in = new FileInputStream(path);
int len = 0;
while ((len = in.read()) != -1) {
System.out.print((char) len);
}
in.close();
}
/** 使用 字符流 读取文件内容 */
public static void readFileByReader(String path) throws Exception {
Reader reader = new FileReader(path);
int len = 0;
while ((len = reader.read()) != -1) {
System.out.print((char) len);
}
reader.close();
}
}
3. Writer
Writer中的常见的方法:
write(ch): 将一个字符写入到流中。
write(char[]): 将一个字符数组写入到流中。
write(String): 将一个字符串写入到流中。
flush():刷新流,将流中的数据刷新到目的地中,流还存在。close():关闭资源:在关闭前会先调用flush(),刷新流中的数据去目的地。然流关闭。
* FileWrite 注意的事项:
* 1. 内部是维护一个1024个字符数组的, flush(),close()方法
* 2. 使用 FileWrite 时,没有目标文件,会自动创建
* 3. 目标文件已经存在,会默认清空文件中的数据。如果需要在原来的基础上,需要使用new FileWriter(file,true)方法。
File file = new File("J:/a.txt");
FileWriter fileWriter = new FileWriter(file, true);
String data = "女神经付祖贤女侠";
fileWriter.write(data); // 字符流具备解码的功能
4. 字符流的缓冲区: BufferedReader 类
Reader有一个子类BufferedReader类,该类提供了方法readLine()方法,具备 一次读取一个文本行的功能。
File srcFile = new File("c:\\linux大纲.txt");
FileReader fr = new FileReader(srcFile);
BufferedReader br = new BufferedReader(fr);
public class Demo7 {
public static void main(String[] args) throws IOException {
File srcFile = new File("c:\\linux大纲.txt"); // 关联源文件
File destFile = new File("d:\\linux大纲.txt"); // 关联目标文件
copyFile(srcFile, destFile); // 实现拷贝
}
private static void copyFile(File srcFile, File destFile) throws IOException {
FileReader fr = new FileReader(srcFile); // 创建字符输入流
FileWriter fw = new FileWriter(destFile); // 创建字符输出流
BufferedReader br = new BufferedReader(fr); // 字符输入流的缓冲区
BufferedWriter bw = new BufferedWriter(fw); // 字符输出流的缓冲区
String line = null;
while ((line = br.readLine()) != null) { // 一次读取一行
bw.write(line); // 一次写出一行.
bw.flush(); // 刷新缓冲
bw.newLine(); // 进行换行,由于readLine方法默认没有换行.需要手动换行
}
br.close();
bw.close();
}
}
5. SequenceInputStream 序列流
* SequenceInputStream(Enumeration<? extends InputStream> e)
通过记住参数来初始化新创建的 SequenceInputStream,该参数必须是生成运行时类型为 InputStream 对象的 Enumeration 型参数。
SequenceInputStream(InputStream s1, InputStream s2)
通过记住这两个参数来初始化新创建的 SequenceInputStream(将按顺序读取这两个参数,先读取 s1,然后读取 s2),以提供从此 SequenceInputStream 读取的字节。
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.SequenceInputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Vector;
public class test_1 {
public static void main(String[] args) throws IOException {
// merge1();
// merge2();
merge3();
}
// 合并方法一
public static void merge1() throws IOException {
File file1 = new File("J:/a.txt");
File file2 = new File("J:/b.txt");
File outfile = new File("J:/c.txt");
FileInputStream fileInputStream1 = new FileInputStream(file1);
FileInputStream fileInputStream2 = new FileInputStream(file2);
FileOutputStream fileOutputStream = new FileOutputStream(outfile);
ArrayList<FileInputStream> list = new ArrayList<FileInputStream>();
list.add(fileInputStream1);
list.add(fileInputStream2);
byte[] buf = new byte[100];
int length = 0;
for(int i=0; i<list.size(); i++) {
FileInputStream fileInputStream = list.get(i);
while((length = fileInputStream.read(buf))!=-1) {
fileOutputStream.write(buf,0,length);
}
fileInputStream.close();
}
fileOutputStream.close();
}
// 合并方法二: 两个文件合并,使用序列化
public static void merge2() throws IOException {
File file1 = new File("J:/a.txt");
File file2 = new File("J:/b.txt");
File outfile = new File("J:/c.txt");
FileInputStream fileInputStream1 = new FileInputStream(file1);
FileInputStream fileInputStream2 = new FileInputStream(file2);
SequenceInputStream inputStream = new SequenceInputStream(fileInputStream1, fileInputStream2);
FileOutputStream fileOutputStream = new FileOutputStream(outfile);
byte[] buf = new byte[1024];
int length = 0;
while((length = inputStream.read(buf))!=-1) {
fileOutputStream.write(buf,0,length);
}
inputStream.close();
fileOutputStream.close();
}
//合并方法三: 多个文件读写 ,采用vector的迭代器
public static void merge3() throws IOException {
File file1 = new File("J:/a.txt");
File file2 = new File("J:/b.txt");
File file3 = new File("J:/c.txt");
File file4 = new File("J:/d.txt");
File outfile = new File("J:/e.txt");
FileInputStream fileInputStream1 = new FileInputStream(file1);
FileInputStream fileInputStream2 = new FileInputStream(file2);
FileInputStream fileInputStream3 = new FileInputStream(file3);
FileInputStream fileInputStream4 = new FileInputStream(file4);
FileOutputStream fileOutputStream = new FileOutputStream(outfile);
Vector<FileInputStream> vector = new Vector<FileInputStream>();
vector.add(fileInputStream1);
vector.add(fileInputStream2);
vector.add(fileInputStream3);
vector.add(fileInputStream4);
Enumeration<FileInputStream> enumeration = vector.elements(); // 创建迭代器
SequenceInputStream sequenceInputStream = new SequenceInputStream(enumeration);
byte[] buf = new byte[1024];
int length = 0;
while((length = sequenceInputStream.read(buf))!=-1) {
fileOutputStream.write(buf,0,length);
}
sequenceInputStream.close();
fileOutputStream.close();
}
}
重点:
SequenceInputStream sequenceInputStream = new SequenceInputStream(enumeration);
sequenceInputStream.read(buf)
例子: 对音频进行切分与合并
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.SequenceInputStream;
import java.util.Enumeration;
import java.util.Vector;
public class test_1 {
public static void main(String[] args) throws IOException {
spilt();
merge();
}
// 切分 : 读入进去,切分后写入
public static void spilt() throws IOException {
File file = new File("J:/清晨的美好.mp3");
File dir = new File("J:/music");
FileInputStream fileInputStream = new FileInputStream(file);
byte[] buf = new byte[1024*1024]; // 切分出来的一小段歌曲的 大小
int length = 0;
for(int i=0; (length = fileInputStream.read(buf))!=-1; i++) { // 一个buf数组读完,写入新的音频文件
FileOutputStream fileOutputStream = new FileOutputStream(new File(dir, "part"+i+".mp3"));
fileOutputStream.write(buf,0,length);
fileOutputStream.close();
}
fileInputStream.close();
}
// 合并 :先读入小片音频,之后合并
public static void merge() throws IOException {
File dir = new File("J:/music/");
File[] files = dir.listFiles();
Vector<FileInputStream> vector = new Vector<FileInputStream>();
for(File file : files) {
if(file.getName().endsWith(".mp3")) { // 查找后缀为 .mp3 的文件,变成输入流装入到 vector
vector.add(new FileInputStream(file));
}
}
File outfile = new File("J:/钢琴曲清晨的美好.mp3");
FileOutputStream fileOutputStream = new FileOutputStream(outfile);
Enumeration<FileInputStream> enumeration = vector.elements();
SequenceInputStream sequenceInputStream= new SequenceInputStream(enumeration);
byte[] buf = new byte[1024*1024];
int length = 0;
while((length = sequenceInputStream.read(buf))!=-1) {
fileOutputStream.write(buf,0,length);
}
fileOutputStream.close();
sequenceInputStream.close();
}
}
6. 对象的输入输出流
对象的输入输出流: 对象的输入输出流,作用:用于写对象的信息与读取对象的信息。对象信息一旦写到文件上,那么对象的信息就可以做到持久化。
* 对象输出流: ObjectOutputStream 注意事项:
1. 对象需要写到文件上,那么对象所属类必须 实现 Serializable 接口。2. 对象的反序列化,创建对象不会调用构造方法
3. 出现错误: 调用序列化 writeobj(),之后在User类增加一个变量,再调用反序列化readobj();
local class incompatible: stream classdesc serialVersionUID = -8851711735379258523, local class serialVersionUID = 8126229762432673517
serialVersionUID 是用于记录class文件的版本信息,serialVersionUID这个数字是通过一个类的类名、成员、包名、工程名算出来的一个数字
4. 使用 对象输入流ObjectInputStream 反序列化的时候,会先读取文件中的serialVersionUID,然后与本地class文件的serialVersionUID进行对比,如果不一致,那么出错
5. 如果序列化与反序列化的时候可能会修改成员,可以一开始就给这个类指定一个serialVersionUID,这样jvm就不会再算这个serialVersionUID了!
6. 如果一个对象某个数据不想被序列化到硬盘上,可以使用 关键字 transient 修饰。
7. 如果一个类维护了另外一个类,另外一个类也需要实现 Serializable 接口。
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
class Address implements Serializable{ // 如果一个类维护了另外一个类,另外一个类也需要实现 Serializable 接口。
String country;
String city;
public Address(String country,String city) {
this.country = country;
this.city = city;
}
}
class User implements Serializable{ // 实现 Serializable 接口
private static final long serialVersionUID = 1L; // 给这个类指定一个serialVersionUID,这样jvm就不会再去算
String username;
String password;
transient int age; // 关键字 transient(透明) ,这个数据不想被序列化到硬盘上
Address address;
public User(String username, String password) {
this.password = password;
this.username = username;
}
public User(String username, String password,int age,Address address) {
this.password = password;
this.username = username;
this.age = age;
this.address = address;
}
@Override
public String toString() {
return "{用户名: " + this.username + " 密码: " + this.password + " 年龄: " + this.age + " 地址:" + this.address.city + "}";
}
}
public class test_1 {
public static void main(String[] args) throws Exception {
writeobj();
readobj();
}
// 把文件中的对象信息读出来--------》 对象的反序列化
public static void readobj() throws IOException, Exception {
File file = new File("J:/object.txt");
FileInputStream fileInputStream = new FileInputStream(file);
ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
User user = (User)objectInputStream.readObject();
System.out.println(user); // 创建对象肯定要依赖对象所属的class文件
objectInputStream.close();
}
// 定义方法将对象的信息写到硬盘上------》对象的序列化
public static void writeobj() throws IOException {
Address address = new Address("中国", "杭州");
User user = new User("付祖贤", "0101", 24, address);
File file = new File("J:/object.txt"); // 找到目标文件
FileOutputStream fileOutputStream = new FileOutputStream(file); // 建立数据的输出流对象
ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream); //建立对象的输出流对象
objectOutputStream.writeObject(user); // 把对象写出
objectOutputStream.close();
}
}
重点:
ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
User user = (User)objectInputStream.readObject();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream); //建立对象的输出流对象
objectOutputStream.writeObject(user); // 把对象写出