hbase開發實例

来源:http://www.cnblogs.com/learn21cn/archive/2016/12/11/6158850.html
-Advertisement-
Play Games

1、put/checkAndPut 使用checkAndPut,需要先對數據進行驗證,上面的例子中,向row1中的cf:col1寫入數據"E",而驗證的是row1中的cf:col5的值是否為"E",註意這一點,相當於加了條件。 2、使用get讀取數據 參考結果: 3、使用scan獲取數據 4、del ...


1、put/checkAndPut

 1 package com.testdata;
 2 
 3 import java.io.IOException;
 4 import org.apache.hadoop.conf.Configuration;
 5 import org.apache.hadoop.hbase.HBaseConfiguration;
 6 import org.apache.hadoop.hbase.client.HConnection;
 7 import org.apache.hadoop.hbase.client.HConnectionManager;
 8 import org.apache.hadoop.hbase.client.HTableInterface;
 9 import org.apache.hadoop.hbase.client.Put;
10 import org.apache.hadoop.hbase.util.Bytes; 
11 
12 public class TestPut {
13 
14     public static void main(String[] args) throws IOException {
15         
16         Configuration conf = HBaseConfiguration.create();
17         conf.set("hbase.zookeeper.quorum","localhost");
18         conf.set("hbase.zookeeper.property.clientPort","2181");
19         HConnection conn = HConnectionManager.createConnection(conf);
20         
21         HTableInterface table = conn.getTable("testdata");        
22         Put testput = new Put(Bytes.toBytes("row1"));
23         testput.add(Bytes.toBytes("cf"),Bytes.toBytes("col1"),Bytes.toBytes("E"));
24         table.put(testput);
25         //使用checkAndPut
26         table.checkAndPut(Bytes.toBytes("row1"), Bytes.toBytes("cf"),Bytes.toBytes("col5"),Bytes.toBytes("E"),testput);
27         table.close();
28         conn.close();
29 
30     }
31 
32 }

使用checkAndPut,需要先對數據進行驗證,上面的例子中,向row1中的cf:col1寫入數據"E",而驗證的是row1中的cf:col5的值是否為"E",註意這一點,相當於加了條件。

 2、使用get讀取數據

 1 package com.testdata;
 2 
 3 import java.io.IOException;
 4 import java.util.List;
 5 
 6 import org.apache.hadoop.conf.Configuration;
 7 import org.apache.hadoop.hbase.Cell;
 8 import org.apache.hadoop.hbase.CellUtil;
 9 import org.apache.hadoop.hbase.HBaseConfiguration;
10 import org.apache.hadoop.hbase.client.Get;
11 import org.apache.hadoop.hbase.client.HConnection;
12 import org.apache.hadoop.hbase.client.HConnectionManager;
13 import org.apache.hadoop.hbase.client.HTableInterface;
14 import org.apache.hadoop.hbase.client.Result;
15 
16 
17 import org.apache.hadoop.hbase.util.Bytes; 
18 
19 public class TestGet {
20 
21     public static void main(String[] args) throws IOException {
22         Configuration conf = HBaseConfiguration.create();
23         conf.set("hbase.zookeeper.quorum","localhost");
24         conf.set("hbase.zookeeper.property.clientPort","2181");
25         HConnection conn = HConnectionManager.createConnection(conf);        
26         HTableInterface table = conn.getTable("testdata");
27         
28         Get testget = new Get(Bytes.toBytes("row1"));
29         Result row1 = table.get(testget);
30         String value = new String(row1.getValue(Bytes.toBytes("cf"), Bytes.toBytes("col1")));
31         System.out.println(value);        
32         //下麵限定到具體的列
33         testget.addColumn(Bytes.toBytes("cf"), Bytes.toBytes("col2"));
34         Result result = table.get(testget);
35         if(result.getValue(Bytes.toBytes("cf"), Bytes.toBytes("col2")) != null){
36             String value2 = new String(result.getValue(Bytes.toBytes("cf"), Bytes.toBytes("col2")));
37             System.out.println(value2);
38         }
39         //另外一種讀取方式
40         List<Cell> cells = row1.listCells();
41         for(Cell cell : cells){
42             String rowkey = new String(CellUtil.cloneRow(cell));
43             String family = new String(CellUtil.cloneFamily(cell));
44             String collumn = new String(CellUtil.cloneQualifier(cell));
45             String cvalue = new String(CellUtil.cloneValue(cell));
46             System.out.println("rowkey:" + rowkey + " family:" + family + " column:" + collumn +" value:" + cvalue);
47             
48         }
49 
50         //註意要關閉
51         table.close();
52         conn.close();
53 
54     }
55 
56 }

 參考結果:

