Java基础---I/O流--序列流+PrintStream+转换流+Serializable+Properties

一、序列流
    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();
	}
}

 

猜你喜欢

转载自blog.csdn.net/JinChao94/article/details/84099061
今日推荐