一、实验概述

大数据计算服务(MaxCompute,原名 ODPS)是一种快速、完全托管的 GB/TB/PB 级数据仓库解决方案。MaxCompute 向用户提供了完善的数据导入方案以及多种经典的分布式计算模型,能够更快速的解决用户海量数据计算问题,有效降低企业成本,并保障数据安全。

本实验结合实际数据和案例,深入浅出的演示了如何使用MaxCompute的内置数据传输功能,详细介绍tunnel数据传输命令及通过tunnel JAVA SDK 定制开发数据传输服务功能。

二、实验目标

   本实验通过控制台Data IDE和客户端两种方式进行实验,掌握不同的数据传输操作命令,以及相关注意事项。

完成此实验后,可以掌握的能力有:

  1. tunnel 数据传输命令的基本操作;

2. tunnel JAVA SDK 定制开发数据传输服务;

三、学习建议

  1. 掌握MaxCompute的内置的数据传输功能以及相关命令的基础操作;

2. 提前安装 ODPS客户端(下载客户端软件)

第 1 章:实验准备

1.1 申请MaxCompute资源

在弹出的左侧栏中,点击 创建资源 按钮,开始创建实验资源。
资源创建过程需要1-3分钟。完成实验资源的创建后,用户可以通过 实验资源 查看实验中所需的资源信息,例如:阿里云账号等。

1.2 准备测试账号

该实验需要和其他同学配合完成,请找到一个可以和你互相配合的同学,下文中会提到A用户、B用户,其中A用户即为你本人使用的阿里云的账号,B用户为和你配合的同学的阿里云账号;

实验中两个账户均使用的是阿里云主账号(或者具有项目admin权限的用户),可在两台电脑中登录,亦或使用同一台电脑里两个不同的浏览器打开,或一个使用浏览器打开,另一个使用odpscmd客户端;

为方便区别相关的账号操作,下述实验过程中A账号的操作记录均采用的命令行的方式进行操作截图,账号B的操作记录均使用页面浏览器的操作截图;

实验中的配置文件、文件路径、账号、项目名称、授权表等,均需根据具体的项目进行修改。

1.3 资源环境准备

1)请点击页面左侧的实验资源,在左侧栏中,查看本次实验资源信息。如图案例:

【实验】阿里云大数据助理工程师认证(ACA)-  ACA认证配套实验-06-MaxCompute 数据传输_java


2)点击“实验资源”,查看所需具体资源,如图案例:

3)在弹出的左侧栏中,点击 创建资源 按钮,开始创建实验资源。

  注意:由于实验环境一旦开始创建则进入计时阶段,建议学员先基本了解实验具体的步骤、目的,真正开始做实验时再进行创建

4)创建资源,如图案例:(创建资源需要几分钟时间,请耐心等候……)资源创建成功,如图案例:(注意资源中的项目名称、子用户名称、子用户密码、AK ID、AK Secret信息)

1.4 进入实验环境

1、登录控制台

1)点击“前往控制台”

注意:此实验界面为使用者提供了进入实验的用户名称,如 u-bcofvgpr 以及登录密码,请先记录下来,密码需要鼠标点击直接拷贝下来,以及使用其他工具的 AK ID 以及 AK Secret 秘钥对 ,项目名称等信息。将AK ID 和 AK Secret配置在安装的客户端的配置文件中。

2)输入用户名

3)点击下一步,输入密码:(刚才实验环境创建时所提供)

4)进入控制台界面

5) 点击 “大数据(数加)”进入大数据开发控制台

6) 点击”大数据开发套件”进入工作区界面

7)点击“进入工作区”,进入工作环境(首次进入显示每个菜单的帮助信息)

8) 点击“跳过”或逐个菜单看看,最终显示

9)点击“新建脚本”设置实验临时文件

【实验】阿里云大数据助理工程师认证(ACA)-  ACA认证配套实验-06-MaxCompute 数据传输_客户端_02


10)设置文件名称、类型(选择ODPS SQL)、描述信息(建议非必须)、文件保存目录信息,点击“提交”进入SQL操作环境