3、使用scan獲取數據

 1 package com.testdata;
 2 
 3 import java.io.IOException;
 4 import java.util.List;
 5 import org.apache.hadoop.conf.Configuration;
 6 import org.apache.hadoop.hbase.Cell;
 7 import org.apache.hadoop.hbase.CellUtil;
 8 import org.apache.hadoop.hbase.HBaseConfiguration;
 9 import org.apache.hadoop.hbase.client.HConnection;
10 import org.apache.hadoop.hbase.client.HConnectionManager;
11 import org.apache.hadoop.hbase.client.HTableInterface;
12 import org.apache.hadoop.hbase.client.Result;
13 import org.apache.hadoop.hbase.client.ResultScanner;
14 import org.apache.hadoop.hbase.client.Scan; 
15 
16 public class TestScan {
17 
18     public static void main(String[] args) throws IOException {
19         Configuration conf = HBaseConfiguration.create();
20         conf.set("hbase.zookeeper.quorum","localhost");
21         conf.set("hbase.zookeeper.property.clientPort","2181");
22         HConnection conn = HConnectionManager.createConnection(conf);        
23         HTableInterface table = conn.getTable("testdata");
24         
25         Scan testscan =new Scan();
26         ResultScanner rs = table.getScanner(testscan);
27         for(Result r : rs ){
28             List<Cell> cells = r.listCells();
29             for(Cell cell : cells){
30                 String rowkey = new String(CellUtil.cloneRow(cell));
31                 String family = new String(CellUtil.cloneFamily(cell));
32                 String collumn = new String(CellUtil.cloneQualifier(cell));
33                 String cvalue = new String(CellUtil.cloneValue(cell));
34                 System.out.println("rowkey:" + rowkey + " family:" + family + " column:" + collumn +" value:" + cvalue);
35                 
36             }
37         }
38         rs.close();
39         table.close();
40         conn.close();
41 
42     }
43 
44 }

4、delete/checkAndDelete

 1 package com.testdata;
 2 
 3 import org.apache.hadoop.conf.Configuration;
 4 import org.apache.hadoop.hbase.HBaseConfiguration;
 5 import org.apache.hadoop.hbase.client.Delete;
 6 import org.apache.hadoop.hbase.client.HConnection;
 7 import org.apache.hadoop.hbase.client.HConnectionManager;
 8 import org.apache.hadoop.hbase.client.HTableInterface;
 9 import java.io.IOException;
10 
11 import org.apache.hadoop.hbase.util.Bytes; 
12 
13 public class TestDelete {
14 
15     public static void main(String[] args) throws IOException {
16         Configuration conf = HBaseConfiguration.create();
17         conf.set("hbase.zookeeper.quorum","localhost");
18         conf.set("hbase.zookeeper.property.clientPort","2181");
19         HConnection conn = HConnectionManager.createConnection(conf);        
20         HTableInterface table = conn.getTable("testdata");
21         
22         Delete testdelete = new Delete(Bytes.toBytes("row1"));
23         testdelete.deleteColumns(Bytes.toBytes("cf"), Bytes.toBytes("col1"));
24         //區別隻是checkAndDelete需要進行驗證,相當於加了前提條件
25         //table.delete(testdelete);
26         table.checkAndDelete(Bytes.toBytes("row1"), Bytes.toBytes("cf"), Bytes.toBytes("col2"),Bytes.toBytes("BC"), testdelete);
27         table.close();
28         conn.close();
29 
30     }
31 
32 }

5、append

 1 package com.testdata;
 2 
 3 import java.io.IOException;
 4 import org.apache.hadoop.conf.Configuration;
 5 import org.apache.hadoop.hbase.HBaseConfiguration;
 6 import org.apache.hadoop.hbase.client.Append;
 7 import org.apache.hadoop.hbase.client.HConnection;
 8 import org.apache.hadoop.hbase.client.HConnectionManager;
 9 import org.apache.hadoop.hbase.client.HTableInterface;
