文件操作
1、压缩/解压
压缩
利用Java.util.zip包中的ZipOutputStream 实现文件的压缩
ZipOutputStream (OutputStream out) 创建新的zip输出流 void putNextEntry(ZipEntry e) 开始写入新的zip文件条目并将流定位到条目数据的开始处 条目指的是一个文件夹下的多个文件。 ZipEntry(String name) 使用指定名称创建新的zip条目 ZipIutputStream实现文件的解压 ZipIutputStream (IutputStream out) 创建新的zip输入流 ZipEntry getNextEntry()读取下一个zip条目并将流定位到该条目数据的开始处
实战
public void zip(String input, String output, String name) throws Exception {
ZipOutputStream out = new ZipOutputStream(new FileOutputStream(output));
String[] paths = input.split("\\|");
File[] files = new File[paths.length];
byte[] buffer = new byte[1024];
for (int i = 0; i < paths.length; i++) {
files[i] = new File(paths[i]);
}
for (int i = 0; i < files.length; i++) {
FileInputStream fis = new FileInputStream(files[i]);
if (files.length == 1 && name != null) {
out.putNextEntry(new ZipEntry(name));
} else {
out.putNextEntry(new ZipEntry(files[i].getName()));
}
int len;
while ((len = fis.read(buffer)) > 0) {
out.write(buffer, 0, len);
}
out.closeEntry();
fis.close();
}
out.close();
}
测试
@Test
void zip() throws Exception {
zipUtils.zip("C:\\Users\\Administrator\\Desktop\\模板.xls", "C:\\Users\\Administrator\\Desktop\\模板.zip", "1");
}
成功
解析
String input :定义的是待压缩文件的条目。
String output:定义得到的压缩文件包.zip的名字。
String name:定义压缩后的条目的名字,如果与压缩前保持一致,定义name为null即可。
解压
实战
public void unzip(String inputFile, String destDirPath) throws Exception {
File srcFile = new File(inputFile);
if (!srcFile.exists()) {
throw new Exception(srcFile.getPath() + "所指文件不存在");
}
ZipInputStream zIn = new ZipInputStream(new FileInputStream(srcFile), Charset.forName("GBK"));
ZipEntry entry = null;
File file = null;
while ((entry = zIn.getNextEntry()) != null) {
if (!entry.isDirectory()) {
file = new File(destDirPath, entry.getName());
if (!file.exists()) {
new File(file.getParent()).mkdirs();
}
OutputStream out = new FileOutputStream(file);
BufferedOutputStream bos = new BufferedOutputStream(out);
int len = -1;
byte[] buf = new byte[1024];
while ((len = zIn.read(buf)) != -1) {
bos.write(buf, 0, len);
}
bos.close();
out.close();
}
}
}
测试
@Test
void unzip() throws Exception {
zipUtils.unzip("C:\\Users\\Administrator\\Desktop\\test.zip", "C:\\Users\\Administrator\\Desktop");
}
问题
java.lang.IllegalArgumentException: MALFORMED
windows环境下,默认字符集为GBK,ZipFile默认使用UTF-8字符集,当文件名存在中文时,处理时就会报错
ZipInputStream zIn = new ZipInputStream(new FileInputStream(srcFile), Charset.forName("GBK"));
2、上传/下载
文件下载
服务类
public void logDownload(String name, HttpServletResponse response) throws Exception {
File file = new File("logs" + File.separator + name);
if (!file.exists()) {
throw new GlobalException(name + "文件不存在");
}
response.setContentType("application/force-download");
response.addHeader("Content-Disposition", "attachment;fileName=" + name);
byte[] buffer = new byte[1024];
try (FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis)) {
OutputStream os = response.getOutputStream();
int i = bis.read(buffer);
while (i != -1) {
os.write(buffer, 0, i);
i = bis.read(buffer);
}
}
}
前端控制类
@GetMapping(value = "/download/{name}")
public void logDownload(@PathVariable String name, HttpServletResponse response) throws Exception {
logService.logDownload(name, response);
}
测试
下载成功
文件上传
服务类
public void logUpload(MultipartFile file) throws Exception {
if (file == null || file.isEmpty()) {
throw new Exception("未选择需上传的日志文件");
}
String filePath = new File("src/main/resources/static/logs").getAbsolutePath();
File fileUpload = new File("src/main/resources/static/logs");
if (!fileUpload.exists()) {
fileUpload.mkdirs();
}
fileUpload = new File(filePath, file.getOriginalFilename());
if (fileUpload.exists()) {
throw new Exception("上传的日志文件已存在");
}
try {
file.transferTo(fileUpload);
} catch (IOException e) {
throw new Exception("上传日志文件到服务器失败:" + e.toString());
}
}
前端控制类
@PostMapping(value = "/upload")
public void logUpload(@RequestParam("file") MultipartFile file) throws Exception {
logService.logUpload(file);
}
HTML页面
文件上传
错误
Circular view path [test]: would dispatch back to the current handler URL [/upload/test] again. Check your ViewResolver setup! (Hint: This may be the result of an unspecified view, due to default view name generation.)
错误原因:返回页面用@Controller,要想返回数据就用@RestController
把@controller改为@RestController就可以了;
java客户端上传文件
依赖
<dependency>
<groupId>commons-httpclient</groupId>
<artifactId>commons-httpclient</artifactId>
<version>3.1</version>
</dependency>
新建客户端
@Test
public void logUpload() throws Exception {
String url = "http://127.0.0.1:8080/upload";
String pathname = new File("src/main/resources/static/logs" + File.separator + "1.log").getCanonicalPath();
logUpload(url, pathname);
}
private static void logUpload(String url, String pathname) {
HttpClient httpClient = new HttpClient();
PostMethod postMethod = new PostMethod(url);
try {
FilePart filePart = new FilePart("file", new File(pathname));
Part[] parts = {filePart};
MultipartRequestEntity multipartRequestEntity = new MultipartRequestEntity(parts, new HttpMethodParams());
postMethod.setRequestEntity(multipartRequestEntity);
httpClient.executeMethod(postMethod);
String result = postMethod.getResponseBodyAsString();
System.out.println(result);
} catch (IOException e) {
e.printStackTrace();
} finally {
postMethod.releaseConnection();
}
}
3、EasyExcel操作Excel
EasyExcel是一个基于Java的简单、省内存的读写Excel的开源项目。
官网EasyExcel
实体类
@Data
public class DemoData {
@ExcelProperty(index = 0, value = "名字")
private String name;
@ExcelProperty(index = 1, value = "时间")
private Date date;
@ExcelProperty(index = 2, value = "数字")
private Double num;
}
监听类
@Slf4j
public class DemoDataListener implements ReadListener<DemoData> {
@Override
public void invoke(DemoData demoData, AnalysisContext analysisContext) {
DemoData data = new DemoData();
BeanUtils.copyProperties(demoData, data);
log.info(data.toString());
}
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
}
}
测试类
@Test
public void simpleRead() {
String fileName = "src/main/resources/static/logs" + File.separator + "demo.xls";
EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).sheet().doRead();
}
@Test
public void simpleWrite() {
String fileName = "src/main/resources/static/logs" + File.separator + "demo.xls";
EasyExcel.write(fileName, DemoData.class).sheet("模板").doWrite(data());
}
private List<DemoData> data() {
List<DemoData> list = ListUtils.newArrayList();
for (int i = 0; i < 10; i++) {
DemoData data = new DemoData();
data.setName("字符串" + i);
data.setDate(new Date());
data.setNum(0.56);
list.add(data);
}
return list;
}
4、SpringBatch
先来粘一段spring官网的介绍
所有批处理都可以用最简单的形式描述为读取大量数据,执行某种类型的计算或转换,然后写出结果。Spring Batch 提供了三个关键接口来帮助执行批量读写: ItemReader 、ItemProcessor 和ItemWriter .
ItemReader
虽然是一个简单的概念,但它ItemReader 是从许多不同类型的输入中提供数据的方法。最普遍的例子包括:
ItemReader 是通用输入操作的基本接口,如下接口定义所示:
public interface ItemReader<T> {
T read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException;
}
该read 方法定义了ItemReader . 调用它会返回一个项目,或者null 如果没有更多项目。
ItemWriter
ItemWriter 在功能上与 ItemReader 相似,但具有逆运算。资源仍然需要定位、打开和关闭,但它们的不同之处在于 ItemWriter 写出而不是读入。在数据库或队列的情况下,这些操作可能是插入、更新或发送。输出的序列化格式特定于每个批处理作业。
与 一样ItemReader , ItemWriter 是一个相当通用的接口,如下面的接口定义所示:
public interface ItemWriter<T> {
void write(List<? extends T> items) throws Exception;
}
与read 一样write 提供了基本的合约ItemWriter 。只要它处于打开状态,它就会尝试写出传入的项目列表。
ItemStream
两者都很好ItemReaders 地ItemWriters 服务于它们各自的目的,但是它们之间有一个共同的问题,即需要另一个接口。通常,作为批处理作业范围的一部分,需要打开、关闭读取器和写入器,并且需要一种保持状态的机制。该ItemStream 接口用于此目的,如以下示例所示:
public interface ItemStream {
void open(ExecutionContext executionContext) throws ItemStreamException;
void update(ExecutionContext executionContext) throws ItemStreamException;
void close() throws ItemStreamException;
}
使用,导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-batch</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
Batch有关于数据库的操作所以要导入JDBC的场景
读平面文件
@Test
public void show() throws Exception {
FlatFileItemReader<Player> itemReader = new FlatFileItemReader<>();
itemReader.setResource(new FileSystemResource("src/main/resources/static/logs/players.txt"));
DefaultLineMapper<Player> lineMapper = new DefaultLineMapper<>();
lineMapper.setLineTokenizer(new DelimitedLineTokenizer());
lineMapper.setFieldSetMapper(new PlayerFieldSetMapper());
itemReader.setLineMapper(lineMapper);
itemReader.open(new ExecutionContext());
for (int i = 0; i < 6; i++) {
Player player = itemReader.read();
System.out.println(player);
}
}
protected static class PlayerFieldSetMapper implements FieldSetMapper<Player> {
public Player mapFieldSet(FieldSet fieldSet) {
Player player = new Player();
player.setID(fieldSet.readString(0));
player.setLastName(fieldSet.readString(1));
player.setFirstName(fieldSet.readString(2));
player.setPosition(fieldSet.readString(3));
player.setBirthYear(fieldSet.readInt(4));
player.setDebutYear(fieldSet.readInt(5));
return player;
}
}
实体类
@Data
public class Player implements Serializable {
private String ID;
private String lastName;
private String firstName;
private String position;
private int birthYear;
private int debutYear;
public String toString() {
return "PLAYER:ID=" + ID + ",Last Name=" + lastName +
",First Name=" + firstName + ",Position=" + position +
",Birth Year=" + birthYear + ",DebutYear=" +
debutYear;
}
}
文件
AbduKa00,Abdul-Jabbar,Karim,rb,1974,1996
AbduRa00,Abdullah,Rabih,rb,1975,1999
AberWa00,Abercrombie,Walter,rb, 1959,1982
AbraDa00,Abramowicz,Danny,wr,1945,1967
AdamBo00,Adams,Bob,te,1946,1969
AdamCh00,Adams,Charlie,wr,1979,2003
写平面文件
测试类
@Autowired
FlatFileItemWriter<Player> flatFileItemWriter;
@Test
public void write() throws Exception {
ArrayList<Player> list = new ArrayList<>();
Player player = new Player();
player.setID("AbduKa00");
player.setFirstName("Abdul-Jabbar");
player.setPosition("Karim");
player.setLastName("rb");
player.setBirthYear(1974);
player.setDebutYear(1996);
list.add(player);
flatFileItemWriter.open(new ExecutionContext());
flatFileItemWriter.write(list);
}
itemWriter
@Bean
public FlatFileItemWriter<Player> itemWriter() {
return new FlatFileItemWriterBuilder<Player>()
.name("itemWriter")
.resource(new FileSystemResource("src/main/resources/static/logs/players副本.txt"))
.lineAggregator(new PassThroughLineAggregator<>())
.build();
}
|