分层命名空间 HNS(Hierarchical NameSpace,简称分层桶)是对象存储 TOS 推出的一个全新的基于分层元数据管理的桶类型。在提供分层命名空间能力的同时兼顾了对象扁平化扩展性,提供对象语义与文件语义透明互通的能力,实现真正的一份数据多种访问协议,提升数据使用效率。
相比原来扁平命名空间 FNS(Flat NameSpace,简称扁平桶)可以很好的支持目录级别的 mv 与 rename 操作,同时优化常见读操作 List 与目录 Head,提升数据处理效率与性能,能很好的满足大数据、数据湖和 AI 领域的使用场景。
本文介绍如何通过 TOS Java SDK 的 listObjects
接口列举指定目录下的对象和子目录等。
delimiter
,且只能使用目录分隔符 /
。tos:ListBucket
权限,具体操作请参见 IAM 策略概述。listObjectsType2
接口,使用方式与 listObjects
接口基本一致。强烈建议您使用 listObjectsType2
接口,以获得更高的列举效率。具体使用方法请参见列举对象 V2。listObjects
接口支持的参数如下。
参数 | 描述 |
---|---|
prefix | 本次查询结果的前缀。 |
delimiter | 对对象名称进行分组的字符,列举分层命名空间对象必须携带 |
marker | 此次列举对象的起点。初始为 null,后续可取值为上次请求返回的 nextMarker。 |
maxKeys | 返回列举对象的最大数。一次最多返回 1000 条结果,若不设置则默认返回 1000 条。 |
encodingType | 对返回的内容进行编码并指定编码的类型。 |
分层桶按照全新的分层架构来组织元数据,因此具有目录实体。
通过 Delimiter
和 Prefix
两个参数实现目录列举的功能:
Delimiter
为 /
同时设置 Prefix
为空, 可返回根目录下的对象和子目录信息。Delimiter
为 /
同时设置 Prefix
为子目录(commonPrefixes
), 可返回子目录的对象和次级目录。以下代码展示如何列举桶 bucket-example
根目录下的对象和子目录。
import com.volcengine.tos.TOSV2; import com.volcengine.tos.TOSV2ClientBuilder; import com.volcengine.tos.TosClientException; import com.volcengine.tos.TosServerException; import com.volcengine.tos.model.object.*; public class HNSListObjectsExample { public static void main(String[] args) { String endpoint = "your endpoint"; String region = "your region"; String accessKey = System.getenv("TOS_ACCESS_KEY"); String secretKey = System.getenv("TOS_SECRET_KEY"); String bucketName = "bucket-example"; int maxKeys = 10; String delimiter = "/"; TOSV2 tos = new TOSV2ClientBuilder().build(region, endpoint, accessKey, secretKey); try{ boolean isTruncated = true; String marker = null; while (isTruncated) { ListObjectsV2Input input = new ListObjectsV2Input().setBucket(bucketName) .setMaxKeys(maxKeys).setDelimiter(delimiter).setMarker(marker); ListObjectsV2Output output = tos.listObjects(input); System.out.printf("listObjects succeed, is truncated? %b, next marker is %s.\n", output.isTruncated(), output.getNextMarker()); if (output.getContents() != null) { for (int i = 0; i < output.getContents().size(); i++) { ListedObjectV2 object = output.getContents().get(i); System.out.printf("Listed object, key is %s, size is %d, storageClass is %s, ETag is %s, " + "last modified is %s, crc64 value is %s.\n", object.getKey(), object.getSize(), object.getStorageClass(), object.getEtag(), object.getLastModified().toString(), object.getHashCrc64ecma()); } } if (output.getCommonPrefixes() != null) { for (int i = 0; i < output.getCommonPrefixes().size(); i++) { ListedCommonPrefix commonPrefix = output.getCommonPrefixes().get(i); System.out.println("Listed commonPrefix is " + commonPrefix.getPrefix()); // commonPrefix 为子目录,可用其作为 prefix 参数继续往下列举 listCommonPrefix(bucketName, maxKeys, delimiter, commonPrefix.getPrefix(), tos); } } isTruncated = output.isTruncated(); marker = output.getNextMarker(); } } catch (TosClientException e) { // 操作失败,捕获客户端异常,一般情况是请求参数错误,此时请求并未发送 System.out.println("listObjects failed"); System.out.println("Message: " + e.getMessage()); if (e.getCause() != null) { e.getCause().printStackTrace(); } } catch (TosServerException e) { // 操作失败,捕获服务端异常,可以获取到从服务端返回的详细错误信息 System.out.println("listObjects failed"); System.out.println("StatusCode: " + e.getStatusCode()); System.out.println("Code: " + e.getCode()); System.out.println("Message: " + e.getMessage()); System.out.println("RequestID: " + e.getRequestID()); } catch (Throwable t) { // 作为兜底捕获其他异常,一般不会执行到这里 System.out.println("listObjects failed"); System.out.println("unexpected exception, message: " + t.getMessage()); } } private static void listCommonPrefix(String bucketName, int maxKeys, String delimiter, String prefix, TOSV2 tos) { boolean isTruncated = true; String marker = null; while (isTruncated) { ListObjectsV2Input input = new ListObjectsV2Input().setBucket(bucketName).setMaxKeys(maxKeys) .setDelimiter(delimiter).setMarker(marker).setPrefix(prefix); ListObjectsV2Output output = tos.listObjects(input); System.out.printf("listObjects succeed, is truncated? %b, next marker is %s.\n", output.isTruncated(), output.getNextMarker()); if (output.getContents() != null) { for (int i = 0; i < output.getContents().size(); i++) { ListedObjectV2 object = output.getContents().get(i); System.out.printf("Listed object, key is %s, size is %d, storageClass is %s, ETag is %s, " + "last modified is %s, crc64 value is %s.\n", object.getKey(), object.getSize(), object.getStorageClass(), object.getEtag(), object.getLastModified().toString(), object.getHashCrc64ecma()); } } if (output.getCommonPrefixes() != null) { for (int i = 0; i < output.getCommonPrefixes().size(); i++) { ListedCommonPrefix commonPrefix = output.getCommonPrefixes().get(i); System.out.println("Listed commonPrefix is " + commonPrefix.getPrefix()); } } isTruncated = output.isTruncated(); marker = output.getNextMarker(); } } }
关于列举对象的 API 文档,请参见 ListObjects。