生成文件
1、生产csv文件
- 方法传递的参数分别为源数据集合,列表头map集合,文件生成路径,文件名称。
代码如下,注释的很详细:
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.beanutils.BeanUtils;
/**
* 生成为csv文件
*
* @param exportData 源数据List
* @param map csv文件的列表头map
* @param outPutPath 文件路径
* @param fileName 文件名称
* @return
*/
public static File createCsvFile(List exportData, LinkedHashMap map, String outPutPath, String fileName) {
File csvFile = null;
BufferedWriter csvFileOutputStream = null;
try {
File file = new File(outPutPath);
if (!file.exists()) {
if (file.mkdirs()) {
LOGGER.info("创建成功");
} else {
LOGGER.error("创建失败");
}
}
//定义文件名格式并创建
csvFile = File.createTempFile(fileName, ".csv", new File(outPutPath));
// UTF-8使正确读取分隔符","
csvFileOutputStream = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(csvFile), StandardCharsets.UTF_8), 1024);
// 写入文件头部
for (Iterator propertyIterator = map.entrySet().iterator();
propertyIterator.hasNext();) {
java.util.Map.Entry propertyEntry =
(java.util.Map.Entry) propertyIterator.next();
csvFileOutputStream.write(
"" + (String) propertyEntry.getValue() != null ?
(String) propertyEntry.getValue() : "" + "");
if (propertyIterator.hasNext()) {
csvFileOutputStream.write(",");
}
}
csvFileOutputStream.newLine();
// 写入文件内容
for (Iterator iterator = exportData.iterator(); iterator.hasNext();) {
Object row = (Object) iterator.next();
for (Iterator propertyIterator = map.entrySet().iterator();
propertyIterator.hasNext();) {
java.util.Map.Entry propertyEntry =
(java.util.Map.Entry) propertyIterator.next();
csvFileOutputStream.write((String) BeanUtils.getProperty(
row, (String) propertyEntry.getKey()));
if (propertyIterator.hasNext()) {
csvFileOutputStream.write(",");
}
}
if (iterator.hasNext()) {
csvFileOutputStream.newLine();
}
}
csvFileOutputStream.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (csvFileOutputStream != null) {
csvFileOutputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return csvFile;
}
- 测试代码如下:
实体
/**
* 班级总分实体
*/
@Data
public class ClassScore {
// 班级ID
private String classUid;
// 班级名称
private String className;
// 年级
private String grade;
private Integer rank;
private String rankOffset;
// 点评分数
private Integer score;
// 学段
private String stage;
private String subject;
// 班主任
private String userName;
// 班主任ID
private String userUid;
}
public static void main(String args[]) throws Exception {
List<ClassScore> resultList = new ArrayList<>();
LinkedHashMap map = new LinkedHashMap();
map.put("className", "班级");
map.put("userName", "班主任");
map.put("stage", "学段");
map.put("grade", "年级");
map.put("score", "点评分数");
String filePath = "./readFile";
String fileName = "班级氛围";
// 生成CSV文件
File file = FileUtils.createCsvFile(resultList, map, filePath, fileName);
fileName = file.getName();
System.out.println(fileName);
}
2、生成.rb或者txt文件
- 文件格式定义可用File.createTempFile实现生成.rb或.txt文件
下面的方法把生成的文件转换成了byte数组,如果不需要则删除转换为byte数组的方法,并把返回类型改成File即可。生成byte数组的方法见下文。
public byte[] createRBFile(List<List<String>> exportData, String outPutPath, String fileName) {
File rbFile = null;
BufferedWriter rbFileOutputStream = null;
try {
File file = new File(outPutPath);
if (!file.exists()) {
if (file.mkdirs()) {
LOGGER.info("创建成功");
} else {
LOGGER.error("创建失败");
}
}
//定义文件名格式并创建
rbFile = File.createTempFile(fileName, ".rb", new File(outPutPath));
rbFileOutputStream = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(rbFile), StandardCharsets.UTF_8), 1024);
// 写入数据
for (List<String> exportDatum : exportData) {
writeRow(exportDatum, rbFileOutputStream);
rbFileOutputStream.newLine();//换行
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (rbFileOutputStream != null) {
rbFileOutputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
byte[] bytes = FileToByte(rbFile);
rbFile.delete();
return bytes;
}
private void writeRow(List<String> row, BufferedWriter writer) throws IOException {
int i=0;
for (String data : row) {
writer.write(DelQuota(data));
if (i!=row.size()-1){
writer.write(",");
}
i++;
}
}
/**
* 剔除特殊字符
*
* @param str 数据
*/
public String DelQuota(String str) {
String result = str;
String[] strQuota = {"~", "!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "`", ";", "'", ",", ".", "/", ":", "/,", "<", ">", "?"};
for (int i = 0; i < strQuota.length; i++) {
if (result.indexOf(strQuota[i]) > -1)
result = result.replace(strQuota[i], "");
}
return result;
}
- 如果源数据集合是一个实体,且需要加上表头
上述方法为通用方法,实际生产中如果用实体接收源数据集合且需要加上表头,示例如下:
现有实体DeviceInfoEntity
@Data
public class DeviceInfoEntity {
//序号
private String id;
//用户名
private String username;
//容量
private String rl;
//所在区域
private String area;
//用户类型
private String userType;
//业主方
private String yzf;
//运行系统内部用户ID
private String enterId;
}
将写入数据的方法改造下即可
rbFileOutputStream.write("@序号,用户名,容量,所在区域,用户类型,业主方,运营系统内部用户ID");
rbFileOutputStream.newLine();
if(exportData.size() > 0){
for (DeviceInfoEntity exportDatum : exportData) {
writeRow(exportDatum, rbFileOutputStream);
rbFileOutputStream.newLine();
}
}else {
rbFileOutputStream.write("未查询到设备模型数据!");
rbFileOutputStream.newLine();
}
private void writeRow(DeviceInfoEntity row, BufferedWriter rbWriter) throws IOException {
rbWriter.write(row.getId() !=null && !"".equals(row.getId()) ? row.getId() : "null");
rbWriter.write(",");
rbWriter.write(row.getUsername() !=null && !"".equals(row.getUsername()) ? row.getUsername() : "null");
rbWriter.write(",");
rbWriter.write(row.getRl() !=null && !"".equals(row.getRl()) ? row.getRl() : "null");
rbWriter.write(",");
rbWriter.write(row.getArea() !=null && !"".equals(row.getArea()) ? row.getArea() : "null");
rbWriter.write(",");
rbWriter.write(row.getUserType() !=null && !"".equals(row.getUserType()) ? row.getUserType() : "null");
rbWriter.write(",");
rbWriter.write(row.getYzf() !=null && !"".equals(row.getYzf()) ? row.getYzf() : "null");
rbWriter.write(",");
rbWriter.write(row.getEnterId() !=null && !"".equals(row.getEnterId()) ? row.getEnterId() : "null");
}
一手仅为示例,具体实现按照实际业务需求。
3、创建固定名称的文件
上述创建文件的方法为File.createTempFile()方法,该方法为创建临时文件,在我们给定的文件名称后会增加后缀,如果实际业务中需要生成固定的文件名称的话,只需要将该方法替换成下列方法即可,以创建csv文件的方法为例:
// 定义文件名格式并创建
// csvFile = File.createTempFile(fileName, ".csv", new File(outPutPath));
csvFile = new File(outPutPath,fileName + ".csv");
文件转换
1、将文件转换成byte数组
/**
* 将文件转换成byte数组
* @by Duke
* @param tradeFile
* @return
*/
public static byte[] FileToByte(File tradeFile){
byte[] buffer = null;
try
{
FileInputStream fis = new FileInputStream(tradeFile);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] b = new byte[1024];
int n;
while ((n = fis.read(b)) != -1)
{
bos.write(b, 0, n);
}
fis.close();
bos.close();
buffer = bos.toByteArray();
}catch (FileNotFoundException e){
e.printStackTrace();
}catch (IOException e){
e.printStackTrace();
}
return buffer;
}
2、根据byte数组,生成文件
/**
* 根据byte数组,生成文件
* @by Duke
* @param bfile byte数组
* @param filePath 要生成的文件路径
* @param fileName 文件名称
*/
public static void ByteToFile(byte[] bfile, String filePath, String fileName) {
BufferedOutputStream bos = null;
FileOutputStream fos = null;
File file = null;
try {
File dir = new File(filePath);
if (!dir.exists() && !dir.isDirectory()) {//判断文件目录是否存在
dir.mkdirs();
}
//filePath是D:\\readFile格式,
file = new File(filePath + "\\" + fileName);
//如果filePath是./readFile,则改成 new File(./readFile/filename)
fos = new FileOutputStream(file);
bos = new BufferedOutputStream(fos);
bos.write(bfile);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (bos != null) {
try {
bos.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
if (fos != null) {
try {
fos.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
文件读取
1、读取文件内容
/**
* 读取file文件内容
* @by Duke
* @param fileName 文件路径
* @return String字符串,每行按【分号】分割
*/
public static String readFileContent(String fileName) {
File file = new File(fileName);
BufferedReader reader = null;
StringBuffer sbf = new StringBuffer();
try {
reader = new BufferedReader(new FileReader(file));
String tempStr;
while ((tempStr = reader.readLine()) != null) {
sbf.append(tempStr+";");
}
reader.close();
return sbf.toString();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
return sbf.toString();
}
文件下载
1、下载csv文件
需要注意的是要追加BOM标识,否则用office打开的csv文件会乱码。
/**
* 下载文件
*
* @param response
* @param csvFilePath
* 文件路径
* @param fileName
* 文件名称
* @throws IOException
*/
public static void exportFile(HttpServletResponse response,
String csvFilePath, String fileName) throws IOException {
FileInputStream in = null;
OutputStream out = response.getOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
response.setContentType("text/csv;charset=UTF-8");
response.setHeader("Content-Disposition", "attachment;filename="
+ URLEncoder.encode(fileName, "UTF-8"));
response.setCharacterEncoding("UTF-8");
// 追加BOM标识,否则下载的csv文件用office打开会乱码
out.write(0xef);
out.write(0xbb);
out.write(0xbf);
File file = new File(csvFilePath,fileName);
try {
in = new FileInputStream(file);
while ((len = in.read(buffer)) > 0) {
out.write(buffer, 0, len);
}
out.flush();
} catch (FileNotFoundException e) {
LOGGER.error("获取文件错误!");
} finally {
if (in != null) {
try {
in.close();
out.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}
文件删除
1、删除单个文件
/**
* 删除单个文件
*
* @param filePath 文件目录路径
* @param fileName 文件名称
*/
public static void deleteFile(String filePath, String fileName) {
File file = new File(filePath);
if (file.exists()) {
File[] files = file.listFiles();
for (int i = 0; i < files.length; i++) {
if (files[i].isFile()) {
if (files[i].getName().equals(fileName)) {
files[i].delete();
return;
}
}
}
}
}
2、删除目录下的所有文件
/**
* 删除该目录filePath下的所有文件
*
* @param filePath 文件目录路径
*/
public static void deleteFiles(String filePath) {
File file = new File(filePath);
if (file.exists()) {
File[] files = file.listFiles();
for (int i = 0; i < files.length; i++) {
if (files[i].isFile()) {
files[i].delete();
}
}
}
}
3、删除目录(文件夹)以及目录下的文件(包括子目录)
/**
* 删除目录(文件夹)以及目录下的文件
*
* @param dir 被删除目录的文件路径
* @return 目录删除成功返回true, 否则返回false
*/
public static boolean deleteDirectory(String dir) {
// 如果dir不以文件分隔符结尾,自动添加文件分隔符
if (!dir.endsWith(File.separator)) {
dir = dir + File.separator;
}
File dirFile = new File(dir);
// 如果dir对应的文件不存在,或者不是一个目录,则退出
if (!dirFile.exists() || !dirFile.isDirectory()) {
LOGGER.info("删除目录失败" + dir + "目录不存在!");
return false;
}
boolean flag = true;
// 删除文件夹下的所有文件(包括子目录)
File[] files = dirFile.listFiles();
for (int i = 0; i < files.length; i++) {
// 删除子文件
if (files[i].isFile()) {
flag = deleteFile(files[i].getAbsolutePath());
if (!flag) {
break;
}
}
// 删除子目录
else {
flag = deleteDirectory(files[i].getAbsolutePath());
if (!flag) {
break;
}
}
}
if (!flag) {
LOGGER.info("删除目录失败");
return false;
}
// 删除当前目录
if (dirFile.delete()) {
LOGGER.info("删除目录" + dir + "成功!");
return true;
} else {
LOGGER.info("删除目录" + dir + "失败!");
return false;
}
}
4、删除文件夹
/**
* 删除文件夹
* @param folderPath 文件夹完整绝对路径
*/
public static void delFolder(String folderPath) {
try {
delAllFile(folderPath); // 删除完里面所有内容
String filePath = folderPath;
filePath = filePath.toString();
java.io.File myFilePath = new java.io.File(filePath);
myFilePath.delete(); // 删除空文件夹
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 删除指定文件夹下所有文件
* @param path 文件夹完整绝对路径
* @return
*/
public static boolean delAllFile(String path) {
boolean flag = false;
File file = new File(path);
if (!file.exists()) {
return flag;
}
if (!file.isDirectory()) {
return flag;
}
String[] tempList = file.list();
File temp = null;
for (int i = 0; i < tempList.length; i++) {
if (path.endsWith(File.separator)) {
temp = new File(path + tempList[i]);
} else {
temp = new File(path + File.separator + tempList[i]);
}
if (temp.isFile()) {
temp.delete();
}
if (temp.isDirectory()) {
delAllFile(path + "/" + tempList[i]);// 先删除文件夹里面的文件
delFolder(path + "/" + tempList[i]);// 再删除空文件夹
flag = true;
}
}
return flag;
}