【实验】阿里云大数据助理工程师认证(ACA)-  ACA认证配套实验-06-MaxCompute 数据传输_客户端_03


2、配置客户端

1)如果为提前安装客户端,请参考下面网址进行安装:

(https://help.aliyun.com/document_detail/27971.html?spm=5176.doc27834.6.730.xbOX5m)

【实验】阿里云大数据助理工程师认证(ACA)-  ACA认证配套实验-06-MaxCompute 数据传输_客户端_04


3)解压安装

4)配置客户端文件,在XXX(个人目录)\odpscmd_public\conf\,打开文件 odps_config.ini,修改配置信息;即将上述实验资源中提供的AK ID 以及 AK Secret 和项目名称分别填写在上述配置文件中,其他信息不变,如图:

5) 检查测试即通过命令行,进入\ODPS_DEMO\odpscmd_public\bin\,执行 odpscmd,进入交互界面,确认安装是否配置成功。案例如图:

执行后进入如下界面:(测试案例项目为bigdata_train)

6) 通过创建一个数据表测试:

        ------输入语句创建表dual 

create table dual (X string);

------数据表中插入一条记录并检查

insert into table dual select count(*) from dual;

【实验】阿里云大数据助理工程师认证(ACA)-  ACA认证配套实验-06-MaxCompute 数据传输_java_05


------检查插入结果

        select * from dual;

1.5 安装配置最新odpscmd 客户端

步骤1:客户端介质下载 (参考地址)

​https://help.aliyun.com/document_detail/27971.html?spm=5176.doc27833.2.1.b6nngs​​ 步骤2:解压odpscmd_public.zip 到本目录,如:解压至本地目录 E:\ ODPS_DEMO \odpscmd_public

步骤3:查看本次实验课用到的介质,可以看到如下的文件夹:
步骤4:在conf文件夹中有odps_config.ini文件。编辑此文件,填写相关信息:

project_name=<自己的项目名称>

access_id=<自己的项目生成的访问ID , www.aliyun.com网站上申请到的access_id>

access_key=<自己的项目生成的访问ID的密钥信息,即 www.aliyun.com网站上申请access_key>

end_point=http://service.odps.aliyun.com/api (tunnel JAVA SDK 需要)

tunnel_endpoint=http://dt.odps.aliyun.com (tunnel JAVA SDK 需要)

log_view_host=http://logview.odps.aliyun.com (默认)

https_check=true (默认)

注意: [在申请资源部分可获取实验所需的项目名称、所需的access_id(AK ID) 、access_key(AK Secre)等信息 ] 如下图开通资源后所示:步骤5:修改好配置文件后运行bin目录下的odpscmd(在Linux系统下是./bin/odpscmd,Windows下运行./bin/odpscmd.bat),现在可以运行 MaxCompute 命令,如:
注意:项目可以随时根据情况切换,上图表示环境设置成功.

将 E:\ODPS_DEMO\odpscmd_public\bin 加入环境变量 PATH,方便通过命令行调用 odpscmd

【实验】阿里云大数据助理工程师认证(ACA)-  ACA认证配套实验-06-MaxCompute 数据传输_客户端_06

1.5 下载配套实验材料

(1) 下载本实验所用到的介质包:

下载附件,将ODPS_DEMO.zip解压至本地目录 E:\ODPS_DEMO,解压密码为:aca21104

(2) 查看本次实验课用到的介质:

 dir E:\ODPS_DEMO\Resources\02-DataTransfer     (注意里面包含建表脚本文件和实验数据文件)

至少应该包含以下文件:

【实验】阿里云大数据助理工程师认证(ACA)-  ACA认证配套实验-06-MaxCompute 数据传输_客户端_07


(3) 检查系统是否安装了Java运行环境(1.6及以上版本):

(4) 检查是否安装了eclipse,建议使用 luna-sr2 版本;

