目录
-
-
- 一、从控制台输入
- 二、 获取当前代码运行的工作目录路径
- 三、判断文件、文件夹是否存在以及创建
- 四、判断文件夹下有多少个文件和文件夹
- 五、遍历获取文件夹下所有文件的路径和名称
- 六、获取文件名
- 七、获取文件大小
- 八、常用的文件信息的获取和处理方法
- 九、字节流与字符流的区别
- 十、使用字节流读写文件
- 十一、使用字符流读写文件
- 十二、输入流转化为byte数组
- 十三、java8使用Files.readAllBytes()或Files.readAllLines优雅读文本文件
- 十四、java8优雅写文件
- 十五、使用字节流复制文件
- 十六、java8使用Files.copy()复制文件
- 十七、使用IOUtils优雅操作流(字符串与InputStream的转化)
- 十八、 对象的序列化与反序列化
- 十九、使用sftp进行服务器文件上传下载
- 二十、图片大小转换
- 二十一、将图片BufferedImage转换为MultipartFile
- 二十二、文件压缩
- 二十三、InputStream、FileInputStream 转 byte[ ]
- 二十四、文本文件的InputStream、FileInputStream 转 String
- 二十五、MultipartFile或byte[]转InputStream
- 二十六、文件转byte[]
-
一、从控制台输入
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String inputStr = null;
while ((inputStr = br.readLine())!=null) {
System.out.println(inputStr);
}
或使用Scanner:
Scanner scanner = new Scanner(System.in);
String inputStr = null;
while ((inputStr = scanner.next()) != null) {
System.out.println(inputStr);
}
/* Scanner scanner = new Scanner(System.in);
String inputStr = null; //输入字符串
if (scanner.hasNextLine()) {
String str2 = scanner.nextLine();
System.out.println(str2);
}
scanner.close();*/
next()和nextLine()区别:
- 1、nextLine()以Enter为结束符,也就是说 nextLine()方法返回的是输入回车之前的所有字符。
- 2、nextLine()可以获得空格。
判断输入的是整数还是小数:
Scanner scan = new Scanner(System.in);
// 从键盘接收数据
int i = 0;
float f = 0.0f;
System.out.print("输入数字:");
if (scan.hasNextInt()) {// 判断输入的是否是整数
i = scan.nextInt();
System.out.println("整数数据:" + i);
}
if (scan.hasNextFloat()) {// 判断输入的是否是小数
f = scan.nextFloat();
System.out.println("小数数据:" + f);
}
scan.close();
二、 获取当前代码运行的工作目录路径
三、判断文件、文件夹是否存在以及创建
- 判断文件是否存在,不存在则创建
String filePth= "F:/cc/test2.txt";
File file = new File(filePth);
if(!file.exists()){
System.out.println("文件不存在");
//创建文件,如果cc文件夹不存在会报错,所有要先检查文件前的文件夹路径是否存在,不存在要先创建文件夹,最后再创建文件
file.createNewFile();
}else {
System.out.println("文件存在");
}
- 判断文件夹是否存在,不存在则创建
String filePth= "F:/test/aa/bb";//判断bb文件夹是否存在
File folder = new File(filePth);
if (!folder.exists() && !folder.isDirectory()) {
folder.mkdirs(); //如果test下连aa文件夹也没有,会连同aa一起创建
System.out.println("创建文件夹");
} else {
System.out.println("文件夹已存在");
}
四、判断文件夹下有多少个文件和文件夹
String path = "D:\\video\\";
int fileCount = 0;
int folderCount = 0;
File d = new File(path);
File list[] = d.listFiles();
for(int i = 0; i < list.length; i++){
if(list[i].isFile()){
fileCount++;
}else{
folderCount++;
}
}
System.out.println("文件个数:"+fileCount);
System.out.println("文件夹数:"+folderCount);
五、遍历获取文件夹下所有文件的路径和名称
获取绝对路径的文件名(获取的list里只有文件,没有文件夹):
public static List<String> getFilesList(String path){
List<String> list = new ArrayList<>();
File file = new File(path);
File[] tempList = file.listFiles();
for (int i = 0; i < tempList.length; i++) {
if (tempList[i].isFile()) {
list.add(tempList[i].toString());
}
}
return list;
}
测试:
String path = "D:\\video\\";
System.out.println(getFilesList(path)); //[D:\video\1.mp4, D:\video\2.mp4, D:\video\新建文本文档.txt]
获取相对路径的文件名(文件和文件夹都有):
File path = new File("D:\\ffmpegMedia\\");
//获取D:\ffmpegMedia\路径下的文件名和文件夹名
String fileNamePath[] = path.list();
for (String f : fileNamePath) {
System.out.println(f);
}
System.out.println("------------------------------------");
//获取D:\ffmpegMedia\路径下的文件名和文件夹名,返回类型为file类型
File[] files = path.listFiles();
for (File f : files) {
if (f.isFile()){
System.out.println(f.getName() + " ---> 是一个文件 " );
}
if (f.isDirectory()){
System.out.println(f.getName() + " ---> 是一个文件夹 " );
}
}
输出:
507-#网愈云故事收藏馆.mp4
aaa.mp3
pictur
temp
刻在我心底的名字-五月天.mp3
------------------------------------
507-#网愈云故事收藏馆.mp4 ---> 是一个文件
aaa.mp3 ---> 是一个文件
pictur ---> 是一个文件夹
temp ---> 是一个文件夹
刻在我心底的名字-五月天.mp3 ---> 是一个文件
list()和listFiles()区别:
- list()返回的是文件和文件夹字符串数组
- listFiles()返回的是文件和文件夹File数组,可以进行更多操作,如获取文件名、判断是否是文件等
六、获取文件名
File file = new File("F:/cc/test2.txt");
System.out.println(file.getName());//输出test2.txt
获取上传时的文件名:
String fName = file.getOriginalFilename(); //file的类型是MultipartFile
/*String fileName = fName.substring(fName.lastIndexOf("/")+1);
//或者
String fileName = fName.substring(fName.lastIndexOf("\\")+1);*/
七、获取文件大小
文件夹不适用,只能获取文件大小的整数位
public static void main(String[] args) throws IOException {
File path = new File("D:\\ffmpegMedia\\");
File[] files = path.listFiles();
for (File f : files) {
if (f.isFile()) {
System.out.println(f.getName() + " ---> 是一个文件 " + "文件大小:" + fileSize(f.length()));
}
if (f.isDirectory()) {
System.out.println(f.getName() + " ---> 是一个文件夹 "+ "文件大小:" + fileSize(f.length()));
}
}
}
/**
* 文件大小显示格式
*
* @param size
* @return
*/
private static String fileSize(long size) {
String[] units = new String[]{"B", "KB", "MB", "GB", "TB", "PB"};
double mod = 1024.0;
int i = 0;
for (i = 0; size >= mod; i++) {
size /= mod;
}
return Math.round(size) + units[i];
}
八、常用的文件信息的获取和处理方法
File file = new File("F:/test/test2.txt");
System.out.println("文件是否绝对路径:" + file.isAbsolute());
System.out.println("取得文件的根目录:" + file.getParent());
System.out.println("文件是否存在:" + file.exists());
System.out.println("是否是目录:" + file.isDirectory());
System.out.println("是否是文件:" + file.isFile());
System.out.println("是否是隐藏文件:" + file.isHidden());
System.out.println("是否可读:" + file.canRead());
System.out.println("是否可写:" + file.canWrite());
System.out.println("删除文件:" + file.delete());
/*使用renameTo进行文件重命名目录路径要一致*/
File oldName = new File("F:/test/test2.txt");//重命名前的文件
File newName = new File("F:/test/test3.txt");//重命名后的文件
System.out.println("文件重命名:" + oldName.renameTo(newName));
/*使用renameTo进行文件移动,目录路径要不一致,文件名要一致*/
File oldName = new File("F:/test/hello.txt");
File newName = new File("F:/tex/hello.txt");
System.out.println("文件移动:" + oldName.renameTo(newName));
输出:
文件是否绝对路径:true
取得文件的根目录:F:\test
文件是否存在:true
是否是目录:false
是否是文件:true
是否是隐藏文件:false
是否可读:true
是否可写:true
删除文件:true
文件重命名:true
文件移动:true
九、字节流与字符流的区别
字节流:
1.字节流在操作的时候不会用到缓冲区(也就是内存)
2.字节流可用于任何类型的对象,包括二进制对象
3.字节流处理单元为1个字节,操作字节和字节数组。
InputStream是所有字节输入流的祖先,而OutputStream是所有字节输出流的祖先。
字符流:
1.而字符流在操作的时候会用到缓冲区
2.而字符流只能处理字符或者字符串
3.字符流处理的单元为2个字节的Unicode字符,操作字符、字符数组或字符串,
Reader是所有读取字符串输入流的祖先,而writer是所有输出字符串的祖先。
在硬盘上的所有文件都是以字节形式存在的(图片,声音,视频),而字符值在内存中才会形成。
所以字符流是由Java虚拟机将字节转化为2个字节的Unicode字符为单位的字符而成的。
用字节流可以操作所有的文件,因为字节流在操作字符时,可能会有中文导致的乱码,所以由字节流引申出了字符流。图片,声音,视频等文件一般操作用字节流,文本等文件用字符流操作。
在从字节流转化为字符流时,实际上就是byte[]转化为String;
而在字符流转化为字节流时,实际上是String转化为byte[];
十、使用字节流读写文件
- 读文件
FileInputStream file = new FileInputStream("F:/test/te.txt"); //读取文件为字节流 BufferedInputStream buf = new BufferedInputStream(file); //加入缓存区 int len = 0; byte[] bys = new byte[1024]; while ((len = buf.read(bys)) != -1) { //读取逐个字节数据到字节数组,读到末尾没数据了返回-1 System.out.println(new String(bys, 0, len, "GBK")); //通过new String将字节数组转化为"GBK"编码的字符串输出 } file.close(); //关闭流 buf.close();
- 写文件
//true代表追加模式写入,没有参数true文件的内容会以覆盖形式写 FileOutputStream outputStream = new FileOutputStream("F:/test/te.txt", true); BufferedOutputStream buf = new BufferedOutputStream(outputStream); 加入缓存区 buf.write("hello".getBytes()); //hello转化为字节数组写入文件 buf.write("\n".getBytes()); //换行 buf.write(97); // 97代表字母a,将a写入文件 buf.write("\n".getBytes()); //换行 byte[] bys = {97, 98, 99, 100, 101}; buf.write(bys, 1, 3);//将98, 99, 100代表的bcd写入文件 buf.close(); //关闭流 outputStream.close();
文件最终内容:hello
a
bcd
十一、使用字符流读写文件
- 读文件
FileInputStream file = new FileInputStream("F:/test/te.txt"); //读取文件为字节流 InputStreamReader in = new InputStreamReader(file, "GBK"); //字节流转化为字符流,以GBK读取防止中文乱码 BufferedReader buf = new BufferedReader(in); //加入到缓存区 String str = ""; while ((str = buf.readLine()) != null) { //按行读取,到达最后一行返回null System.out.println(str); } buf.close(); file.close();
- 写文件
FileWriter f = new FileWriter("F:/test/te.txt", true); //文件读取为字符流,追加模式写数据 BufferedWriter buf = new BufferedWriter(f); //文件加入缓冲区 buf.write("hello"); //向缓冲区写入hello buf.write("\n"); //向缓冲区写入换行,或者采用buf.newLine(); buf.write("def"); //向缓冲区写入def buf.close(); //关闭缓冲区并将信息写入文件 f.close();
十二、输入流转化为byte数组
FileInputStream in = new FileInputStream("F:/test/te.txt");//输入流
ByteArrayOutputStream bos=new ByteArrayOutputStream();
byte[] buffer=new byte[1024];
int len=0;
while((len=in.read(buffer))!=-1){ //输入流转读取到字节数组输出流
bos.write(buffer,0,len);
}
in.close();
bos.flush();
byte[] result=bos.toByteArray(); //输出流转化成byte数组
十三、java8使用Files.readAllBytes()或Files.readAllLines优雅读文本文件
Files.readAllBytes():
byte[] data = Files.readAllBytes(Paths.get("F:/oracle_init.sql")); //获取文件转化为字节数组
String str= new String(data, StandardCharsets.UTF_8); //字节数组转化为UTF_8编码的字符串
//String str= new String(data, "GBK"); //上一行代码若有中文乱码,可改用此行代码
System.out.println(str); //输出文件内容
优化为一行代码:
String content = new String(Files.readAllBytes(Paths.get("F:/oracle_init.sql")), StandardCharsets.UTF_8);
System.out.println(content); //输出文件内容
注意:Files.readAllBytes(Path)方法把整个文件读入内存,此方法返回一个字节数组。在针对大文件的读取的时候,可能会出现内存不 足,导致堆溢出。所以大文件不推荐此方法读取。
Files.readAllLines:
List<String> lines = Files.readAllLines(Paths.get("F:/zzz.txt") , StandardCharsets.UTF_8);
lines.forEach(v-> System.out.println(v));
注意:不适用读取大文件
十四、java8优雅写文件
文本文件:
//文件不存在会自动创建,true表示在文件末尾追加形式写入,false则覆盖写入
try(PrintWriter writer = new PrintWriter(new BufferedWriter(new FileWriter("F:/ccc.txt", true)))) {
writer.println("777");
writer.println("888");
}catch (IOException e) {
System.err.println(e);
}
二进制文件(图片、音频等):
byte data[] = ...
FileOutputStream out = new FileOutputStream("F:/ccc.mp3");
out.write(data);
out.close();
十五、使用字节流复制文件
不使用缓冲区(不推荐):
FileInputStream inputStream = new FileInputStream("F:/test/te.txt"); //待复制的文件
FileOutputStream outputStream = new FileOutputStream("F:/new/te1.txt"); //要复制到的路径和文件名
byte[] bytes = new byte[1024];
int len = 0;
while ((len=inputStream.read(bytes)) != -1) { //读取待复制的文件到字节数组bytes
outputStream.write(bytes,0,len); //字节数组bytes的数据写入要复制到的文件
}
inputStream.close();
outputStream.close();
使用缓冲区(推荐):
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("F:/test/lv.mp4"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("F:/new/lv1.mp4"));
int len = 0;
byte[] bytes =new byte[1024];
while ((len=bis.read(bytes)) != -1) {
bos.write(bytes,0,len);
}
bis.close();
bos.close();
经测试使用缓冲区的复制和下面的使用Files.copy()复制速度最快,比较推荐。
十六、java8使用Files.copy()复制文件
Path source = Paths.get("F:/oracle_init.sql"); //源文件路径
File f = new File("F:/test/new.sql"); //拷贝后的文件名和路径
f.createNewFile(); //创建一个空的new.sql, 如果test目录下已经存在new.sql原来的会被覆盖。
//复制文件
Files.copy(source, new FileOutputStream(f));
十七、使用IOUtils优雅操作流(字符串与InputStream的转化)
需要导入包org.apache.commons.io
1.从流中读取数据
- 文件内容转换成List<String>
FileInputStream fileInputStream = new FileInputStream(new File("F:/test/oracle_init.sql")); //也可以用下面的FileOutputStream的构造方法获取文件,比较简洁 //FileOutputStream fileInputStream = new FileOutputStream("F:/test/oracle_init.sql"); List<String> list = IOUtils.readLines(fileInputStream, "UTF-8");//只要是InputStream流都可以,比如http响应的流 for (String str : list){ //list中每个元素是一行 System.out.println(str); }
- 文件内容转换成String
FileInputStream fileInputStream = new FileInputStream(new File("F:/test/oracle_init.sql")); String content = IOUtils.toString(fileInputStream,"UTF-8"); System.out.println(content);
- 把流转换为byte数组
FileInputStream fileInputStream = new FileInputStream(new File("F:/test/oracle_init.sql")); byte[] bytes = IOUtils.toByteArray(fileInputStream); //只要是InputStream流都可以
- byte数组转化为String
FileInputStream fileInputStream = new FileInputStream(new File("F:/test/oracle_init.sql")); byte[] bytes = IOUtils.toByteArray(fileInputStream); String str= new String(bytes, StandardCharsets.UTF_8);//若有中文乱码StandardCharsets.UTF_8改为"GBK" System.out.println(str);
- 把字符串转换为InputStream
-
InputStream 转换为 String
参考:https://stackoverflow.com/questions/309424/how-do-i-read-convert-an-inputstream-into-a-string-in-java?rq=1
2.把数据写入流
//true为追加模式再文件末尾写内容把数据写入输出流
FileOutputStream outputStream = new FileOutputStream("F:/test/te.txt", true);
IOUtils.write("abc", outputStream,"GBK");//将abc写入文件,编码格式为GBK
outputStream.close();
3.文件拷贝
FileInputStream in = new FileInputStream(new File("F:/new/lv.mp4"));
FileOutputStream out = new FileOutputStream("F:/test/lv1.mp4");
IOUtils.copy(in, out);
in.close();
out.close();
把oracle_init.sql文件内容追加到te.txt末尾:
FileInputStream in = new FileInputStream(new File("F:/oracle_init.sql"));
FileOutputStream out = new FileOutputStream("F:/test/te.txt",true);
IOUtils.copy(in, out);
in.close();
out.close();
参考:Apache Commons IO之IOUtils优雅操作流
十八、 对象的序列化与反序列化
序列化对象就是把对象转成字节数组,便于传输或存储。
反序列化对象就是将序列化后的字节数组再恢复成对象。
序列化对象方法:
/*对象转字节数组*/
public static byte[] serizlize(Object object){
ObjectOutputStream oos = null;
ByteArrayOutputStream baos = null;
try {
baos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(baos);
oos.writeObject(object);
byte[] bytes = baos.toByteArray();
return bytes;
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
if(baos != null){
baos.close();
}
if (oos != null) {
oos.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
return null;
}
序列化对象方法:
/*字节数组转对象*/
public static Object deserialize(byte[] bytes){
ByteArrayInputStream bais = null;
ObjectInputStream ois = null;
try{
bais = new ByteArrayInputStream(bytes);
ois = new ObjectInputStream(bais);
return ois.readObject();
}catch(Exception e){
e.printStackTrace();
}finally {
try {
} catch (Exception e2) {
e2.printStackTrace();
}
}
return null;
}
实例:
十九、使用sftp进行服务器文件上传下载
以下是经常用到的文件上传、下载、判断文件路径是否存在、创建文件夹、
从本地上传、从服务器上传到另一台服务器的一些实用操作。
需要用到的需要jar包:jsch-0.1.54.jar
/**
* 开启连接
*
* @param ftpUserName用户名
* @param ftpPassword服务器密码
* @param ftpHost 服务器ip
* @param ftpPort服务器端口
*
*/
public static ChannelSftp connect(String ftpUserName, String ftpPassword, String ftpHost, int ftpPort) throws Exception {
jsch = new JSch();// 创建JSch对象
session = jsch.getSession(ftpUserName, ftpHost, ftpPort);// 根据用户名、主机ip、端口号获取一个Session对象
session.setPassword(ftpPassword);// 设置密码
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);// 为Session对象设置properties
session.setTimeout(1000 * 30);// 设置超时
session.connect();// 通过Session建立连接
logger.info("Session connected.");
channel = session.openChannel("sftp"); // 打开SFTP通道
channel.connect(); // 建立SFTP通道的连接
logger.info("Connected successfully to ftpHost = " + ftpHost + ",as ftpUserName = " + ftpUserName);
return (ChannelSftp) channel;
}
/**
* 关闭连接
*/
public static void close() {
if (channel != null) {
channel.disconnect();
logger.info("关闭channel成功");
}
if (session != null) {
session.disconnect();
logger.info("关闭session成功");
}
}
/**
* 判断目录是否存在
*
@param directory文件夹路径,如:/root/test/saveFile/
*/
public static boolean isDirExist(String directory, ChannelSftp sftp) {
boolean isDirExistFlag = false;
try {
SftpATTRS sftpATTRS = sftp.lstat(directory);
isDirExistFlag = true;
return sftpATTRS.isDir();
} catch (Exception e) {
if (e.getMessage().toLowerCase().equals("no such file")) {
isDirExistFlag = false;
}
}
return isDirExistFlag;
}
/**
* 创建一个文件目录
* @throws SystemException
*
* @param createpath要创建的文件夹路径,如:/root/test/saveFile/
*/
public static void createDir(String createpath, ChannelSftp sftp) throws SftpException {
if (isDirExist(createpath,sftp)) {
}else{
String pathArry[] = createpath.split("/");
for (String path : pathArry) {
if (path.equals("")) {
continue;
}
if (isDirExist(path,sftp)) {
try {
sftp.cd(path);
} catch (SftpException e) {
e.printStackTrace();
}
if (isDirExist(createpath, sftp)) {
}
} else {
// 建立目录
sftp.mkdir(path);
// 进入并设置为当前目录
sftp.cd(path);
}
}
}
}
/**
* 删除文件
*
* @param directory
* 要删除文件所在目录
* @param deleteFile
* 要删除的文件
* @param sftp
*/
public void delete(String directory, String deleteFile, ChannelSftp sftp) {
try {
sftp.cd(directory);
sftp.rm(deleteFile);
} catch (Exception e) {
System.out.println("delete:"+e);
}
}
/**
* 文件上传
*/
public CodeNoteResponse uploadFile(MultipartFile file, String fileAddress) {
String picName = "";
// 将文件上传到临时目录
String tmpLocation = System.getProperty("user.dir") + "/sftp_file";
File tmpFile = new File(tmpLocation);
if (!tmpFile.exists()) {
tmpFile.mkdirs();
}
File dest = new File(tmpLocation + "/" + file.getOriginalFilename());
ChannelSftp sftp = null;
try {
file.transferTo(dest);
sftp = connect(ftpUserName, ftpPassword, ftpHost, Integer.valueOf(ftpPort));
createPath(fileAddress, sftp);
FileInputStream in = new FileInputStream(dest);
picName = file.getOriginalFilename();
sftp.put(in, fileAddress + "/" + picName);
} catch (IOException e) {
e.printStackTrace();
return new CodeNoteResponse().fail(-1, e.getMessage());
} catch (SftpException e) {
e.printStackTrace();
return new CodeNoteResponse().fail(-1, e.getMessage());
} finally {
close();
}
return new CodeNoteResponse<>().ok();
}
/**
* 返回服务器文件内容
*/
public String previewFile(String fileAddress, String fileName) {
ChannelSftp sftp = null;
BufferedReader bufferedReader = null;
JSONObject response = new JSONObject();
String str="";
try {
sftp = connect(ftpUserName, ftpPassword, ftpHost, Integer.valueOf(ftpPort));
sftp.cd(fileAddress);//进入指定目录操作
InputStream inputStream = null;
inputStream = sftp.get(fileName);
bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "utf-8"));
String tempString = "";
StringBuilder sb = new StringBuilder();//定义一个字符串缓存,将字符串存放缓存中
while ((tempString = bufferedReader.readLine()) != null) {
sb.append(tempString + "\n");//将读取的字符串添加换行符后累加存放在缓存中
}
str = sb.toString();
bufferedReader.close();//关闭流
} catch (SftpException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
close();
}
return str;
}
二十、图片大小转换
- 通过url 获取图片流 BufferedImage 并转换大小
try { //通过url获取BufferedImage图像缓冲区 URL img = new URL("https://img1.360buyimg.com/image/jfs/t1/38591/20/3737/314695/5cc69c01E1838df09/dd6dce681bd23031.jpg"); BufferedImage image = ImageIO.read(img); //获取图片的宽、高 System.out.println("Width: " + image.getWidth()); System.out.println("Height: " + image.getHeight()); //调整图片大小为532x532尺寸 BufferedImage newImage = resizeImage(image,532,532); //图像缓冲区图片保存为图片文件(文件不存在会自动创建文件保存,文件存在会覆盖原文件保存) ImageIO.write(newImage, "jpg", new File("F:/test/pic1.jpg")); } catch (IOException e) { e.printStackTrace(); }
resizeImage方法:
其他可能会用到的方法:
//BufferedImage图片流转byte[]数组 public static byte[] imageToBytes(BufferedImage bImage) { ByteArrayOutputStream out = new ByteArrayOutputStream(); try { ImageIO.write(bImage, "jpg", out); } catch (IOException e) { log.error(e.getMessage()); } return out.toByteArray(); } //byte[]数组转BufferedImage图片流 private static BufferedImage bytesToBufferedImage(byte[] ImageByte) { ByteArrayInputStream in = new ByteArrayInputStream(ImageByte); BufferedImage image = null; try { image = ImageIO.read(in); } catch (IOException e) { e.printStackTrace(); } return image; }
- 读取图片文件进行调整图片大小
参考:How Can I Resize an Image Using Java?try { //读取原始图片 BufferedImage image = ImageIO.read(new FileInputStream("F:/test/pic1.jpg")); System.out.println("Width: " + image.getWidth()); System.out.println("Height: " + image.getHeight()); //调整图片大小 BufferedImage newImage = resizeImage(image,200,200); //图像缓冲区图片保存为图片文件(文件不存在会自动创建文件保存,文件存在会覆盖原文件保存) ImageIO.write(newImage, "jpg", new File("F:/test/pic2.jpg")); } catch (IOException e) { e.printStackTrace(); }
二十一、将图片BufferedImage转换为MultipartFile
上面一条是将图片转为BufferedImage进行大小调整,有时候我们需要将BufferedImage转为MultipartFile进行上传等操作
方法一:
- 第一步:创建类实现MultipartFile接口
import org.springframework.web.multipart.MultipartFile; import java.io.*; public class ConvertToMultipartFile implements MultipartFile { private byte[] fileBytes; String name; String originalFilename; String contentType; boolean isEmpty; long size; public ConvertToMultipartFile(byte[] fileBytes, String name, String originalFilename, String contentType, long size) { this.fileBytes = fileBytes; this.name = name; this.originalFilename = originalFilename; this.contentType = contentType; this.size = size; this.isEmpty = false; } @Override public String getName() { return name; } @Override public String getOriginalFilename() { return originalFilename; } @Override public String getContentType() { return contentType; } @Override public boolean isEmpty() { return isEmpty; } @Override public long getSize() { return size; } @Override public byte[] getBytes() throws IOException { return fileBytes; } @Override public InputStream getInputStream() throws IOException { return new ByteArrayInputStream(fileBytes); } @Override public void transferTo(File dest) throws IOException, IllegalStateException { new FileOutputStream(dest).write(fileBytes); } }
- 第二步:转换
//读取原始图片 BufferedImage image = ImageIO.read(new FileInputStream("F:/test/pic1.jpg")); //BufferedImage转MultipartFile MultipartFile multipartFile = new ConvertToMultipartFile(imageToBytes(image), "pic1", "myPicture", "jpg", imageToBytes(image).length);
方法二:
引入依赖:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.3.2</version>
<scope>compile</scope>
</dependency>
try {
//读取图片转换为 BufferedImage
BufferedImage image = ImageIO.read(new FileInputStream("F:/test/pic1.jpg"));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write( newImage, "jpg", baos );
//转换为MultipartFile
MultipartFile multipartFile = new MockMultipartFile("pic1.jpg", baos.toByteArray());
} catch (IOException e) {
e.printStackTrace();
}
参考:How to convert BufferedImage to a MultiPart file without saving file to disk?
二十二、文件压缩
工具类:
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public class ZipUtils {
/**
*
* 文件夹压缩成ZIP
*
* @param srcDir 压缩文件夹路径
* @param out 压缩文件输出流
* @param keepDirStructure 是否保留原来的目录结构,true:保留目录结构;
*
* false:所有文件跑到压缩包根目录下(注意:不保留目录结构可能会出现同名文件,会压缩失败)
*
* @throws RuntimeException 压缩失败会抛出运行时异常
*
*/
public static void toZip(String srcDir, OutputStream out, boolean keepDirStructure)
throws RuntimeException {
long start = System.currentTimeMillis();
ZipOutputStream zos = null;
try {
zos = new ZipOutputStream(out);
File sourceFile = new File(srcDir);
compress(sourceFile, zos, sourceFile.getName(), keepDirStructure);
long end = System.currentTimeMillis();
System.out.println("压缩完成,耗时:" + (end - start) + " ms");
} catch (Exception e) {
throw new RuntimeException("zip error from ZipUtils", e);
} finally {
if (zos != null) {
try {
zos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 多文件压缩成ZIP
*
* @param imageMap 需要压缩的文件列表,键值对为 <文件名,文件的字节数组>,文件名必须包含后缀
* @param out 压缩文件输出流
* @throws RuntimeException 压缩失败会抛出运行时异常
*/
public static void toZip(Map<String, byte[]> imageMap, OutputStream out) throws RuntimeException {
long start = System.currentTimeMillis();
try (ZipOutputStream zos = new ZipOutputStream(out)) {
for (Map.Entry<String, byte[]> map : imageMap.entrySet()) {
zos.putNextEntry(new ZipEntry(map.getKey()));
zos.write(map.getValue());
zos.closeEntry();
}
long end = System.currentTimeMillis();
System.out.println("压缩完成,耗时:" + (end - start) + " ms");
} catch (Exception e) {
throw new RuntimeException("zip error from ZipUtils", e);
}
}
/**
* 多文件压缩成ZIP
* @param srcFiles 需要压缩的文件列表
* @param out 压缩文件输出流
* @throws RuntimeException 压缩失败会抛出运行时异常
*/
public static void toZip(List<File> srcFiles , OutputStream out)throws RuntimeException {
long start = System.currentTimeMillis();
try(ZipOutputStream zos= new ZipOutputStream(out)) {
for (File srcFile : srcFiles) {
byte[] buf = new byte[2048];
zos.putNextEntry(new ZipEntry(srcFile.getName()));
int len;
FileInputStream in = new FileInputStream(srcFile);
while ((len = in.read(buf)) != -1){
zos.write(buf, 0, len);
}
zos.closeEntry();
in.close();
}
long end = System.currentTimeMillis();
System.out.println("压缩完成,耗时:" + (end - start) +" ms");
} catch (Exception e) {
throw new RuntimeException("zip error from ZipUtils",e);
}
}
/**
*
* 递归压缩方法
* @param sourceFile 源文件
* @param zos zip输出流
* @param name 压缩后的名称
* @param keepDirStructure 是否保留原来的目录结构,true:保留目录结构;
*
* false:所有文件跑到压缩包根目录下(注意:不保留目录结构可能会出现同名文件,会压缩失败)
* @throws Exception
*/
private static void compress(File sourceFile, ZipOutputStream zos, String name, boolean keepDirStructure) throws Exception {
byte[] buf = new byte[2048];
if (sourceFile.isFile()) {
// 向zip输出流中添加一个zip实体,构造器中name为zip实体的文件的名字
zos.putNextEntry(new ZipEntry(name));
// copy文件到zip输出流中
int len;
FileInputStream in = new FileInputStream(sourceFile);
while ((len = in.read(buf)) != -1) {
zos.write(buf, 0, len);
}
// Complete the entry
zos.closeEntry();
in.close();
} else {
File[] listFiles = sourceFile.listFiles();
if (listFiles == null || listFiles.length == 0) {
// 需要保留原来的文件结构时,需要对空文件夹进行处理
if (keepDirStructure) {
// 空文件夹的处理
zos.putNextEntry(new ZipEntry(name + "/"));
// 没有文件,不需要文件的copy
zos.closeEntry();
}
} else {
for (File file : listFiles) {
// 判断是否需要保留原来的文件结构
if (keepDirStructure) {
// 注意:file.getName()前面需要带上父文件夹的名字加一斜杠,
// 不然最后压缩包中就不能保留原来的文件结构,即:所有文件都跑到压缩包根目录下了
compress(file, zos, name + "/" + file.getName(), keepDirStructure);
} else {
compress(file, zos, file.getName(), keepDirStructure);
}
}
}
}
}
}
- 测试:压缩多个文件(利用byte[]压缩)
import org.apache.commons.io.IOUtils; import utils.ZipUtils; import java.io.*; import java.util.HashMap; import java.util.Map; public class Test { public static void main(String[] args) { try { //读取图片转换为byte[] FileInputStream inputStream1 = new FileInputStream("F:/test/pic1.jpg"); byte[] bytes1 = IOUtils.toByteArray(inputStream1); //读取pdf转换为byte[] FileInputStream inputStream2 = new FileInputStream("F:/test/doc_20210203100237.pdf"); byte[] bytes2 = IOUtils.toByteArray(inputStream2); //读取txt转换为byte[] FileInputStream inputStream3 = new FileInputStream("F:/test/za.txt"); byte[] bytes3 = IOUtils.toByteArray(inputStream3); //三个文件存入picMap Map<String, byte[]> picMap = new HashMap<>(); picMap.put("pic1.jpg", bytes1); picMap.put("doc_20210203100237.pdf", bytes2); picMap.put("za.txt", bytes3); //定义输出流和最终生成的文件名,如;MyPic.zip FileOutputStream fileOutputStream = new FileOutputStream(new File("F:/test/MyPic.zip")); BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream); //开始压缩 ZipUtils.toZip(picMap, bufferedOutputStream); } catch (IOException e) { e.printStackTrace(); } } }
- 测试,压缩多文件文件(读取文件为byte[]压缩):
import java.io.*; import java.util.ArrayList; import utils.ZipUtils; import java.util.List; public class Test { public static void main(String[] args) { try { //要压缩的文件列表 List<File> fileList = new ArrayList<>(); fileList.add(new File("F:/test/pic1.jpg")); fileList.add(new File("F:/test/doc_20210203100237.pdf")); //压缩后的文件名和保存路径 FileOutputStream fos2 = new FileOutputStream(new File("f:/test/Myzip.zip")); //开始压缩 ZipUtils.toZip(fileList, fos2); } catch (FileNotFoundException e) { e.printStackTrace(); } } }
- 压缩文件夹
import utils.ZipUtils; import java.io.*; public class Test { public static void main(String[] args) { try { //定义输出流和最终生成的文件名,如;保存到 F盘的 MyPic.zip FileOutputStream fileOutputStream = new FileOutputStream(new File("F:/Myfolder.zip")); BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream); //开始压缩 F盘下的test文件夹 ZipUtils.toZip("F:/test", bufferedOutputStream,true); } catch (FileNotFoundException e) { e.printStackTrace(); } } }
参考:Java实现将文件或者文件夹压缩成zip
二十三、InputStream、FileInputStream 转 byte[ ]
利用Apache Commons IO包
InputStream is;
//FileInputStream is;
byte[] bytes = IOUtils.toByteArray(is);
参考:Convert InputStream to byte array in Java
二十四、文本文件的InputStream、FileInputStream 转 String
利用Apache Commons IO包
StringWriter writer = new StringWriter();
IOUtils.copy(inputStream, writer, encoding);
String theString = writer.toString();
参考:How do I read / convert an InputStream into a String in Java?
二十五、MultipartFile或byte[]转InputStream
//multipartFile获取文件byte[]
byte[] bytes = multipartFile.getBytes();
//byte[]转 InputStream
InputStream in = new ByteArrayInputStream(bytes);
二十六、文件转byte[]
方法一(使用apache.commons.io库):
File file = new File("F:/oracle_init.sql");
byte[] bytes = FileUtils.readFileToByteArray(file);
方法二:
File file = new File("F:/oracle_init.sql");
byte[] bytes = Files.readAllBytes(file.toPath());
//byte[] bytes = Files.readAllBytes(Paths.get("F:/oracle_init.sql"));
参考:
java基础io流——OutputStream和InputStream的故事(温故知新)
Java:字节流和字符流(输入流和输出流)
Java IO流操作汇总: inputStream 和 outputStream
JAVA中字符流详解
字符流与字节流的区别
使用sftp上传下载删除文件,创建文件夹