10 import org.apache.hadoop.hbase.util.Bytes; 
11 
12 public class TestAppend {
13 
14     public static void main(String[] args) throws IOException {
15         Configuration conf = HBaseConfiguration.create();
16         conf.set("hbase.zookeeper.quorum","localhost");
17         conf.set("hbase.zookeeper.property.clientPort","2181");
18         HConnection conn = HConnectionManager.createConnection(conf);        
19         HTableInterface table = conn.getTable("testdata");
20         
21         Append testappend = new Append(Bytes.toBytes("row1")); 
22         testappend.add(Bytes.toBytes("cf"),Bytes.toBytes("col1"),Bytes.toBytes("F"));
23         table.append(testappend);
24         table.close();
25         conn.close();
26     }
27 
28 }

下麵是結果,註意append是在原有的值之上附加,先前的值為"E",現在變為"EF"

 6、計數器

計數器可以用於統計用戶數,點擊量等信息

 1 package com.testdata;
 2 
 3 import java.io.IOException;
 4 import org.apache.hadoop.conf.Configuration;
 5 import org.apache.hadoop.hbase.HBaseConfiguration;
 6 import org.apache.hadoop.hbase.client.HConnection;
 7 import org.apache.hadoop.hbase.client.HConnectionManager;
 8 import org.apache.hadoop.hbase.client.HTableInterface;
 9 import org.apache.hadoop.hbase.util.Bytes;
10 
11 public class TestIncrement {
12 
13     public static void main(String[] args) throws IOException {
14         Configuration conf = HBaseConfiguration.create();
15         conf.set("hbase.zookeeper.quorum","localhost");
16         conf.set("hbase.zookeeper.property.clientPort","2181");
17         HConnection conn = HConnectionManager.createConnection(conf);        
18         HTableInterface table = conn.getTable("testdata");
19         
20         long result = table.incrementColumnValue(Bytes.toBytes("row1"),Bytes.toBytes("cf"),Bytes.toBytes("coli"), 10);
21         
22         System.out.println(result);
23         table.close();
24         conn.close();
25 
26     }
27 
28 }

註意 long result = table.incrementColumnValue(Bytes.toBytes("row1"),Bytes.toBytes("cf"),Bytes.toBytes("coli"), 10);

最後一個參數,可以為0,意味著讀取,也可以是負數。

可以使用get_counter可以獲取對應的計數器的值,也可以使用以下命令進行操作

 incr '<table>', '<row>', '<column>', |<increment-value>|

7、filter

使用時註意性能

 1 package com.testdata;
 2 
 3 import java.io.IOException;
 4 import java.util.List;
 5 import org.apache.hadoop.conf.Configuration;
 6 import org.apache.hadoop.hbase.Cell;
 7 import org.apache.hadoop.hbase.CellUtil;
 8 import org.apache.hadoop.hbase.HBaseConfiguration;
 9 import org.apache.hadoop.hbase.client.HConnection;
10 import org.apache.hadoop.hbase.client.HConnectionManager;
11 import org.apache.hadoop.hbase.client.HTableInterface;
12 import org.apache.hadoop.hbase.client.Result;
13 import org.apache.hadoop.hbase.client.ResultScanner;
14 import org.apache.hadoop.hbase.client.Scan;
15 import org.apache.hadoop.hbase.filter.BinaryComparator;
16 import org.apache.hadoop.hbase.filter.BinaryPrefixComparator;
17 import org.apache.hadoop.hbase.filter.CompareFilter;
18 import org.apache.hadoop.hbase.filter.Filter;
19 import org.apache.hadoop.hbase.filter.QualifierFilter;
20 import org.apache.hadoop.hbase.filter.RowFilter;
21 import org.apache.hadoop.hbase.filter.SubstringComparator;
22 import org.apache.hadoop.hbase.util.Bytes; 
23 
24 public class TestSimplefilter {
25 
26     public static void main(String[] args) throws IOException {
27         Configuration conf = HBaseConfiguration.create();
28         conf.set("hbase.zookeeper.quorum","localhost");
29         conf.set("hbase.zookeeper.property.clientPort","2181");
30         HConnection conn = HConnectionManager.createConnection(conf);        
31         HTableInterface table = conn.getTable("testdata");
32         
33         Scan sc = new Scan();
34         sc.setCacheBlocks(false);
35         //行過濾器,判斷"row1"與行的key是否相等
36         //Filter filter = new RowFilter(CompareFilter.CompareOp.EQUAL,new BinaryComparator(Bytes.toBytes("row1")));
37         //是否以"row"為首碼
38         //Filter filter = new RowFilter(CompareFilter.CompareOp.EQUAL,new BinaryPrefixComparator(Bytes.toBytes("row")));
39         //是否包含"row"
40         //Filter filter = new RowFilter(CompareFilter.CompareOp.EQUAL,new SubstringComparator("row"));
41         
42         //列過濾器,與行類似
43         Filter filter = new QualifierFilter(CompareFilter.CompareOp.EQUAL,new BinaryComparator(Bytes.toBytes("col1")));
44         
45         sc.setFilter(filter);
46         
47         ResultScanner rs = table.getScanner(sc);
48         for(Result r : rs ){
49             List<Cell> cells = r.listCells();
50             for(Cell cell : cells){
51                 String rowkey = new String(CellUtil.cloneRow(cell));
52                 String family = new String(CellUtil.cloneFamily(cell));
53                 String collumn = new String(CellUtil.cloneQualifier(cell));
54                 String cvalue = new String(CellUtil.cloneValue(cell));
55                 System.out.println("rowkey:" + rowkey + " family:" + family + " column:" + collumn +" value:" + cvalue);                
56             }
57         }
58         rs.close();
59         table.close();
60         conn.close();            
61     }
62 }

