DAY13
☞☞☞ IO流
- 按照流的方法
- 读取流:读取数据
- 输出流:写出数据
- 按照数据类型
- 字节流:任何文件都可以被看成一个字节数组,字节流可以操作任何文件
- 字符流:只能操作文本类型的文件
- 字节流基类
- 输出流基类:OutputStream
- 输入流基类:InputStream
- 字符流基类
- 输出流基类:Writer
- 输入流基类:Reader
注:字节流和字符流的子类的命名方式都是以它们的基类作为后缀名的
输出流代码实现:
分析:将“中国,你好”输出到一个文本文件中,发现更适合用字符流,但是字符流是通过字节流包装得来的,所以先要学习字节流
- public FileOutputStream(File file)创建一个向指定File对象表示的文件中写入数据的文件输出流
- public FileOutputStream(String name)创建一个向具有指定名称的文件中写入数据的输出文件流
- public void write(byte[] b)将b.length个字节从指定byte数组写入此文件输出流中
- public void write(byte[] b, int off, int len)将指定byte数组中从偏移量off开始的len个字节写入此文件输出流
- public viod close()关闭侧文件输出流并释放与此流有关的所有系统资源
package cn.edu360;
import java.io.FileOutputStream;
/**
* @author Zhang
*/
public class ClassDemo {
public static void main(String[] args){
FileOutputStream fos = null;
try {
fos = new FileOutputStream("D:\\haha.txt");
byte[] bytes = "中国,你好".getBytes();
fos.write(bytes);
fos.write(bytes, 6, 9);
fos.close();
} catch (Exception e) {
e.printStackTrace();
}finally{
if(null != fos){
try {
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
图解说明:
- public FileOutputStream(String name, boolean append):append—如果为true,则将字节写入文件末尾部,而不是文件开始部
输入流:
- public FileInputStream(File file)和指定文件建立一个读取通道
- public FileInputStream(String name)和指定文件建立一个读取通道
- public int read()从读取通道中读取一个字节,这个方法是阻塞的(意思就是如果读取到值后,后续代码才能执行,如果没有读取导致,后续代码执行不了)
- public int read(byte[] b)从输入流中读取一定数量的字节,并将其存储在缓冲区数组b中;返回值为:读入缓冲区的总字节数,如果因为已经到达流末尾而不再有数据可用,则返回-1;
代码实现:
package cn.edu360;
import java.io.FileInputStream;
/**
* @author Zhang
*/
public class ClassDemo {
public static void main(String[] args){
FileInputStream fis = null;
try {
fis = new FileInputStream("D:\\haha.txt");
int i = fis.read();
System.out.println(i);//228
i = fis.read();
System.out.println(i);//184
byte[] b = new byte[1024];
int len = fis.read(b);
System.out.println(len);//22
String result = new String(b, 0, len);
System.out.println(result);//中国,你好,你好
} catch (Exception e) {
e.printStackTrace();
}
}
}
案例展示:
1、把当前项目目录下的a.txt内容复制到当前项目目录下的b.txt中
代码实现:
package cn.edu360;
import java.io.FileInputStream;
import java.io.FileOutputStream;
/**
* @author Zhang
*/
public class ClassDemo {
public static void main(String[] args){
//先读后写
//文件字节流
FileInputStream fis = null;
FileOutputStream fos = null;
try {
fis = new FileInputStream("D:\\haha.txt");
fos = new FileOutputStream("D:\\hehe.txt");
//读的时候,需要定义一个缓冲区容器,一次读取一点
byte[] buf = new byte[1024];
//定义一个变量用于接收每次读取的字节数
int len = -1;
//循环读写
while ((len = fis.read(buf)) != -1) {
fos.write(buf, 0, len);
}
System.out.println("拷贝成功");
} catch (Exception e) {
e.printStackTrace();
}finally{
//先创建的后关闭
if(null != fos){
try {
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if(null != fis){
try {
fis.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
注意:简化上述代码的两种方式:
- 直接将后续的关闭流操作封装成方法或者封装到一个工具类里面,通过工具类名.方法名来调用
- JDK1.7新特性,可以在用完流的时候自动关闭流;在try括号里面自动用于创建流的代码才可以
简化代码如下:
package cn.edu360;
import java.io.FileInputStream;
import java.io.FileOutputStream;
/**
* @author Zhang
*/
public class ClassDemo {
public static void main(String[] args){
//先读后写
//文件字节流
try(FileInputStream fis = new FileInputStream("D:\\haha.txt");
FileOutputStream fos = new FileOutputStream("D:\\hehe.txt");) {
//读的时候,需要定义一个缓冲区容器,一次读取一点
byte[] buf = new byte[1024];
//定义一个变量用于接收每次读取的字节数
int len = -1;
//循环读写
while ((len = fis.read(buf)) != -1) {
fos.write(buf, 0, len);
}
System.out.println("拷贝成功");
} catch (Exception e) {
e.printStackTrace();
}
}
}
字节缓冲流:
- 字节缓冲输入流
- public BufferedInputStream(InputStream in)创建一个BufferedInputStream并保存其参数,即输入流in,以便将来使用。创建一个内部缓冲区数组并将其存储在buf中
- 字节缓冲输出流
- public BufferedOutputStream(OutputStream out)创建一个新的缓冲输出流,以将数据写入指定的底层输出流
代码实现:
package cn.edu360;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
/**
* @author Zhang
*/
public class ClassDemo {
public static void main(String[] args){
//先读后写
//文件字节流
try (FileInputStream fis = new FileInputStream("D:\\haha.txt");
BufferedInputStream bis = new BufferedInputStream(fis);
FileOutputStream fos = new FileOutputStream("D:\\hehe.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);){
byte[] buf = new byte[1024];
int len = -1;
while((len = bis.read(buf)) != -1){
bos.write(buf,0,len);
//写一次数据就刷一次
bos.flush();
}
System.out.println("复制成功");
} catch (Exception e) {
e.printStackTrace();
}
}
}
字符流:
使用字节流操作文本数据比较麻烦,所以就出现了字符流
字符流=字节流+编码表
编码表:就是一张可以表示文字的码表,我们现实生活中的文字和符号,计算机使不认识的,我们需要给这些文字和符号一个编码,这样计算机存储这些编号就可以了;每个国家都有不同的文字,比如录入中国的文字的编码表有GB2312/GBK/GB18030
- 转换流父类
- OutputStreamWriter是字符流通向字节流的桥梁;其中以什么编码写出的,就以什么编码查看
- InputStreamReader是字节流通向字符流的桥梁
- Charset.defaultCharset().name()获取平台默认编码
- public OutputStreamWriter(OutputStream out)创建使用默认字符编码的OutputStreamWriter
- public void write(String str)写入字符串
- public OutputStreamWriter(OutputStream out,String charseName)创建使用指定字符集的OutputStreamWriter
代码实现:
package cn.edu360;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
/**
* @author Zhang
*/
public class ClassDemo {
public static void main(String[] args) throws Exception{
FileOutputStream fis = new FileOutputStream("D:\\haha.txt");
OutputStreamWriter osw = new OutputStreamWriter(fis);
osw.write("哈哈,我使用字符流写出的!");
osw.flush();//一定要进行flush,不然没有结果,因为写入的是缓冲区
osw.close();
}
}
- public InputStreamReader(InputStream in)创建一个使用默认字符集的InputStreamReader
- public InputStreamReader(InputStream in, String charseNmae)创建使用指定字符集的InputStreamReader
- public int read(char[] cbuf)将字符读入数组,读取的字符数,如果已达到流的末尾,则返回-1
注意:文件是什么类型的编码,就用什么类型的编码读取
代码实现:
package cn.edu360;
import java.io.FileInputStream;
import java.io.InputStreamReader;
/**
* @author Zhang
*/
public class ClassDemo {
public static void main(String[] args) throws Exception{
FileInputStream in = new FileInputStream("D:\\haha.txt");
InputStreamReader isr = new InputStreamReader(in);
char[] cbuf = new char[1024];
int len = isr.read(cbuf);
String content = new String(cbuf, 0, len);
System.out.println(content);
}
}
- FileReader和FileWriter
- FileWriter是OutputStreamWriter的简化写法,FileWriter的编码方式默认就是平台的编码;如果一定要指定编码格式,只能用OutputStreamWriter
代码实现:
package cn.edu360;
import java.io.FileWriter;
/**
* @author Zhang
*/
public class ClassDemo {
public static void main(String[] args) throws Exception{
FileWriter fw = new FileWriter("D:\\haha.txt");
fw.write("哈哈,我是用FileWriter写出的");
fw.flush();
fw.close();
}
}
- FileReader是InputStreamReader的简化写法,FileReader的编码方式默认就是平台的编码;如果一定要指定编码格式,只能用InputStreamReader
- 代码实现:
package cn.edu360;
import java.io.FileReader;
/**
* @author Zhang
*/
public class ClassDemo {
public static void main(String[] args) throws Exception{
FileReader fr = new FileReader("D:\\haha.txt");
char[] cbuf = new char[1024];
int len = fr.read(cbuf);
System.out.println(new String(cbuf, 0, len));
}
}
综合案例:
package cn.edu360;
import java.io.FileReader;
import java.io.FileWriter;
/**
* @author Zhang
*/
public class ClassDemo {
public static void main(String[] args) throws Exception{
//先读后写
FileReader fr = new FileReader("D:\\haha.txt");
FileWriter fw = new FileWriter("D:\\hehe.txt");
char[] cbuf = new char[1024];
int len = -1;
while((len = fr.read(cbuf)) != -1){
fw.write(cbuf);
fw.flush();
}
fw.close();
fr.close();
System.out.println("拷贝成功");
}
}
注意事项:在windows中换行分隔符:\r\n;在Linux里面中的换行分隔符:\n
- BufferedReader和BufferedWriter
- public BufferedWriter(Writer out)创建一个使用默认大小输出缓冲区的缓冲字符输出流
- public void newLine()写入一个行分隔符。行分隔符字符串由系统属性line.separator定义,并且不一定是单个新行(‘\n’)符
代码实现:
package cn.edu360;
import java.io.BufferedWriter;
import java.io.FileWriter;
/**
* @author Zhang
*/
public class ClassDemo {
public static void main(String[] args) throws Exception{
FileWriter fw = new FileWriter("D:\\hehe.txt");
BufferedWriter bw = new BufferedWriter(fw);
bw.write("哈哈,我是通过缓冲字符输出流写出的");
bw.newLine();
bw.write("哈哈,我是通过缓冲字符输出流写出的");
bw.flush();
bw.close();
}
}
- public BufferedReader(Reader in)创建一个使用默认大小输入缓冲区的缓冲字符输入流
- public String readLine()读取一个文本行,如果没有数据可以读取了返回null
代码实现:
package cn.edu360;
import java.io.BufferedReader;
import java.io.FileReader;
/**
* @author Zhang
*/
public class ClassDemo {
public static void main(String[] args) throws Exception{
FileReader fr = new FileReader("D:\\hehe.txt");
BufferedReader br = new BufferedReader(fr);
String content = br.readLine();
System.out.println(content);//打印一行
content = br.readLine();
System.out.println(content);//打印两行
content = br.readLine();
System.out.println(content);//打印三行
}
}
IO流练习:
1、复制文本
- 使用缓冲区写出数据时,如果中途不着急将一部分数据刷新出去,可以等到最后关闭流的时候再将数据刷新出去
- 如果缓冲区存满了,缓存区将里面的数据强制刷新出去
代码实现:
package cn.edu360;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
/**
* @author Zhang
*/
public class ClassDemo {
public static void main(String[] args) throws Exception{
BufferedReader br = new BufferedReader(new FileReader("D:\\haha.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("E:\\xixi.txt"));
String len = null;
while((len = br.readLine()) != null){
bw.write(len);
bw.newLine();
}
bw.close();
br.close();
System.out.println("复制成功");
}
}
2、复制图片
代码实现:
package cn.edu360;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
/**
* @author Zhang
*/
public class ClassDemo {
public static void main(String[] args){
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:\\mm.jpg"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("E:\\nn.jpg"));){
//自定义缓冲区容器
byte[] buf = new byte[1024];
//自定义变量用于接收每次读取的字节长度
int len = -1;
//循环读取
while((len = bis.read(buf)) != -1){
//读多少写多少
bos.write(buf, 0, len);
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("拷贝成功");
}
}
3、将ArrayList集合中的字符串写入到文本文件中
代码实现:
package cn.edu360;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.util.ArrayList;
/**
* @author Zhang
*/
public class ClassDemo {
public static void main(String[] args) throws Exception{
//创建ArrayList并添加内容
ArrayList<String> list = new ArrayList<String>();
list.add("javaSe");
list.add("javaEE");
list.add("hadoop");
list.add("张明");
list.add("lili");
//创建缓冲字符流
BufferedWriter bw = new BufferedWriter(new FileWriter("D:\\list.txt"));
for (String result : list) {
bw.write(result);
bw.newLine();
}
bw.close();
System.out.println("添加成功");
}
}
4、从文本文件中读取数据(每一行为一个字符串数据)到集合中,并遍历结合
代码实现:
package cn.edu360;
import java.io.BufferedReader;
import java.io.FileReader;
import java.util.ArrayList;
/**
* @author Zhang
*/
public class ClassDemo {
public static void main(String[] args) throws Exception{
BufferedReader br = new BufferedReader(new FileReader("D:\\list.txt"));
ArrayList<String> list = new ArrayList<String>();
String line = null;
while((line = br.readLine()) != null){
list.add(line);
}
br.close();
for (String result : list) {
System.out.println(result);
}
}
}
5、复制单级文件夹
复制单级文件夹中指定文件并修改文件名称
代码实现:
package cn.edu360;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
/**
* @author Zhang
*/
public class ClassDemo {
public static void main(String[] args) throws Exception{
//复制单级文件夹
//1.封装源文件夹的文件对象
File srcFolder = new File("D:\\test123");
//2.封装要拷贝到的文件夹对象
File destFolder = new File("E:\\");
//3.在目标盘符创建一个一模一样的文件夹
destFolder = new File(destFolder, srcFolder.getName());
destFolder.mkdir();
//4.获取源文件夹中所有的子文件对象
File[] files = srcFolder.listFiles();
//遍历所有的子文件对象数组,然后拷贝到目标文件中
for (File srcFile : files) {
//在目标文件夹里面创建一个名字一模一样的文件
File destFile = new File(destFolder, srcFile.getName());
//调用拷贝文件的方法
copyFile(srcFile,destFile);
}
System.out.println("拷贝成功");
}
private static void copyFile(File srcFile, File destFile) {
try(BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFile));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFile))){
byte[] buf = new byte[1024];
int len = -1;
while((len = bis.read(buf)) != -1){
bos.write(buf, 0, len);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
6、复制多级文件夹
代码实现:
package cn.edu360;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
/**
* @author Zhang
*/
public class ClassDemo {
public static void main(String[] args) throws Exception{
//1.封装原文件夹对象
File srcFolder = new File("D:\\test123");
//2.封装目标文件夹对象
File destFolder = new File("E:\\");
//调用拷贝文件夹的方法
copyFolder(srcFolder,destFolder);
System.out.println("拷贝成功");
}
private static void copyFolder(File srcFolder, File destFolder) {
//4.判断srcFolder是不是一个标准文件
if(srcFolder.isFile()){
//4.1如果是一个标准文件就直接拷贝
//在目标文件夹中,创建有一个一模一样名字文件
File destFile = new File(destFolder, srcFolder.getName());
copyFile(srcFolder,destFile);
}else {
//4.2如果不是一个标准文件,那么就是一个文件夹
//在目标文件夹中创建一个一模一样的名字子文件夹
destFolder = new File(destFolder, srcFolder.getName());
destFolder.mkdir();
//5.获取原文件夹中所有的子文件对象
File[] files = srcFolder.listFiles();
//6.遍历子文件对象数组,再调用拷贝文件夹的方法
for (File srcFile : files) {
copyFolder(srcFile, destFolder);
}
}
}
private static void copyFile(File srcFile, File destFile) {
try(BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFile));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFile))){
byte[] buf = new byte[1024];
int len = -1;
while((len = bis.read(buf)) != -1){
bos.write(buf, 0, len);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
☞☞☞ Java序列化
- Java序列化是指把Java对象转换成字节序列的过程
- Java反序列化是指把字节序列恢复为Java对象的过程
当两个Java进程进行通信时,发送方需要把这个Java对象转换为字节序列,然后在网络上传送;另一方面,接收方面需要从字节序列中恢复出Java对象
- Java序列化:ObjectOutputStream将Java对象的基本数据类型和图形写入OutputStream
- public ObjectOutputStream(OutputStream out)创建写入指定OutputStream的ObjectOutputStream
- public final void writeObject(Object obj)将指定的对象写入ObjectOutputStream
- Java反序列化:ObjectInputStream对以前使用ObjectOutputStream写入的基本数据和对象进行反序列化
- public ObjectInputStream(InputStream in)创建从指定InputStream读取的ObjectInputStream
- public final Object readObject()从ObjectInputStream读取对象
序列化的注意事项:
- 要被序列化的对象必须实现Serializable接口
- 如果一个成员被transient修饰了,那么这个成员就不能被序列化保存
代码实现:
(1)主代码:
package cn.edu360;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
/**
* @author Zhang
*/
public class ClassDemo {
public static void main(String[] args) throws Exception{
//序列化
objectToFile();
//反序列化
fileToObject();
}
private static void fileToObject() throws Exception{
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:\\person.txt"));
Object object = ois.readObject();
System.out.println(object);
}
private static void objectToFile() throws Exception {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\\person.txt"));
oos.writeObject(new Person("张三", 18, "西安"));
oos.close();
System.out.println("成功");
}
}
(2)相关类
package cn.edu360;
import java.io.Serializable;
public class Person implements Serializable{
private String name;
private int age;
private String address;
public Person() {
}
public Person(String name, int age, String address) {
super();
this.name = name;
this.age = age;
this.address = address;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "[name=" + name + ", age=" + age + ", address=" + address
+ "]";
}
}
☞☞☞ 内存操作流
- 操作字节数组
- ByteArrayInputStream:包含一个内部缓冲区,该缓冲区包含从流 中读取的字节
- ByteArrayOutputStream:此类实现了一个输出流,其中的数据被写入一个byte数组。缓冲区会随着数组的不断写入而自动增长。可使用toByteArray()和toString()获取数据
代码实现:
package cn.edu360;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import com.sun.xml.internal.messaging.saaj.util.ByteOutputStream;
/**
* @author Zhang
*/
public class ClassDemo {
public static void main(String[] args) throws Exception{
//将一张图片转换成字节数组
byte[] byteArray = imageToByteArray();
//将一个字节数组保存成一张图片
byteArrayToImage(byteArray);
}
private static void byteArrayToImage(byte[] byteArray) throws Exception {
ByteArrayInputStream bais = new ByteArrayInputStream(byteArray);
//将字节数组保存到硬盘上一个文件图片中
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("D:\\hehe.jpg"));
//定义一个缓冲区容器
byte[] buf = new byte[1024];
int len = -1;
while((len = bais.read(buf)) != -1){
bos.write(buf, 0, len);
}
bos.close();
System.out.println("保存成功");
}
private static byte[] imageToByteArray() throws FileNotFoundException,
IOException {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:\\abc.jpg"));
ByteOutputStream baos = new ByteOutputStream();
//自定义缓冲区
byte[] buf = new byte[1024];
int len = -1;
while((len = bis.read(buf)) != -1){
//我们之前是往一个文件中去写,现在改为往一个字节数组中写
baos.write(buf, 0, len);
}
baos.close();
//将字节数组中的字节取出来
byte[] byteArray = baos.toByteArray();
return byteArray;
}
}
- 操作字符数组
- CharArrayReader
- CharArrayWrite
- 操作字符串
- StringReader
- StringWriter
注意事项:上述两个跟第一个的案例类似
加密分割和解密组成文件(很重要):
package cn.edu360;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
/**
* @author Zhang
*/
public class ClassDemo {
public static void main(String[] args) throws Exception{
//将一个文件分割成最多四份并且加密
spiltFile();
//将四个文件组合成一张图片
groupFile();
}
private static void groupFile() throws Exception {
//1.创建一个缓冲字节读取流
BufferedInputStream bis = null;
//2.创建字节数组输出流
ByteArrayOutputStream baos = new ByteArrayOutputStream();
for(int i = 0; i < 4; i++){
switch (i) {
case 0:
bis = new BufferedInputStream(new FileInputStream("D:\\temp1.dll"));
//将文件中的字节读取到字节数组中
readByteArray(bis,baos);
break;
case 1:
bis = new BufferedInputStream(new FileInputStream("D:\\temp2.dll"));
readByteArray(bis,baos);
break;
case 2:
bis = new BufferedInputStream(new FileInputStream("D:\\temp3.dll"));
readByteArray(bis,baos);
break;
case 3:
//首先判断第四个文件存不存在
File file = new File("D:\\temp4.dll");
if(file.exists()){
bis = new BufferedInputStream(new FileInputStream("D:\\temp4.dll"));
readByteArray(bis,baos);
}
break;
}
bis.close();
}
//3.将字节数组写出流中的字节数组取出来解密
byte[] byteArray = lockAndKey(baos);
//4.将字节数组保存成一个图片
ByteArrayInputStream bais = new ByteArrayInputStream(byteArray);
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("D:\\group.jpg"));
byte[] buf = new byte[1024];
int len = -1;
while((len = bais.read(buf)) != -1){
bos.write(buf, 0, len);
}
bos.close();
System.out.println("图片组合成功");
}
private static void readByteArray(BufferedInputStream bis,ByteArrayOutputStream baos) throws Exception {
byte[] buf = new byte[1024];
int len = -1;
while((len = bis.read(buf)) != -1){
baos.write(buf, 0, len);
}
}
private static void spiltFile() throws Exception {
//1.将图片转换成一个加密过后的字节数组
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:\\车.jpg"));
//2.创建一个字节数组输出流
ByteArrayOutputStream baos = new ByteArrayOutputStream();
//3.循环读写
byte[] buf = new byte[1024];
int len = -1;
while((len = bis.read(buf)) != -1){
baos.write(buf, 0, len);
}
bis.close();
//4.将字节数组输出流中的字节数组取出来并加密
byte[] byteArray = lockAndKey(baos);
//5.将字节数组最多分割成四份
//三份分割的文件保存的字节长度
int size = byteArray.length/3;
//6.将每一份数据保存到文件中
BufferedOutputStream bos = null;
for (int i = 0; i < 3; i++) {
switch (i) {
case 0:
bos = new BufferedOutputStream(new FileOutputStream("D:\\temp1.dll"));
//第一次写size字节
bos.write(byteArray, 0, size);//这样写如果文件很大的情况下,内存可能会crash
break;
case 1:
bos = new BufferedOutputStream(new FileOutputStream("D:\\temp2.dll"));
bos.write(byteArray, size, size);
break;
case 2:
bos = new BufferedOutputStream(new FileOutputStream("D:\\temp3.dll"));
bos.write(byteArray, size*2, size);
break;
}
bos.close();
}
//7.判断还有没有剩余的字节
if(size*3 < byteArray.length){
bos = new BufferedOutputStream(new FileOutputStream("D:\\temp4.dll"));
bos.write(byteArray, size*3, byteArray.length-size*3);
bos.close();
}
System.out.println("分隔成功");
}
private static byte[] lockAndKey(ByteArrayOutputStream baos) {
byte[] byteArray = baos.toByteArray();
//加密过程(采用异或)
for (int i = 0; i < byteArray.length; i++) {
byteArray[i] = (byte) (byteArray[i]^61);
}
return byteArray;
}
}