一、序列流
SequenceInputStream (序列流) : 可以把多个输入流串联起来读取,先从第一个开始i读取,然后再下一个....
方式一:只合并两个流
public SequenceInputStream(InputStream s1,InputStream s2)
将按顺序读取这两个参数,先读取 s1 然后读取 s2
参数:两个输入流
// 方式一:合并两个文件
public static void merge1() throws IOException {
// 找到目标文件对象
File inFile1 = new File("g:\\a.txt");
File inFile2 = new File("g:\\b.txt");
File outFile = new File("g:\\s.txt");
// 第二步:建立数据的输入输出通道
FileOutputStream fileOutputStream = new FileOutputStream(outFile);
// 建立数据的输入输出通道
FileInputStream fileInputStream1 = new FileInputStream(inFile1);
fileInputStream2 = new FileInputStream(inFile2);
// 创建序列流对象
SequenceInputStream sequenceInputStream = new SequenceInputStream(fileInputStream1, fileInputStream2);
// 边读边写
byte[] buf = new byte[1024];
int length = 0;
while ((length = sequenceInputStream.read(buf)) != -1) {
fileOutputStream.write(buf, 0, length);
}
// 关闭资源
sequenceInputStream.close();
fileOutputStream.close();
}
方式二:合并多个流 (重点是构造迭代器)
public SequenceInputStream(Enumeration<? extends InputStream> e)
将按顺序读取由该枚举生成的输入流,调用该流的 close 方法将其关闭
参数:必须是InputStream对象的Enumeration型参数
// 把三个文件合并成一个。
public static void merge2() throws IOException {
// 找到目标文件对象
File inFile1 = new File("g:\\a.txt");
File inFile2 = new File("g:\\b.txt");
File inFile3 = new File("g:\\c.txt");
File outFile = new File("g:\\s.txt");
// 建立数据的输入输出通道
FileOutputStream fileOutputStream = new FileOutputStream(outFile);
FileInputStream fileInputStream1 = new FileInputStream(inFile1);
FileInputStream fileInputStream2 = new FileInputStream(inFile2);
FileInputStream fileInputStream3 = new FileInputStream(inFile3);
// 通过Vector得到一个迭代器。
Vector<FileInputStream> v = new Vector<FileInputStream>();
v.add(fileInputStream1);
v.add(fileInputStream2);
v.add(fileInputStream3);
Enumeration<FileInputStream> e = v.elements();
// 创建一个序列流对象
SequenceInputStream inputStream = new SequenceInputStream(e);
// 创建缓冲数组,边读边写
byte[] buf = new byte[1024];
int length = 0;
while ((length = inputStream.read(buf)) != -1) {
fileOutputStream.write(buf, 0, length);
}
// 关闭资源
inputStream.close();
fileOutputStream.close();
}
应用:MP3文件的切割与合并
//文件切割与合并
public class SequenceInputStream2 {
public static void main(String[] args) throws IOException {
//cutFile();
mergeFile();
}
// 切割mp3文件
public static void cutFile() throws IOException {
File file = new File("g:/1.mp3");
FileInputStream fileInputStream = new FileInputStream(file);
byte[] buf = new byte[1024 * 1024];
int length = 0;
int count = 1;
while ((length = fileInputStream.read(buf)) != -1) {
// 每读取一次,则生成一个文件 注意文件路径的设置
FileOutputStream fileOutputStream = new FileOutputStream("g:/music/" + count + ".mp3");
// 把读取到的数据写出
fileOutputStream.write(buf, 0, length);
count++;
// 关闭资源
fileOutputStream.close();
}
// 关闭资源
fileInputStream.close();
}
// 合并mp3文件
public static void mergeFile() throws IOException {
// 文件夹路径
File dir = new File("g:/music");
// 获取到文件夹中的所有子文件
File[] files = dir.listFiles();
// 创建一个Vector对象存储FileInputStream对象
Vector<FileInputStream> vector = new Vector<FileInputStream>();
// 遍历数组,添加到集合
for (int i = 0; i < files.length; i++) {
if (files[i].getName().endsWith(".mp3")) {
vector.add(new FileInputStream(files[i]));
}
}
// 创建一个序列流对象
SequenceInputStream inputStream = new SequenceInputStream(vector.elements());
// 创建一个输出流对象
FileOutputStream fileOutputStream = new FileOutputStream("g:/合并.mp3");
// 边读边写
byte[] buf = new byte[1024];
int length = 0;
while ((length = inputStream.read(buf)) != -1) {
fileOutputStream.write(buf, 0, length);
}
// 关闭资源
fileOutputStream.close();
inputStream.close();
}
二、对象输入输出流
ObjectOutputStream(对象的输出流类): 把 对象数据 写出到硬盘文件上 序列化
ObjectInputStream(对象的输入流类): 把 硬盘中的 对象数据 读取回来 反序列化
Serializable接口 没有任何方法,这种接口称作为标识接口
serialVersionUID版本号 :通过类名、包名、工程名、成员一起计算得出的id号
序列反序列注意:
1.ObjectOutputStream的writeObject方法只能写出实现了Serializable接口的对象
2.对象反序列化创建对象时是不会调用构造方法。
3.把对象写到文件上时,文件记录对象信息,还记录class的版本号(serialVersionUID)
4.反序列化时,jvm使用本地class文件算出一个id号与文件记录的id号进行对比,如果不一致,反序列化失败。
5.如果一个类的成员可能在后期会发生改动,那么可以在序列化之前就指定一个serialVersionUID , 如果一个类一家指定了一个serialVersionUID那么java虚拟机则不会再计算该class文件的serialVersionUID了。
6.果一个类的某些成员不想被序列化到硬盘上,可以使用关键字transient修饰。
7.一个类的内部维 护了另外一个类对象,则另外一个类也必须要实现Serializable接口
//用户类
class User implements Serializable {
// 提前生成一个serialVersionUID
private static final long serialVersionUID = -4964722333163184880L;
String name;
String password;
transient int age; // transient 透明
public User(String name, String password, int age) {
this.name = name;
this.password = password;
this.age = age;
}
@Override
public String toString() {
return "User [name=" + name + ", password=" + password + ", age=" + age + "]";
}
}
public class Serializable1 {
private static ObjectInputStream inputStream;
public static void main(String[] args) throws Exception {
writeObj();
readObj();
}
// 把对象写到文件上------>对象的序列化。
public static void writeObj() throws IOException {
User user = new User("chao", "ttt", 16);
// 找到目标
File file = new File("g:/obj.txt");
// 建立数据的输出通道
FileOutputStream fileOutputStream = new FileOutputStream(file);
// 建立对象的输出流对象
ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
// 把对象写出到输出流中
objectOutputStream.writeObject(user);
// 关闭资源
objectOutputStream.close();
}
// 对象的反序列化-----> 读取硬盘中的对象到内存中。
public static void readObj() throws Exception {
// 找到目标文件
File file = new File("g:/obj.txt");
// 建立数据的输入流对象
FileInputStream fileInputStream = new FileInputStream(file);
inputStream = new ObjectInputStream(fileInputStream);
// 读取对象的数据
// 反序列化的时候需要创建对象,创建对象需要依赖:Class文件
User user = (User) inputStream.readObject();
// 测试查看
System.out.println("对象的信息:" + user);
}
}
Properties配置文件类 (属于Map集合体系)
作用:
1. 生成配置文件
2. 读取配置
注意:
1.添加数据时不要添加非字符串类型的数据,否则强转报错
2.添加中文字符数据,使用store方法时,使用字符流
3.修改了properties里面的数据,一定要重新生成一个配置文件
4.properties.setProperty(String key,String value)设置值或修改值(map)
5.保证键值对为字符串类型的数据
6.properties.store(OutputStream out,String comments); comments:描述随便写
store()方法写入硬盘
7.加载:加载配置文件到Properties使用load方法
Properties创建+修改+读取配置文件
public class Properties1 {
public static void main(String[] args) throws IOException {
createProperties();
readProperties();
}
// 创建一个配置文件
public static void createProperties() throws IOException {
// 创建一个Properties对象
Properties properties = new Properties();
properties.setProperty("迪迦", "1234");
properties.setProperty("奥特曼", "2345");
properties.setProperty("abc", "4567");
// 当存非中文数据时用字节流
// FileOutputStream fileOutputStream = new
// FileOutputStream("g:/users.properties");
FileWriter fileWriter = new FileWriter("g:/users.properties");
// 利用Properties生成一个配置文件。
properties.store(fileWriter, "jinchao94"); // 第二个参数是使用一段文字对参数列表进行描述。
}
// 读取配置文件 ---- 加载配置文件到Properties是使用load方法。
public static void readProperties() throws IOException {
// 创建一个Properties
Properties properties = new Properties();
// 建立输入字符流对象
FileReader fileReader = new FileReader("g:/users.properties");
// 加载配置文件的数据到Properties是使用load方法。
properties.load(fileReader);
// 遍历元素
Set<Entry<Object, Object>> set = properties.entrySet();
for (Entry<Object, Object> entry : set) {
System.out.println("键:" + entry.getKey() + " 值:" + entry.getValue());
}
// 修改奥特曼...
properties.setProperty("奥特曼", "110");
// 重新生成一个配置文件
properties.store(new FileWriter("g:/users.properties"), "jinchao94");
}
}
Properties应用:正版软件:只能试用三次,三次之后提示购买正版并退出
public class Properties2 {
public static void main(String[] args) throws IOException {
// 先检查是否存在配置文件
File file = new File("g:/usetime.properties");
if (!file.exists()) {
// ,如果不存在,创建配置文件
file.createNewFile();
}
// 创建一个Properties对象
Properties properties = new Properties();
// 加载配置文件
properties.load(new FileReader(file));
// 定义一个变量记录运行的次数
int count = 0;
// 如果配置文件记录了运行次数,则应该使用配置文件的运行次数
String num = properties.getProperty("num");
if (num != null) {
count = Integer.parseInt(num);
}
// 判断是否已经运行了三次
if (count == 3) {
System.out.println("达到限制次数,请购买正版!!");
System.exit(0);
}
count++;
properties.setProperty("num", count + "");
// count+""将count转换成字符串格式(自动)
System.out.println("软件已使用" + count + "次,还剩余" + (3 - count) + "次");
// 重新生成配置文件
properties.store(new FileWriter(file), "runtime");
}
}
PrintStream 打印(输出)流:
打印流的好处:
1. 打印流可以打印任意类型的数据。
2. 打印流打印任意类型数据之前,会先把数据转成字符串然后再打印输出
3. 原样输出
// 作用一:打印任意类型的数据
public static void function1() throws FileNotFoundException {
// 找到目标文件
File file = new File("g:/c.txt");
// 建立打印流对象
PrintStream printStream = new PrintStream(file);
// 打印数据
printStream.println(99160);
// 关闭资源
printStream.close();
}
// 作用二: 收集日志信息
public static void function2() throws FileNotFoundException {
File file = new File("g:/c.txt");
FileOutputStream fileOutputStream = new FileOutputStream(file, true);
PrintStream printStream = new PrintStream(fileOutputStream);
try {
str = null;
System.out.println("字符个数:" + str.length());
result = 4 / 0;
} catch (Exception e) {
e.printStackTrace(printStream);
}
}
转换流:
InputStreamReader :输入字节流转换成输入字符流
OutputStreamWriter :输出字节流转换成输出字符流
转换流的作用:
1. 可以把字节流转换成字符流。
2. 可以指定任意的码表进行读写数据。支持编码指定
作用详细说明:无非就是指定码表 所有转换成字符串输出 快捷方便,功能强大
//转换流
public class IOswitch {
public static void main(String[] args) throws IOException {
readTest1();
writeTest1();
readData();
readData();
}
// 作用一、把输入字节流转换成输入字符流 -----> InputStreamReader
// 此方法可从控制台取一行数据,取代scanner方法
public static void readTest1() throws IOException {
// 先获取标准 的输入流
InputStream in = System.in;
// 把字节流转换成字符流
InputStreamReader inputStreamReader = new InputStreamReader(in);
// 一次读取一行的功能 只有BufferedReader才有,故需要引用
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
// 简写:一行顶三行
// BufferedReader bufferedReader2 = new BufferedReader(new
// InputStreamReader(System.in));
String line = null;
while ((line = bufferedReader.readLine()) != null) {
System.out.println(line);
}
}
// 作用二、把输出字节流转换成输出字符流
public static void writeTest1() throws IOException {
FileOutputStream fileOutputStream = new FileOutputStream("g:/b.txt");
String data = "hello world";
OutputStreamWriter writer = new OutputStreamWriter(fileOutputStream);
// 写出数据
writer.write(data);
// 关闭资源
writer.close();
}
// 作用三、指定码表读取数据
public static void readData() throws IOException {
FileInputStream fileInputStream = new FileInputStream("g:/b.txt");
// FileReader 默认使用的码表是gbk码表,而且不能指定码表读。
// 指定解码格式
InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, "utf-8");
char[] buf = new char[1024];
int length = 0;
while ((length = inputStreamReader.read(buf)) != -1) {
System.out.println(new String(buf, 0, length));
}
// 关闭资源
inputStreamReader.close();
}
// 指定码表进行写数据
public static void writeData() throws IOException {
FileOutputStream fileOutputStream = new FileOutputStream("g:/b.txt");
// FileWriter 默认使用的码表是gbk码表,而且不能指定码表写。
OutputStreamWriter fileWriter = new OutputStreamWriter(fileOutputStream, "utf-8");
fileWriter.write("奥特曼");
fileWriter.close();
}
}