使用filterlist

 1 package com.testdata;
 2 
 3 import java.io.IOException;
 4 import java.util.ArrayList;
 5 import java.util.List;
 6 import org.apache.hadoop.conf.Configuration;
 7 import org.apache.hadoop.hbase.Cell;
 8 import org.apache.hadoop.hbase.CellUtil;
 9 import org.apache.hadoop.hbase.HBaseConfiguration;
10 import org.apache.hadoop.hbase.client.HConnection;
11 import org.apache.hadoop.hbase.client.HConnectionManager;
12 import org.apache.hadoop.hbase.client.HTableInterface;
13 import org.apache.hadoop.hbase.client.Result;
14 import org.apache.hadoop.hbase.client.ResultScanner;
15 import org.apache.hadoop.hbase.client.Scan;
16 import org.apache.hadoop.hbase.filter.BinaryComparator;
17 import org.apache.hadoop.hbase.filter.BinaryPrefixComparator;
18 import org.apache.hadoop.hbase.filter.CompareFilter;
19 import org.apache.hadoop.hbase.filter.Filter;
20 import org.apache.hadoop.hbase.filter.FilterList;
21 import org.apache.hadoop.hbase.filter.QualifierFilter;
22 import org.apache.hadoop.hbase.filter.RegexStringComparator;
23 import org.apache.hadoop.hbase.filter.RowFilter;
24 import org.apache.hadoop.hbase.filter.SingleColumnValueFilter;
25 import org.apache.hadoop.hbase.filter.SubstringComparator;
26 import org.apache.hadoop.hbase.util.Bytes; 
27 
28 public class TestFilterList {
29 
30     public static void main(String[] args) throws IOException {
31         Configuration conf = HBaseConfiguration.create();
32         conf.set("hbase.zookeeper.quorum","localhost");
33         conf.set("hbase.zookeeper.property.clientPort","2181");
34         HConnection conn = HConnectionManager.createConnection(conf);        
35         HTableInterface table = conn.getTable("testdata");
36         
37         Scan sc = new Scan();
38         Filter filter1 = new RowFilter(CompareFilter.CompareOp.EQUAL,new BinaryComparator(Bytes.toBytes("row2")));
39         SingleColumnValueFilter filter2 = new SingleColumnValueFilter(Bytes.toBytes("cf"),Bytes.toBytes("col1"),CompareFilter.CompareOp.EQUAL,new BinaryPrefixComparator(Bytes.toBytes("B")));
40         
41         SingleColumnValueFilter filter3 = new SingleColumnValueFilter(Bytes.toBytes("cf"),Bytes.toBytes("col1"),CompareFilter.CompareOp.EQUAL,new RegexStringComparator("B|C"));
42         filter2.setFilterIfMissing(true);
43         filter3.setFilterIfMissing(true);
44         
45         //List<Filter> filters = new ArrayList<Filter>();
46         //filters.add(filter1);
47         //filters.add(filter2);        
48         //FilterList filterlist = new FilterList(filters);
49         
50         //也可以這樣寫,MUST_PASS_ALL標識滿足所有的filter,當然也可以使用MUST_PASS_ONE,標識只需要滿足一個
51         FilterList filterlist = new FilterList(FilterList.Operator.MUST_PASS_ALL);
52         filterlist.addFilter(filter1);
53         filterlist.addFilter(filter2);
54         filterlist.addFilter(filter3);        
55         sc.addColumn(Bytes.toBytes("cf"),Bytes.toBytes("col1"));
56         sc.setFilter(filterlist);
57         
58         ResultScanner rs = table.getScanner(sc);
59         for(Result r : rs ){
60             List<Cell> cells = r.listCells();
61             for(Cell cell : cells){
62                 String rowkey = new String(CellUtil.cloneRow(cell));
63                 String family = new String(CellUtil.cloneFamily(cell));
64                 String collumn = new String(CellUtil.cloneQualifier(cell));
65                 String cvalue = new String(CellUtil.cloneValue(cell));
66                 System.out.println("rowkey:" + rowkey + " family:" + family + " column:" + collumn +" value:" + cvalue);                
67             }
68         }
69         rs.close();
70         table.close();
71         conn.close();
72     }
73 }

