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

一、实验概述

大数据计算服务(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)请点击页面左侧的实验资源,在左侧栏中,查看本次实验资源信息。如图案例:
在这里插入图片描述
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)点击“新建脚本”设置实验临时文件
在这里插入图片描述
10)设置文件名称、类型(选择ODPS SQL)、描述信息(建议非必须)、文件保存目录信息,点击“提交”进入SQL操作环境
在这里插入图片描述
2、配置客户端

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

(https://help.aliyun.com/document_detail/27971.html?spm=5176.doc27834.6.730.xbOX5m)
在这里插入图片描述
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;

在这里插入图片描述
------检查插入结果

        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
在这里插入图片描述

1.5 下载配套实验材料

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

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

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

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

至少应该包含以下文件:
在这里插入图片描述
(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;

在这里插入图片描述
(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
在这里插入图片描述
(2) 执行E:\ODPS_DEMO\eclipse\eclipse.exe,打开 eclipse,点击 New -> Other
(3) 配置 odps
在这里插入图片描述
在这里插入图片描述
(4) 指定 JavaProject Name:
在这里插入图片描述

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 中设置测试运行参数:
在这里插入图片描述
将下列参数填入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
在这里插入图片描述
通过console查看输出信息:
去ODPS project里检查上传结果:

read t_tunnel_sdk;
在这里插入图片描述

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”’
在这里插入图片描述
去查看下载文件E:\ODPS_DEMO\resources\02-DataTransfer\downloadMaleDataSet.csv,并和ODPS表 t_tunnel_sdk 中的数据对比。

第 4 章:实验总结

4.1 实验总结

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

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

猜你喜欢

转载自blog.csdn.net/wyn_365/article/details/107283761
今日推荐