一、说明
今天,项目现场提出这样一种需求:项目中,将项目文件打成zip包进行发布时,由于安全机制的限制,不允许发布二进制文件,因此需要将.zip格式的二进制文件encode成文本文件,再将文本文件上传后decode成.zip格式。
二、直接上代码
1、首先上传统IO实现方式
package com.mzj.pe.codec;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* @Auther: mazhongjia
* @Date: 2020/9/17 11:26
* @Version: 1.0
*/
public interface BinaryTextCodec {
String encode(FileInputStream fileInputStream) throws IOException;
void decode(FileOutputStream outputStream, String text) throws IOException;
public static BinaryTextCodec createBinaryTextCodec(){
return new BinaryTextCodecImpl();
}
}
package com..mzj.pe.codec;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* @Auther: mazhongjia
* @Date: 2020/9/17 11:28
* @Version: 1.0
*/
public class BinaryTextCodecImpl implements BinaryTextCodec {
private static final String TEXT_SPLIT_CHAR = ",";
@Override
public String encode(FileInputStream fileInputStream) throws IOException {
if (fileInputStream == null) {
return null;
}
StringBuilder builder = new StringBuilder();
int i = 0;
while ((i = fileInputStream.read()) != -1) {
builder.append(i + TEXT_SPLIT_CHAR);
}
return builder.toString();
}
@Override
public void decode(FileOutputStream fileOutputStream, String text) throws IOException {
if (fileOutputStream == null || text == null) {
return;
}
String[] lineone = text.split(TEXT_SPLIT_CHAR);
for (int j = 0; j < lineone.length; j++) {
fileOutputStream.write(Integer.valueOf(lineone[j]));
}
fileOutputStream.flush();
}
}
package com.mzj.pe.codec;
import java.io.*;
/**
* @Auther: mazhongjia
* @Date: 2020/9/17 13:55
* @Version: 1.0
*/
public class FileTransitionUtil {
private static BinaryTextCodec binaryTextCodec = BinaryTextCodec.createBinaryTextCodec();
public static void binaryToText(String binaryFilePath, String textFilePath) throws IOException {
File binaryFile = new File(binaryFilePath);
if (!binaryFile.exists()) {
System.out.println("转换的二进制文件不存在....");
return;
}
File textFile = new File(textFilePath);
if (!textFile.exists())
textFile.createNewFile();
FileInputStream fileInputStream = null;
BufferedWriter bufferedWriter = null;
try {
fileInputStream = new FileInputStream(binaryFile);
bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(textFile)));
String encoder = binaryTextCodec.encode(fileInputStream);
if (encoder != null) {
bufferedWriter.write(encoder);
bufferedWriter.flush();
System.out.println("成功将【"+binaryFilePath+"】转换成文本文件【"+textFilePath+"】");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fileInputStream != null) {
try {
fileInputStream.close();
} catch (IOException ie) {
ie.printStackTrace();
}
}
if (bufferedWriter != null) {
try {
bufferedWriter.close();
} catch (IOException ie) {
ie.printStackTrace();
}
}
}
}
public static void textToBinary(String binaryFilePath, String textFilePath) throws IOException {
File textFile = new File(textFilePath);
if (!textFile.exists()) {
System.out.println("转换的文本文件不存在....");
return;
}
File binaryFile = new File(binaryFilePath);
if (!binaryFile.exists())
binaryFile.createNewFile();
FileOutputStream fileOutputStream = null;
BufferedReader bufferedReader = null;
try {
fileOutputStream = new FileOutputStream(binaryFile);
bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(textFile)));
binaryTextCodec.decode(fileOutputStream, bufferedReader.readLine());
System.out.println("成功将【"+textFilePath+"】转换成二进制文件【"+binaryFilePath+"】");
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fileOutputStream != null) {
try {
fileOutputStream.close();
} catch (IOException ie) {
ie.printStackTrace();
}
}
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException ie) {
ie.printStackTrace();
}
}
}
}
}
package com.mzj.pe.codec;
import java.io.IOException;
/**
* @Auther: mazhongjia
* @Date: 2020/9/17 14:15
* @Version: 1.0
*/
public class Demo {
public static void main(String[] args) throws IOException {
FileTransitionUtil.binaryToText("D:\\埃及项目画面说明.doc","D:\\1.txt");
FileTransitionUtil.textToBinary("D:\\1.doc","D:\\1.txt");
FileTransitionUtil.binaryToText("D:\\专题图演示视频.mp4","D:\\2.txt");
FileTransitionUtil.textToBinary("D:\\2.mp4","D:\\2.txt");
FileTransitionUtil.binaryToText("D:\\17年餐费未报销.zip","D:\\3.txt");
FileTransitionUtil.textToBinary("D:\\3.zip","D:\\3.txt");
}
}
2、然后我自己又用NIO实现了一版
package com.mzj.pe.codec.test;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
/**
* @Auther: mazhongjia
* @Date: 2020/9/17 14:57
* @Version: 1.0
*/
public class Text {
public static void main(String[] args) throws Exception {
Path pathIn = Paths.get("D://原始二进制文件.zip");
Path pathOut = Paths.get("D://1.txt");
FileChannel inputChannel = FileChannel.open(pathIn, StandardOpenOption.READ);
FileChannel outputChannel =FileChannel.open(pathOut,StandardOpenOption.WRITE);
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
while (true){
byteBuffer.clear();
int read = inputChannel.read(byteBuffer);
if(-1 == read){//此处用-1判断是否读完需要依赖上面的 byteBuffer.clear();
//文件读完了
break;
}
//读到文件中内容了,翻转缓冲区,准备get其中数据
byteBuffer.flip();//本例中从ByteBuffer获取数据没有显示的get,而是将其作为参数传给另一个Channel的write方法,但是也是读其中的数据,所以也要进行翻转
StringBuilder builder = new StringBuilder();
while (byteBuffer.hasRemaining()){
builder.append(byteBuffer.get()+",");//1、将bytebuffer中数据,以字节形式取出,每个字节后追加逗号,形成字符串,以便解析字符串时时按,分割还原字节
}
CharBuffer charBuffer = CharBuffer.allocate(builder.length());//2、定义一个上面生成字符串长度的ChatBuffer
charBuffer.put(builder.toString());//3、将字符串写入CharBuffer(A,B,C,D....)
charBuffer.flip();
Charset charset= Charset.defaultCharset();//4、将CharBuffer数据准备写入outputChannel,写入之前,需要转换成ByteBuffer,转换时需要按照特定字符集编码形式进行转换
ByteBuffer byteBuffe1r=charset.encode(charBuffer);
// byteBuffe1r.flip();
outputChannel.write(byteBuffe1r);//将byteBuffer中内容写入到Channel中//5、将CharBuffer的ByteBuffer数组写入outputChannel
// outputChannel.write(byteTemp);//将byteBuffer中内容写入到Channel中
}
inputChannel.close();
outputChannel.close();
}
}
package com.mzj.pe.codec.test;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.List;
/**
* @Auther: mazhongjia
* @Date: 2020/9/17 14:57
* @Version: 1.0
*/
public class Text2 {
public static void main(String[] args) throws Exception {
Path pathIn = Paths.get("D://1.txt");
Path pathOut = Paths.get("D://1.zip");
FileChannel inputChannel = FileChannel.open(pathIn, StandardOpenOption.READ);
FileChannel outputChannel =FileChannel.open(pathOut,StandardOpenOption.WRITE);
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
List<Byte> byteList = new ArrayList<>();
while (true){
byteBuffer.clear();
int read = inputChannel.read(byteBuffer);
if(-1 == read){//此处用-1判断是否读完需要依赖上面的 byteBuffer.clear();
//文件读完了
break;
}
//读到文件中内容了,翻转缓冲区,准备get其中数据
byteBuffer.flip();//本例中从ByteBuffer获取数据没有显示的get,而是将其作为参数传给另一个Channel的write方法,但是也是读其中的数据,所以也要进行翻转
while(byteBuffer.hasRemaining()){
byteList.add(byteBuffer.get());
}
}
byte[] bytes = new byte[byteList.size()];
for (int ii=0;ii<bytes.length;ii++){
bytes[ii] = byteList.get(ii);
}
//1、这里的data,是A,B,C...的字符串形式,也就是原始二进制文件的byte数组的字符串逗号分割形式
String data = new String(bytes,Charset.defaultCharset());//这一步是通过文本的字节数组形式,获取文本内容//2、将文本文件中字节还原成A,B,C,....形式,这里相当于decode,解码字符集要与编码保持一致
//3、下面是还原原二进制文件的字节数组:byte2s
String[] dataspliet = data.split(",");
byte[] byte2s = new byte[dataspliet.length];
for (int ii=0;ii<byte2s.length;ii++){
byte2s[ii] = Byte.valueOf(dataspliet[ii]);
}
//4、下面是根据原二进制文件字节数组封装ByteBuffer
ByteBuffer byteBufferWrite = ByteBuffer.allocate(byte2s.length);
byteBufferWrite.put(byte2s);
byteBufferWrite.flip();
//5、将字节数组写入outputChannel
outputChannel.write(byteBufferWrite);//将byteBuffer中内容写入到Channel中
// outputChannel.write(byteTemp);//将byteBuffer中内容写入到Channel中
inputChannel.close();
outputChannel.close();
}
}