以上一組filter標識了這樣的條件,即行的key必須為"row2",列名必須為"col1",值必須為"B"

結果參考:

如果沒有 sc.addColumn(Bytes.toBytes("cf"),Bytes.toBytes("col1"));這一句,結果會是下麵的樣子

rowkey:row2 family:cf column:col1 value:B
rowkey:row2 family:cf column:colb value:U

問題出在 SingleColumnValueFilter filter2 = new SingleColumnValueFilter(Bytes.toBytes("cf"),Bytes.toBytes("col1"),CompareFilter.CompareOp.EQUAL,new BinaryPrefixComparator(Bytes.toBytes("B")));這一句,如果列印Bytes.toBytes("B")Bytes.toBytes("U"),會發現都是以"B"開頭的。即使換成BinaryComparator,也不會解決問題。

這裡是值得註意的地方,搜索網路可以發現一樣的結論,使用時務必使用sc.addColumn(Bytes.toBytes("cf"),Bytes.toBytes("col1"))類似的語句。

rowkey:row2 family:cf column:col1 value:B

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • NAND FLASH是一個存儲晶元 那麼: 這樣的操作很合理"讀地址A的數據,把數據B寫到地址A" 問1. 原理圖上NAND FLASH和S3C2440之間只有數據線, 怎麼傳輸地址? 答1.在DATA0~DATA7上既傳輸數據,又傳輸地址 當ALE為高電平時傳輸的是地址, ... ...
  • Linux設備模型是對系統設備組織架構進行抽象的一個數據結構,旨在為設備驅動進行分層、分類、組織。降低設備多樣性帶來的Linux驅動開發的複雜度,以及設備熱拔插處理、電源管理等。 ...
  • 之前沒怎麼註意,在使用下載盒通過isp下載stm32時,由於是通過stm32板子給下載盒供電,所以是我的stm32板子和下載盒同時上電。這樣總是不能夠進入下載模式,後來對下載盒進行模擬,發現在下載發送了7F之前,下載盒已經收到了一個位元組,導致在判斷首位元組時出錯。 後來就先把下載和給去了,直接把串口接 ...
  • 在2.1、欄目的前臺顯示中因右鍵沒有添加視圖把微軟給鄙視了一下,後來有仔細研究了一下發現應該鄙視自己,其實這個功能是有的,是自己沒搞清楚亂吐糟。 其實只要在NuGet中安裝兩個包(Microsoft.VisualStudio.Web.CodeGeneration.Tools和Microsoft.Vi... ...
  • 前面一篇里提到事件是通過委托來進行關聯的,而委托是可以帶各種各樣的參數的,其中就可以用事件參數(EventArgs),同時,也可以用.Net框架裡邊提供的一個委托EventHandler來Handle事件。 一樣,搞一個場景(這個場景是書里的):買車。經銷商(CarDealer)會上新車(NewCa ...
  • C#的事件基於委托,所以先說委托。 一切脫離實際場景的抽象概念新手看上去就像是在扯犢子,不錯,我就是個新手。所以我需要一個實際的場景。 明天剛好考試(商務英語),考試上有兩個角色(class):老師(Teacher)和學生(Student),在考試時間終止的時候,老師會觸發(invoke)一個事件( ...
  • 上篇 《python時間時分秒與秒數的互相轉換》http://www.cnblogs.com/gayhub/p/6154707.html 提到了把時間轉成秒數的方法, 這篇寫寫轉換成秒數後有些什麼用處。 場景1:取N個07:30:00 09:30:33之間的隨機時間。 下麵是我的代碼: 從代碼中可以 ...
  • OpenGL常用函數 glAccum 操作累加緩衝區 glAddSwapHintRectWIN 定義一組被 SwapBuffers拷貝的三角形 glAlphaFunc允許設置alpha檢測功能 glAreTexturesResident 決定特定的紋理對象是否常駐在紋理記憶體中 glArrayElem ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...