5.1 下载文件,图片
学习了如何请求图片,excel等文件,此类二进制文件无法把内容输出在console进行查看,所以请求结果必须写入文件。
在Java中写文件必须经历三个步骤:
创建文件对象 ↓ 写入内容 ↓ 关闭写入操作
打开和关闭的步骤,是为了确保同一个文件同时只能被同一个程序写,否则内容会错乱。
写入文本文件
在程序中写入字符串内容的语句
import java.io.File; import java.io.FileWriter; // 文件对象 File file = new File("foo.txt"); // 写入内容 FileWriter fileWritter = new FileWriter(file.getName()); fileWritter.write(content); // 关闭 fileWritter.close();
File是文件类,FileWriter是用来给文件写入内容的类。
写入二进制文件
当然,写入的内容不只是文本,excel等二进制文件也可以。
请求一个excel文件(网址https://style.youkeda.com/img/ham/course/py2/china-city-list.xlsx),文件数据类型是byte[].
假设文件数据的变量是byte[] data,那么写入本地文件的代码如下:
import java.io.File; import java.io.FileOutputStream; // 文件对象 File file = new File("china-city-list.xlsx"); // 写文件 FileOutputStream fos = new FileOutputStream(file); fos.write(data); // 必须刷新并关闭 fos.flush(); fos.close();
与写入文本内容不同,写入二进制内容,需要用FileOutputStream,再次强调,必须执行刷新,关闭操作。
注意:下载图片和下载其他文件别无二致,而且图片都是二进制文件。
5.2 解析excel
另一种常见的文件是excel文件
依赖库:easyexcel是操作Excel文件的库,使用前必须在pom.xml文件中加入对库的依赖。
<dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>2.1.6</version> </dependency>
调用库:
excel文件是多sheet模式的,每个sheet实际上是一个表格,表格又分为行和列,所以解析数据的路径一定是:sheet->行->列。第一个sheet、第一行、第一列的位置是0,0,0
下载了xzq_201907.xlsx文件后,解析其内容
import com.alibaba.excel.EasyExcel; import java.util.Map; import java.util.List; // 读取第一个sheet List<Map<Integer, String>> sheetDatas = EasyExcel.read("xzq_201907.xlsx").sheet(0).doReadSync(); // List 中每个元素表示一行 for (Map<Integer, String> rowData : sheetDatas) { // Map 中用序号指代每一列 for (Integer index : rowData.keySet()) { // 列值 String columnValue = rowData.get(index); } }
解析文件的第一个步骤是读取文件内容,调用EasyExcel.read()方法,传入文件名称,然后这里解析的第一个工作表,调用sheet()方法,传入参数0.最后的doRead()表示同步方式读取文件内容,返回一个读取到的内容集合List,这是一个连贯的写法。返回的List集合中,系统用Map类表示一行数据
自动转换为类
如果不能确定每一行含义,用Map表示每一列的数据,如果知道excel文件的每一列的含义,用自定义类表示会更加直观
import com.alibaba.excel.EasyExcel; import java.util.List; // 读取第一个sheet List<DemoData> sheetDatas = EasyExcel.read("xzq_201907.xlsx").head(DemoData.class).sheet(0).doReadSync();
DemoData就是自定义的类,表示一行数据,类的每个属性都表示一列的值。
Map更灵活,自定义类更直观更易理解,一般行数不太多,不会变化用自定义类。
返回值为List<DemoData>就表示把每一行都转换为一个DemoData的实例对象,放入List集合中。
// 属性定义的顺序必须与列顺序保持一致 public class DemoData { private String code1; private String city1; private String code2; private String city2; private String code3; private String city3; }
code1是第一个属性,映射excel文件第一列的值,注意excel表的列与自定义的属性,是按顺序一一对应的,不是按名称。
例:任务:
下载excel文件:
https://style.youkeda.com/img/ham/course/py2/china-city-list.xlsx
完成
com.youkeda.test.http.ExcelAsker
类,遍历其内容,当然,本文件只有一个sheet,所以只需要读取第一个sheet内容即可。
遍历结果要求::excel表格的一行内容输出到console一行中,每个单元格之间用空格隔开即可。
首先在pom.xml中添加easyexcel依赖库,然后完善com.youkeda.test.http.ExcelAsker库:
1 package com.youkeda.test.http; 2 3 4 import com.alibaba.excel.EasyExcel; 5 import com.alibaba.fastjson.JSON; 6 import java.io.File; 7 import java.io.FileOutputStream; 8 import java.io.IOException; 9 import java.util.List; 10 import java.util.Map; 11 import okhttp3.OkHttpClient; 12 import okhttp3.Request; 13 import okhttp3.Response; 14 15 public class ExcelAsker { 16 17 /** 18 * 根据输入的url,读取页面内容并返回 19 */ 20 public byte[] getFile(String url) { 21 // okHttpClient 实例 22 OkHttpClient okHttpClient = new OkHttpClient(); 23 // 定义一个request 24 Request request = new Request.Builder().url(url).build(); 25 byte[] bytes = null; 26 try { 27 // 执行请求 28 Response response = okHttpClient.newCall(request).execute(); 29 bytes = response.body().bytes(); 30 } catch (IOException e) { 31 // 抓取异常 32 System.out.println("request " + url + " error . "); 33 e.printStackTrace(); 34 } 35 36 return bytes; 37 } 38 39 public static void main(String[] args) { 40 String url = "https://style.youkeda.com/img/ham/course/py2/china-city-list.xlsx"; 41 ExcelAsker asker = new ExcelAsker(); 42 byte[] data = asker.getFile(url); 43 44 try { 45 File file = new File("china-city-list.xlsx"); 46 47 FileOutputStream fos = new FileOutputStream(file); 48 fos.write(data); 49 50 fos.flush(); 51 fos.close(); 52 53 System.out.println("下载成功"); 54 } catch (IOException e) { 55 e.printStackTrace(); 56 } 57 58 // 解析 excel 文件 59 List<Map<Integer, String>> sheetDatas = EasyExcel.read("china-city-list.xlsx").sheet(0).doReadSync(); 60 for (Map<Integer, String> rowData : sheetDatas) { 61 for (Integer index : rowData.keySet()) { 62 System.out.print(rowData.get(index) + " "); 63 } 64 System.out.println(""); 65 } 66 } 67 }