说明:目前高版本的Eclipse Neon有可能会导致插件加载失败,请使用Eclipse Luna版本。(下载地址:http://www.eclipse.org/downloads/packages/release/luna/sr2)
(5) 使用实验账号,登录阿里云官网,检查账号下的可用资源:

应至少包括 大数据计算 服务;

如无项目,请新建一个项目用于本次实验,本实验中使用项目名称为 IDE;

检查可用 AccessKeyID 和 AccessKeySecret,并记录一对用于后续实验;

第 2 章:tunnel 数据传输命令基本操作

2.1 tunnel upload 目标为单表

注意本节实验首先保证表t_tunnel 必须已经创建完成,如果没有,请参考如下语句创建:

 drop table if exists t_tunnel; 

create table t_tunnel (id int, name string);

(1) 使用 upload 子命令,上传文件 people.csv 到表 t_tunnel 中:

tunnel upload E:\ODPS_DEMO\resources\02-DataTransfer\people.csv t_tunnel;

【实验】阿里云大数据助理工程师认证(ACA)-  ACA认证配套实验-06-MaxCompute 数据传输_eclipse_08


(2) 检查上传结果:

read t_tunnel;

(3) 再上传一遍,验证一下tunnel 上传数据的方式是 append 还是 overwrite:

tunnel upload E:\ODPS_DEMO\resources\02-DataTransfer\people.csv t_tunnel;

read t_tunnel;

上述结果表明tunnel upload操作为append操作不是overwrite操作

2.2 tunnel upload 目标为分区表

本节实验首先保证表t_tunnel_p存在,若不存在,请参考下面语句处理(或直接重新创建表t_tunnel_p):

                     drop table if exists t_tunnel_p;

create table t_tunnel_p (id int, name string) partitioned by (gender string);

(1) 创建表 t_tunnel_p 的分区 gender='male’中:

alter table t_tunnel_p add if not exists partition (gender='male');

(2) 使用 upload 子命令,上传文件 men.csv 以及 women.csv 到表 t_tunnel_p 的已存在的分区 gender='male’中

tunnel upload E:\ODPS_DEMO\resources\02-DataTransfer\women.csv t_tunnel_p/gender='male';

tunnel upload E:\ODPS_DEMO\resources\02-DataTransfer\men.csv t_tunnel_p/gender='male';

(3) 检查表 t_tunnel_p 中的内容,体会一下分区内容和标称值的逻辑关系:

read t_tunnel_p;

向同一个分区装载不同文件时,两个文件的内容append到一起了

2.3 tunnel upload 源文件为目录

本节实验首先保证表t_tunnel存在,否则参照下面操作新建表t_tunnel ;

drop table if exists t_tunnel;

create table t_tunnel (id int, name string);

(1) 将目录E:\ODPS_DEMO\resources\02-DataTransfer\famous_people\ 下的所有文件都上传到 t_tunnel 中去:

truncate table t_tunnel;

tunnel upload E:\ODPS_DEMO\resources\02-DataTransfer\famous_people\ t_tunnel;

(2) 检查上传结果:

read t_tunnel;

2.4 tunnel upload 容忍错误记录
注意表t_tunnel已经存在,否则,可单独创建:

drop table if exists t_tunnel;

create table t_tunnel (id int, name string);

(1) 将文件E:\ODPS_DEMO\resources\02-DataTransfer\people_bad.csv上传至t_tunnel:

truncate table t_tunnel;

tunnel upload E:\ODPS_DEMO\resources\02-DataTransfer\people_bad.csv t_tunnel;

read t_tunnel;

默认情况下,不允许有错误数据,如果有则抛出错误,数据装载失败

(2) 指定容忍错误的参数 -dbr 为 true:

truncate table t_tunnel;

tunnel upload E:\ODPS_DEMO\resources\02-DataTransfer\people_bad.csv t_tunnel -dbr true;

read t_tunnel;

指定容易错误的参数 -dbr 为ture 后,错误的数据不会被装载,正确的数据会被装载,如上图,记录ID为10的记录为错误数据没有被装载上

2.5 tunnel upload 扫描文件

t_tunnel建表参考:

drop table if exists t_tunnel;

create table t_tunnel (id int, name string);

欲将文件E:\ODPS_DEMO\resources\02-DataTransfer\crawd.csv上传至t_tunnel,可以在上传前先做个预扫描

tunnel upload E:\ODPS_DEMO\resources\02-DataTransfer\crawd.csv t_tunnel --scan=only;

2.6 tunnel upload 行、列分隔符

本节实验首先保证表t_tunnel存在,若不存在,请参考下面语句处理(或直接重新创建表t_tunnel):

                   drop table if exists t_tunnel;

create table t_tunnel (id int, name string);

将文件E:\ODPS_DEMO\resources\02-DataTransfer\people_delimeter.csv文件上传到 t_tunnel 中去:

truncate table t_tunnel;

tunnel upload E:\ODPS_DEMO\resources\02-DataTransfer\people_delimiter.csv t_tunnel -fd || -rd &;

read t_tunnel;

指定数据文件的列分隔符 –fd || , 行分隔符 –rd &

2.7 tunnel upload多线程

本节实验首先保证表t_tunnel存在,若不存在,请参考下面语句处理(或直接重新创建表t_tunnel):

drop table if exists t_tunnel;

create table t_tunnel (id int, name string);

使用多个线程将文件E:\ODPS_DEMO\resources\02-DataTransfer\crawd.csv文件上传到 t_tunnel 中去:

truncate table t_tunnel;

tunnel upload E:\ODPS_DEMO\resources\02-DataTransfer\crawd.csv t_tunnel -threads 8;

read t_tunnel;

count t_tunnel;

当数据文件较大地,可以通过-threads N 指定N个线程同时进行装载,加快速度

2.8 tunnel download 非分区表

将表 t_tunnel 下载到本地文件 t_tunnel.csv

tunnel download t_tunnel t_tunnel.csv;

数据下载当前路径下,可以指定导出文件的具体路径,指定path\t_tunnel.csv 即可 path 根据自己的机器情况指定

2.9 tunnel download 分区表

将表 t_tunnel_p 下载到本地文件 t_tunnel_p.csv

tunnel download t_tunnel_p/gender='male' t_tunnel_p.csv;

第 3 章:tunnel JAVA SDK 定制开发数

3.1 安装配置eclipse开发环境

首先,解压下载的eclipse-java-luna-SR2-win32-x86_64.zip到E:\ODPS_DEMO,然后执行以下操作:

(1) 将E:\ODPS_DEMO\InstallMedia\odps-eclipse-plugin-bundle-0.16.0.jar 拷贝至目录E:\ODPS_DEMO\eclipse\plugins

【实验】阿里云大数据助理工程师认证(ACA)-  ACA认证配套实验-06-MaxCompute 数据传输_eclipse_09


(2) 执行E:\ODPS_DEMO\eclipse\eclipse.exe,打开 eclipse,点击 New -> Other

(3) 配置 odps

【实验】阿里云大数据助理工程师认证(ACA)-  ACA认证配套实验-06-MaxCompute 数据传输_客户端_10


【实验】阿里云大数据助理工程师认证(ACA)-  ACA认证配套实验-06-MaxCompute 数据传输_eclipse_11


(4) 指定 JavaProject Name:

【实验】阿里云大数据助理工程师认证(ACA)-  ACA认证配套实验-06-MaxCompute 数据传输_eclipse_12

3.2 单线程上传文件

此部分建表语句参考:

drop table if exists t_tunnel_sdk;

create table t_tunnel_sdk (

id    int,

name string

)

partitioned by (gender string);

本实验可参考脚本:E:\ODPS_DEMO\resources\02-DataTransfer\UploadSample.java

(1) 新增 Java 类:
(2) 类名为UploadSample,包名为 DTSample
(3) 设计该类实现功能为将单个文件上传至ODPS的表中,需要的输入参数为:

-f <file_name>

-t <table_name>

-c <config_file>

[-p ]

[-fd <field_delimiter>]

编写方法 printUsage,提示调用语法:

private static void printUsage(String msg) {
System.out.println(
"Usage: UploadSample -f file \\\n"
+ " -t table\\\n"
+ " -c config_file \\\n"
+ " [-p partition] \\\n"
+ " [-fd field_delimiter] \\\n"
);
if (msg != null) {
System.out.println(msg);
}
}

编写获取、解析输入参数的方法 :

private static String accessId;
private static String accessKey;
private static String OdpsEndpoint;
private static String TunnelEndpoint;
private static String project;
private static String table;
private static String partition;
private static String fieldDelimeter;
private static String file;



private static void printUsage(String msg) {
System.out.println(
"Usage: UploadSample -f file \\\n"
+ " -t table\\\n"
+ " -c config_file \\\n"
+ " [-p partition] \\\n"
+ " [-fd field_delimiter] \\\n"
);
if (msg != null) {
System.out.println(msg);
}
}
private static void parseArgument(String[] args) {
for (int i = 0; i < args.length; i++) {
if ("-f".equals(args[i])) {
if (++i == args.length) {
throw new IllegalArgumentException("source file not specified in -f");
}
file = args[i];
}
else if ("-t".equals(args[i])) {
if (++i == args.length) {
throw new IllegalArgumentException("ODPS table not specified in -t");
}
table = args[i];
}
else if ("-c".equals(args[i])) {
if (++i == args.length) {
throw new IllegalArgumentException(
"ODPS configuration file not specified in -c");
}
try {
InputStream is = new FileInputStream(args[i]);
Properties props = new Properties();
props.load(is);
accessId = props.getProperty("access_id");
accessKey = props.getProperty("access_key");
project = props.getProperty("project_name");
OdpsEndpoint = props.getProperty("end_point");
TunnelEndpoint = props.getProperty("tunnel_endpoint");
} catch (IOException e) {
throw new IllegalArgumentException(
"Error reading ODPS config file '" + args[i] + "'.");
}
}
else if ("-p".equals(args[i])){
if (++i == args.length) {
throw new IllegalArgumentException(
"odps table partition not specified in -p");
}
partition = args[i];
}
else if ("-fd".equals(args[i])){
if (++i == args.length) {
throw new IllegalArgumentException(
"odps table partition not specified in -p");
}
fieldDelimeter = args[i];
}
}
if(file == null) {
throw new IllegalArgumentException(
"Missing argument -f file");
}
if (table == null) {
throw new IllegalArgumentException(
"Missing argument -t table");
}

if (accessId == null || accessKey == null ||
project == null || OdpsEndpoint == null || TunnelEndpoint == null) {
throw new IllegalArgumentException(
"ODPS conf not set, please check -c odps.conf");
}
}

(4) 编写方法,从文件中读出记录,同时将这些记录格式化

 读出记录,逐列处理
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
import com.aliyun.odps.Column;
import com.aliyun.odps.OdpsType;
import com.aliyun.odps.TableSchema;

import com.aliyun.odps.data.ArrayRecord;
import com.aliyun.odps.data.Record;

class RecordConverter {
private TableSchema schema;
private String nullTag;
private SimpleDateFormat dateFormater;

private DecimalFormat doubleFormat;
private String DEFAULT_DATE_FORMAT_PATTERN = "yyyyMMddHHmmss";
public RecordConverter(TableSchema schema, String nullTag, String dateFormat,
String tz) {
this.schema = schema;
this.nullTag = nullTag;
if (dateFormat == null) {
this.dateFormater = new SimpleDateFormat(DEFAULT_DATE_FORMAT_PATTERN);
} else {
dateFormater = new SimpleDateFormat(dateFormat);
}
dateFormater.setLenient(false);
dateFormater.setTimeZone(TimeZone.getTimeZone(tz == null ? "GMT" : tz));

doubleFormat = new DecimalFormat();
doubleFormat.setMinimumFractionDigits(0);
doubleFormat.setMaximumFractionDigits(20);
}

/**
* record to String array
* */
public String[] format(Record r) {
int cols = schema.getColumns().size();
String[] line = new String[cols];
String colValue = null;
for (int i = 0; i < cols; i++) {
Column column = schema.getColumn(i);
OdpsType t = column.getType();
switch (t) {
case BIGINT: {
Long v = r.getBigint(i);
colValue = v == null ? null : v.toString();
break;
}
case DOUBLE: {
Double v = r.getDouble(i);
if (v == null) {
colValue = null;
} else {
colValue = doubleFormat.format(v).replaceAll(",", "");
}
break;
}
case DATETIME: {
Date v = r.getDatetime(i);
if (v == null) {
colValue = null;
} else {
colValue = dateFormater.format(v);
}
break;
}
case BOOLEAN: {
Boolean v = r.getBoolean(i);
colValue = v == null ? null : v.toString();
break;
}
case STRING: {
String v = r.getString(i);
colValue = (v == null ? null : v.toString());
break;
}
default:
throw new RuntimeException("Unknown column type: " + t);
}

if (colValue == null) {
line[i] = nullTag;
} else {
line[i] = colValue;
}
}
return line;
}

/**
* String array to record
* @throws ParseException
* */
public Record parse(String[] line){

if (line == null) {
return null;
}

int columnCnt = schema.getColumns().size();
Column[] cols = new Column[columnCnt];
for (int i = 0; i < columnCnt; ++i) {
Column c = new Column(schema.getColumn(i).getName(),
schema.getColumn(i).getType());
cols[i] = c;
}
ArrayRecord r = new ArrayRecord(cols);
int i = 0;
for (String v : line) {
if (v.equals(nullTag)) {
i++;
continue;
}
if (i >= columnCnt) {
break;
}
OdpsType type = schema.getColumn(i).getType();
switch (type) {
case BIGINT:
r.setBigint(i, Long.valueOf(v));
break;
case DOUBLE:
r.setDouble(i, Double.valueOf(v));
break;
case DATETIME:
try {
r.setDatetime(i, dateFormater.parse(v));
} catch (ParseException e) {
throw new RuntimeException(e.getMessage());
}
break;
case BOOLEAN:
v = v.trim().toLowerCase();
if (v.equals("true") || v.equals("false")) {
r.setBoolean(i, v.equals("true") ? true : false);
} else if (v.equals("0") || v.equals("1")) {
r.setBoolean(i, v.equals("1") ? true : false);
} else {
throw new RuntimeException(
"Invalid boolean type, expect: true|false|0|1");
}
break;
case STRING:
r.setString(i, v);
break;
default:
throw new RuntimeException("Unknown column type");
}
i++;
}
return r;
}
}

(5) 编写主方法,读取文件,上传到odps表中去:

public static void main(String args[]) {
try {
parseArgument(args);
} catch (IllegalArgumentException e) {
printUsage(e.getMessage());
System.exit(2);
}

Account account = new AliyunAccount(accessId, accessKey);
Odps odps = new Odps(account);
odps.setDefaultProject(project);
odps.setEndpoint(OdpsEndpoint);

BufferedReader br = null;
try {
TableTunnel tunnel = new TableTunnel(odps);
tunnel.setEndpoint(TunnelEndpoint);
TableTunnel.UploadSession uploadSession = null;
if(partition != null) {
PartitionSpec spec = new PartitionSpec(partition);
System.out.println(spec.toString());
uploadSession=tunnel.createUploadSession(project, table,spec);
System.out.println("Session Status is : " + uploadSession.getStatus().toString());
}
else
{
uploadSession= tunnel.createUploadSession(project, table);
//System.out.println("Session Status is : " + uploadSession.getStatus().toString());
}
Long blockid = (long) 0;
RecordWriter recordWriter = uploadSession.openRecordWriter(blockid, true);
Record record = uploadSession.newRecord();

TableSchema schema = uploadSession.getSchema();
RecordConverter converter = new RecordConverter(schema, "NULL", null, null);
br = new BufferedReader(new FileReader(file));
Pattern pattern = Pattern.compile(fieldDelimeter);
String line = null;
while ((line = br.readLine()) != null) {
String[] items=pattern.split(line,0);
record = converter.parse(items);
recordWriter.write(record);
}
recordWriter.close();
Long[] blocks = {blockid};
uploadSession.commit(blocks);
System.out.println("Upload succeed!");
} catch (TunnelException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if (br != null)
br.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}

(6) 在 ODPS 中建表:

odpscmd -f E:\ODPS_DEMO\resources\02-DataTransfer\crt_tbl.sql

(7) 在 eclipse 中设置测试运行参数:

【实验】阿里云大数据助理工程师认证(ACA)-  ACA认证配套实验-06-MaxCompute 数据传输_eclipse_13


将下列参数填入program parameter:-f E:\ODPS_DEMO\resources\02-DataTransfer\uploadDataSet.csv -t t_tunnel_sdk -p ‘gender=“Male”’ -fd , -c E:\ODPS_DEMO\odpscmd_public\conf\odps_config.ini

【实验】阿里云大数据助理工程师认证(ACA)-  ACA认证配套实验-06-MaxCompute 数据传输_客户端_14


通过console查看输出信息:

去ODPS project里检查上传结果:read t_tunnel_sdk;

【实验】阿里云大数据助理工程师认证(ACA)-  ACA认证配套实验-06-MaxCompute 数据传输_java_15

3.3 单线程下载文件

本实验可参考脚本:E:\ODPS_DEMO\resources\02-DataTransfer\DownloadSample.java

(1) 在已有的名称为 DataTransfer 的 Java project中的 DTSample 包下新增 Java 类:
(2) 编写方法 printUsage,提示调用该程序的输入参数;

(3) 编写方法 parseArgument,获取并解析输入参数;

(4) 编写类RecordConverter用来格式化数据,生成 Record 记录;

(5) 编写方法 main 方法,实现单线程数据下载:

//根据输入参数中的配置文件,配置阿里云账号

Account account = new AliyunAccount(accessId, accessKey);

Odps odps = new Odps(account);

odps.setDefaultProject(project);

odps.setEndpoint(OdpsEndpoint);

//基于上述云账号,创建服务入口类

TableTunnel tunnel = new TableTunnel(odps);

tunnel.setEndpoint(TunnelEndpoint);

//创建从上述odps服务通道中下载数据的会话,分为分区的表和非分区表两种:

TableTunnel.DownloadSession session;

if(partition != null) {

PartitionSpec spec = new PartitionSpec(partition);

session= tunnel.createDownloadSession(project, table, spec);

}else{

session= tunnel.createDownloadSession(project, table);

}

//从odps表中读出记录,格式化后,写入到本地文件:

RecordReader reader = session.openRecordReader(0L, session.getRecordCount(),

true);

TableSchema schema = session.getSchema();

Record record;

RecordConverter converter = new RecordConverter(schema, "NULL", null, null);

String[] items = new String[schema.getColumns().size()];

while ((record = reader.read()) != null) {

items = converter.format(record);

for(int i=0; i<items.length; ++i) {

if(i>0) out.write(fieldDelimeter.getBytes());

out.write(items[i].getBytes());

}

out.write(lineDelimiter.getBytes());

}

reader.close();

out.close();

(6) 在 eclipse 中设置测试运行参数:
将下列参数填入 program parameter

-f E:\ODPS_DEMO\resources\02-DataTransfer\downloadMaleDataSet.csv -fd , -c E:\ODPS_DEMO\odpscmd_public\conf\odps_config.ini -t t_tunnel_sdk -p ‘gender=“Male”’

【实验】阿里云大数据助理工程师认证(ACA)-  ACA认证配套实验-06-MaxCompute 数据传输_java_16


去查看下载文件E:\ODPS_DEMO\resources\02-DataTransfer\downloadMaleDataSet.csv,并和ODPS表 t_tunnel_sdk 中的数据对比。

第 4 章:实验总结

4.1 实验总结

MaxCompute提供的数据传输功能,tunnel命令集方便我们上传本地数据到单表、分区表,并支持上传时自定义设计列分隔符、行分隔符、及数据容错等能力,数据量较大,还可以指定线程数据来加速数据的上传,实验详细介绍了日常工作中常用的功能。

另外,MaxCompute还提供了tunnel JAVA SDK 方便我们进行程序开发时使用数据传输功能