您好,登錄后才能下訂單哦!
今天小編給大家分享一下Java怎么實現提取QSV文件視頻內容的相關知識點,內容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。
第一步新建一個java類QSV
,構造函數傳入需要解析的文件名稱。
public class QSV { private RandomAccessFile randomAccessFile; private String name; public QSV(String name) throws FileNotFoundException { randomAccessFile = new RandomAccessFile(name, "r"); this.name = name; } }
我們需要逐個字節讀取文件,這邊就需要jdk自帶的類RandomAccessFile
,先定義一個通用函數,輸出偏移位置和字節大小獲取字節數組。
/** * @param offset 偏移未知 * @param size 字節大小 * @return 字節數組 * @throws IOException */ private byte[] getByteFromFile(int offset, int size) throws IOException { //指針移動至偏移位置 randomAccessFile.seek(offset); //需要讀取的字節數 byte[] bs = new byte[size]; randomAccessFile.read(bs); return bs; }
private static final char[] HEX_VOCABLE = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; /** * 字節數組轉16進制字符串 * * @param bs * @return */ public String bytesToHex(byte[] bs) { StringBuilder sb = new StringBuilder(); for (byte b : bs) { int high = (b >> 4) & 0x0f; int low = b & 0x0f; sb.append(HEX_VOCABLE[high]); sb.append(HEX_VOCABLE[low]); } return sb.toString(); }
/** * 字節數組轉int * * @param b * @return */ public int toInt(byte[] b) { int res = 0; for (int i = 0; i < b.length; i++) { res += (b[i] & 0xff) << (i * 8); } return res; }
老版本解密方法比較簡單,先看下C的寫法:
// 定義1個字節內存 typedef uint8_t BYTE; // 定義4個字節內存 typedef uint32_t DWORD; // decryption algorithm for some segments in qsv version 0x1 void decrypt_1(BYTE* buffer, DWORD size) { static BYTE dict[] = {0x62, 0x67, 0x70, 0x79}; for(int i = 0; i < size; ++i) { DWORD j = ~i & 0x3; buffer[i] ^= dict[j]; } }
可以直接用byte數組和long類型替換c的內存定義,這邊沒問題時因為沒有位移算法,后面新版本解密算法會講到。
private void decrypt_1(byte[] bs, long len) { byte[] b = new byte[]{0x62, 0x67, 0x70, 0x79}; for (int i = 0; i < len; i++) { //先取反再與運算 int j = ~i & 0x3; //異或運算 bs[i] ^= b[j]; } }
新版本解密算法比較復雜,同樣先看下c的寫法:
// 定義1個字節內存 typedef uint8_t BYTE; // 定義4個字節內存 typedef uint32_t DWORD; // decryption algorithm for some segments in qsv version 0x2 void decrypt_2(BYTE* buffer, DWORD size) { DWORD x = 0x62677079; for(DWORD i = size - 1; i != 0; --i) { x = (x << 1) | (x >> 31); x ^= buffer[i]; } for(DWORD i = 1; i < size; ++i) { x ^= buffer[i] & 0xFF; x = (x >> 1) | (x << 31); DWORD j = x % i; BYTE tmp = buffer[j]; buffer[j] = tmp ^ (BYTE)~buffer[i]; buffer[i] = tmp; } }
這邊注意c的寫法有位移,定義的DWORD
占32位內存,而java與之對應的int
類型也是占32位內存,取值范圍是-2^31~2^31-1
(即-2147483648~2147483647
),如果超出這個范圍java需要用long,而long占64位內存取反和位移都是按64位進行的與C的32位取反位移計算結果肯定有差異。
比如:2147483648,轉換位二進制表示:10000000000000000000000000000000,C的寫法由于DWORD
占32位內存,左移一位后超出32為故就變成00000000000000000000000000000000,而java已經超出了int的取值范圍,只能用long定義,由于long占64位,左移一位不會超出,結果也就不一樣了。
又比如:9147483648,轉為二進制表示:1000100001001110111000011000000000,已經超出32位,存到DWORD
中的只保留右邊的32位,即00100001001110111000011000000000,左移以為變成01000010011101110000110000000000,轉為10進制為1115098112,而java采用long定義不會超出64位,左移結果位10001000010011101110000110000000000,轉為十進制表示為18294967296,與C的結果相差較大。那么有辦法解決嗎,答案肯定是有的,我們需要重新寫一個位移算法。
/** * 左移 * * @param value long * @param i 位移量 * @return long */ private long longLeftShift(long value, int i) { String binary = format32(value); binary = binary.substring(i) + String.format("%0" + i + "d", 0); return Long.parseLong(binary, 2); } /** * 右移 * * @param value long * @param i 位移量 * @return long */ private long longRightShift(long value, int i) { String binary = format32(value); binary = String.format("%0" + i + "d", 0) + binary.substring(0, binary.length() - i); return Long.parseLong(binary, 2); } private String format32(long value) { String binary = Long.toBinaryString(value); if (binary.length() < 32) { //補滿32位 binary = String.format("%0" + (32 - binary.length()) + "d", 0) + binary; } else { //多余的截取掉 binary = binary.substring(binary.length() - 32); } return binary; }
有了新定義的位移算法,解密算法就可以修改為:
private void decrypt_2(byte[] buffer, int size) { long x = 0x62677079; for (int i = size - 1; i != 0; --i) { x = longLeftShift(x, 1) | longRightShift(x, 31); x ^= buffer[i] & 0xFF; } for (int i = 1; i < size; ++i) { x ^= buffer[i] & 0xFF; x = longRightShift(x, 1) | longLeftShift(x, 31); int j = (int) (x % i); byte tmp = buffer[j]; int a = buffer[i]; buffer[j] = (byte) (tmp ^ ~a); buffer[i] = tmp; } }
上一篇文章講到,頭部信息共90個字節,signature
(10byte)+version
(4byte)+vid
(16byte)+_unknown1
(4byte)+_unknown2
(32byte)+_unknown3
(4byte)+_unknown4
(4byte)+json_offset
(8byte)+json_size
(4byte)+nb_indices
(4byte)
public static void main(String[] args) throws IOException { QSV qsv = new QSV("D:\\workspace\\c\\風吹半夏第1集-藍光1080P.qsv"); qsv.readHead(); qsv.close(); } public void readHead() throws IOException { //signature:10byte byte[] signature = getByteFromFile(0x0, 0xA); //version:4byte byte[] version = getByteFromFile(0xA, 0x4); //vid:16byte byte[] vid = getByteFromFile(0xE, 0x10); //_unknown1:4byte byte[] _unknown1 = getByteFromFile(0x1E, 0x4); //_unknown2:32byte byte[] _unknown2 = getByteFromFile(0x22, 0x20); //_unknown3:4byte byte[] _unknown3 = getByteFromFile(0x42, 0x4); //_unknown4:4byte byte[] _unknown4 = getByteFromFile(0x46, 0x4); //json_offset:8byte byte[] json_offset = getByteFromFile(0x4A, 0x8); //json_size:4byte byte[] json_size = getByteFromFile(0x52, 0x4); //nb_indices:4byte byte[] nb_indices = getByteFromFile(0x56, 0x4); System.out.println(String.format("signature:%s\nversion:%s\nvid:%s\n_unknown1:%s\n_unknown2:%s\n_unknown3:%s\n_unknown4:%s\njson_offset:0x%s\njson_size:0x%s\nnb_indices:0x%s", new String(signature), toInt(version), bytesToHex(vid), bytesToHex(_unknown1), bytesToHex(_unknown2), bytesToHex(_unknown3), bytesToHex(_unknown4), Integer.toHexString(toInt(json_offset)), Integer.toHexString(toInt(json_size)), Integer.toHexString(toInt(nb_indices)))); }
運行結果:
signature:QIYI VIDEO
version:2
vid:A90EA47D4333331BB85F331C1130504C
_unknown1:01000000
_unknown2:0000000000000000000000000000000000000000000000000000000000000000
_unknown3:01000000
_unknown4:01000000
json_offset:0x167
json_size:0x1d81
nb_indices:0x7
獲取json數據需要先獲取頭部信息記錄的json的偏移位置和字節大小,獲取到的字節數組再通過老版本解密算法解密即可。
public static void main(String[] args) throws IOException { QSV qsv = new QSV("D:\\workspace\\c\\風吹半夏第1集-藍光1080P.qsv"); qsv.readJson(); qsv.close(); } public void readJson() throws IOException { //json_offset:8byte byte[] json_offset = getByteFromFile(0x4A, 0x8); //json_size:4byte byte[] json_size = getByteFromFile(0x52, 0x4); //json byte[] bs = getByteFromFile(toInt(json_offset), toInt(json_size)); decrypt_1(bs, bs.length); System.out.println(String.format("json_offset:0x%s\njson_size:0x%s", Integer.toHexString(toInt(json_offset)), Integer.toHexString(toInt(json_size)))); System.out.println(new String(bs, StandardCharsets.UTF_8)); }
運行結果:
json_offset:0x167
json_size:0x1d81
QYVI {"qsv_info":{"ad":{},"aid":"3644740799867701","bid":600,"dr":-1,"independentaudio":true,"m3u8":"","pano":{"type":1},"qsvinfo_version":2,"sdv":"","st":"","thdt":1,"tht":0,"title":"","title_tail_info":{"bt":99,"bts":-1,"et":2621,"ete":-1,"fe":1,"le":0},"tvid":"3185901936393500","vd":{"seg":{"duration":["376140","365508","370300","371477","368311","368308","554319"],"rid":["a8c47c2906b88ae47e8503c96dae0494","4c8578cecbdfa3137a61b7e2bd1c68dc","4bc76f9b4d4ce995f40b42c467d206f8","8ed13ccd56aa2367f5eaabee12043d89","247b4612415c5b452f5965894a967e19","309400bef063cfd6baf19feb0d4a73a9","9771b1042cabfc9828767a3d0350f655"],"size":["75624801","84329329","90135782","82093900","91974933","75298884","111399115"]},"time":{"et":"2621000","st":"99000"}},"vi":"{\"writer\":\"\",\"authors\":\"\",\"upOrder\":36,\"rewardAllowed\":0,\"fl\":[],\"allowEditVVIqiyi\":0,\"isPopup\":1,\"payMark\":0,\"an\":\"風吹半夏\",\"pvu\":\"\",\"subType\":1,\"rewardMessage\":\"\",\"ipLimit\":1,\"pubTime\":\"1673306651000\",\"mainActorRoles\":[],\"up\":\"2023-01-17 20:20:02\",\"un\":\"\",\"qiyiProduced\":1,\"platforms\":[],\"vn\":\"風吹半夏第1集\",\"plc\":{\"4\":{\"downAld\":1,\"coa\":1},\"40\":{\"downAld\":1,\"coa\":1},\"10\":{\"downAld\":1,\"coa\":1},\"5\":{\"downAld\":1,\"coa\":1},\"41\":{\"downAld\":1,\"coa\":1},\"22\":{\"downAld\":1,\"coa\":1},\"32\":{\"downAld\":1,\"coa\":1},\"11\":{\"downAld\":1,\"coa\":1},\"12\":{\"downAld\":1,\"coa\":1},\"7\":{\"downAld\":1,\"coa\":1},\"13\":{\"downAld\":1,\"coa\":1},\"14\":{\"downAld\":1,\"coa\":1},\"91\":{\"downAld\":1,\"coa\":1},\"34\":{\"downAld\":1,\"coa\":1},\"9\":{\"downAld\":1,\"coa\":1},\"6\":{\"downAld\":1,\"coa\":1},\"16\":{\"downAld\":1,\"coa\":1},\"17\":{\"downAld\":1,\"coa\":1},\"27\":{\"downAld\":1,\"coa\":1},\"28\":{\"downAld\":1,\"coa\":1},\"18\":{\"downAld\":1,\"coa\":1},\"29\":{\"downAld\":1,\"coa\":1},\"1\":{\"downAld\":1,\"coa\":1},\"50\":{\"downAld\":1,\"coa\":1},\"31\":{\"downAld\":1,\"coa\":1},\"15\":{\"downAld\":1,\"coa\":1},\"2\":{\"downAld\":1,\"coa\":1},\"3\":{\"downAld\":1,\"coa\":1},\"21\":{\"downAld\":1,\"coa\":1},\"30\":{\"downAld\":1,\"coa\":1},\"19\":{\"downAld\":1,\"coa\":1},\"8\":{\"downAld\":1,\"coa\":1},\"20\":{\"downAld\":1,\"coa\":1}},\"sm\":0,\"st\":200,\"startTime\":99,\"showChannelId\":2,\"vu\":\"http:\\/\\/www.iqiyi.com\\/v_uvxuws1kkw.html\",\"povu\":\"\",\"ppsuploadid\":0,\"qiyiPlayStrategy\":\"非會員每日20:00轉免1集\",\"ar\":\"內地\",\"cc\":0,\"videoQipuId\":3185901936393500,\"albumQipuId\":3644740799867701,\"pano\":{\"type\":1},\"subt\":\"許半夏幫童驍騎驅霉運\",\"endTime\":2621,\"cpa\":1,\"userVideocount\":0,\"es\":36,\"plg\":2774,\"stl\":{\"d\":\"http:\\/\\/meta.video.iqiyi.com\",\"stl\":[]},\"subKey\":\"3644740799867701\",\"tvFocuse\":\"趙麗穎歐豪攜手創業\",\"qtId\":0,\"ty\":0,\"ppsInfo\":{\"shortTitle\":\"風吹半夏第1集\",\"name\":\"風吹半夏第1集\"},\"sid\":0,\"etm\":\"\",\"keyword\":\"風吹半夏\",\"pturl\":\"\",\"a\":\"\",\"isTopChart\":0,\"idl\":0,\"albumAlias\":\"許半夏幫童驍騎驅霉運\",\"stm\":\"\",\"pd\":1,\"tags\":[],\"coa\":0,\"c\":2,\"producers\":\"\",\"nurl\":\"\",\"tvEname\":\"wild bloom\",\"uid\":\"0\",\"asubt\":\"\",\"d\":\"傅東育|毛溦\",\"vid\":\"a90ea47d4333331bb85f331c1130504c\",\"dts\":\"20230117202002\",\"editorInfo\":\"\",\"tvSeason\":0,\"ntvd\":3185901936393500,\"vpic\":\"http:\\/\\/pic6.iqiyipic.com\\/image\\/20221127\\/e2\\/52\\/v_170312139_m_601_m1.jpg\",\"vType\":0,\"cType\":1,\"payMarkUrl\":\"\",\"apic\":\"http:\\/\\/pic8.iqiyipic.com\\/image\\/20230104\\/6c\\/00\\/a_100498846_m_601_m26.jpg\",\"shortTitle\":\"風吹半夏第1集\",\"tvid\":3185901936393500,\"aid\":3644740799867701,\"au\":\"http:\\/\\/www.iqiyi.com\\/a_yq6d69gtw9.html\",\"tvPhase\":0,\"ifs\":0,\"is\":0,\"tpl\":[],\"actors\":[],\"isVip\":\"\",\"votes\":[],\"previewImageUrl\":\"http:\\/\\/preimage3.iqiyipic.com\\/preimage\\/20230110\\/6a\\/a6\\/v_170312139_m_611_m6.jpg\",\"e\":\"\",\"cnPremTime\":0,\"s\":\"\",\"ma\":\"趙麗穎|歐豪|李光潔|劉威|柯藍|任重|馮嘉怡|孫千|黃澄澄|是安|宋熹|王西|黃義威|王勁松|劉威葳|尤靖茹|林鵬(大陸男演員)|郝平|淮文|顏世魁|薛淑杰|劉碩|丁冠中|豆藝坤|寇鐘吁|楊德民|傅宜箴|朱超藝|黃子琪|榮飛|田玲|周小鑌|孔琳|方曉莉|陳創|韓朔|高遠\",\"supName\":\"\",\"sc\":0,\"categoryKeywords\":\"電視劇,3644740799867701,0,http:\\/\\/list.iqiyi.com\\/www\\/2\\/------------------.html 自制,12791537149997,2,http:\\/\\/list.iqiyi.com\\/www\\/2\\/-12791537149997-----------------.html 浙江衛視,20291787825994,0,http:\\/\\/list.iqiyi.com\\/www\\/2\\/------------------.html 家庭,23757144288056,2,http:\\/\\/list.iqiyi.com\\/www\\/2\\/-23757144288056-----------------.html 言情,23789230921965,2,http:\\/\\/list.iqiyi.com\\/www\\/2\\/-23789230921965-----------------.html 勵志,29717236536467,2,http:\\/\\/list.iqiyi.com\\/www\\/2\\/-29717236536467-----------------.html 商戰,32284167249109,2,http:\\/\\/list.iqiyi.com\\/www\\/2\\/-32284167249109-----------------.html 劇情,37979544767779,2,http:\\/\\/list.iqiyi.com\\/www\\/2\\/-37979544767779-----------------.html 都市,80141381722890,2,http:\\/\\/list.iqiyi.com\\/www\\/2\\/-80141381722890-----------------.html 內地,80526421329786,0,http:\\/\\/list.iqiyi.com\\/www\\/2\\/------------------.html 愛情,87328787718281,2,http:\\/\\/list.iqiyi.com\\/www\\/2\\/-87328787718281-----------------.html\",\"onlineStatus\":1,\"mdown\":0,\"bmsg\":{\"t\":\"20230117202002\",\"f\":\"web\",\"mid\":\"\",\"sp\":\"26173601,\"},\"nvid\":\"8ec7f862076f40ee17c908e2bbc3fae2\",\"flpps\":[],\"supType\":\"\",\"lg\":2,\"is3D\":0,\"bossStatus\":0,\"isDisplayCircle\":0,\"actorRoles\":[],\"exclusive\":1,\"circle\":{\"type\":0,\"id\":0},\"commentAllowed\":1,\"tg\":\"忠犬 大女主 自制 工業強國 毒舌 重組家庭 渣男 浙江衛視 家庭 言情 霸道總裁 御姐 勵志 個人成長 虐戀 雙強 普通話 商戰 硬漢 劇情 出軌 兄弟反目 女強人 爽劇 初戀 青年奮斗 熱血 女性勵志 群像 個人奮斗 接地氣 女青年 大佬 原生家庭 豬隊友 都市 內地 組團 愛情\",\"info\":\"1996年的秋天,陽光炫目。許半夏開著一輛桑塔納,接著剛出獄的童驍騎駛往鷺州出差。一路上童驍騎默默無言,二人之間氣氛尷尬。到了酒店后,許半夏的指示很清楚:洗澡,看電視,睡覺,第二天一早,她來接童驍騎一起出差。童驍騎點點頭,在許半夏離開后,他開始洗澡,記憶也回到了五年前……\\n1991年的一個雨夜,童驍騎因為急著給媽媽籌醫藥費,撬了一堆下水井蓋,蹬著三輪車拉到了許半夏和小陳的廢品站。小陳認定童驍騎就是個騙子,不愿幫忙,但善良的半夏相信童驍騎,給了他錢,并且三個人一大早一起把井蓋都送了回去。童驍騎為表感激,愿意替二人做事。許半夏提到當地鋼廠有很多廢了的下腳料,他們可以去收,但缺一輛大車。于是司機班出身的童驍騎真的把廠里的東風偷偷開了出來,三人搖搖晃晃進了鋼廠,掙到了人生的第一桶金,但童驍騎也因為私自用車被廠里開除了。回到廢品站的童驍騎心灰意冷,許半夏卻安慰道正好,今后他們三個人就一塊兒干,而這些錢就是他們的第一筆合伙資金。\",\"supId\":0,\"issueTime\":0,\"dtype\":3,\"producer\":\"\",\"presentor\":[],\"followerCount\":0}","vid":"a90ea47d4333331bb85f331c1130504c","videotype":0}}s
獲取視頻信息,首先要先提取索引信息,根據索引信息中的偏移位置和字節大小獲取,獲取到的字節數組前1024個字節需要解密,根據頭部信息中的version
判斷,如果是1則用老版本算法解密,如果是2則用新版本算法解密。
一個QSV文件包含多段視頻數據,已發現的視頻格式有flv(舊版客戶端)、mpeg-ts(新版客戶端)。可以通過前三個字節判斷,如果前三個字節轉字符串為FLV
則為FLV
格式。
public static void main(String[] args) throws IOException { QSV qsv = new QSV("D:\\workspace\\c\\風吹半夏第1集-藍光1080P.qsv"); qsv.readIndex("D:\\workspace\\c"); qsv.close(); } public void readIndex(String outPath) throws IOException { //nb_indices byte[] nb_indices = getByteFromFile(0x56, 0x4); //索引 //_unknown_flag byte[] _unknown_flag = getByteFromFile(0x5A, toInt(nb_indices) + 7 >> 3); System.out.println(String.format("nb_indices:0x%s\n_unknown_flag:%s", Integer.toHexString(toInt(nb_indices)), bytesToHex(_unknown_flag))); //version:4byte byte[] version = getByteFromFile(0xA, 0x4); //索引體 byte[] indices = getByteFromFile(0x5A + (toInt(nb_indices) + 7 >> 3), toInt(nb_indices) * 0x1C); for (int i = 0; i < toInt(nb_indices); i++) { byte[] indice = new byte[0x1C]; System.arraycopy(indices, 0x1C * i, indice, 0, 0x1C); if (toInt(version) == 1) { decrypt_1(indice, indice.length); } else if (toInt(version) == 2) { decrypt_2(indice, indice.length); } //索引體 //_codetable byte[] _codetable = new byte[0x10]; System.arraycopy(indice, 0, _codetable, 0, 0x10); //segment_offset byte[] segment_offset = new byte[0x8]; System.arraycopy(indice, 0x10, segment_offset, 0, 0x8); //segment_size byte[] segment_size = new byte[0x4]; System.arraycopy(indice, 0x18, segment_size, 0, 0x4); System.out.println(String.format("_codetable:%s,segment_offset:0x%s,segment_size:0x%s", bytesToHex(_codetable), Integer.toHexString(toInt(segment_offset)), Integer.toHexString(toInt(segment_size)))); exportVideo(i + 1, segment_offset, segment_size, outPath); } } private void exportVideo(int fileindex, byte[] segment_offset, byte[] segment_size, String outPath) throws IOException { byte[] file = getByteFromFile(toInt(segment_offset), toInt(segment_size)); //前1024字節加密 decrypt_2(file, 1024); byte[] head = new byte[0x3]; System.arraycopy(file, 0, head, 0, 0x3); //System.out.println(new String(head)); String outname = name.substring(name.lastIndexOf(File.separator) + 1); String outFile = outPath + File.separator + outname.substring(0, outname.lastIndexOf(".")) + "-第" + fileindex + "段." + new String(head).toLowerCase(); RandomAccessFile write = new RandomAccessFile(outFile, "rw"); System.out.println("export:" + outFile); write.write(file); write.close(); }
運行結果:
nb_indices:0x7
_unknown_flag:7F
_codetable:A8C47C2906B88AE47E8503C96DAE0494,segment_offset:0x1ee8,segment_size:0x481f161
export:D:\workspace\c\風吹半夏第1集-藍光1080P-第1段.flv
_codetable:4C8578CECBDFA3137A61B7E2BD1C68DC,segment_offset:0x4821049,segment_size:0x506c371
export:D:\workspace\c\風吹半夏第1集-藍光1080P-第2段.flv
_codetable:4BC76F9B4D4CE995F40B42C467D206F8,segment_offset:0x988d3ba,segment_size:0x55f5ce6
export:D:\workspace\c\風吹半夏第1集-藍光1080P-第3段.flv
_codetable:8ED13CCD56AA2367F5EAABEE12043D89,segment_offset:0xee830a0,segment_size:0x4e4a74c
export:D:\workspace\c\風吹半夏第1集-藍光1080P-第4段.flv
_codetable:247B4612415C5B452F5965894A967E19,segment_offset:0x13ccd7ec,segment_size:0x57b6d15
export:D:\workspace\c\風吹半夏第1集-藍光1080P-第5段.flv
_codetable:309400BEF063CFD6BAF19FEB0D4A73A9,segment_offset:0x19484501,segment_size:0x47cf844
export:D:\workspace\c\風吹半夏第1集-藍光1080P-第6段.flv
_codetable:9771B1042CABFC9828767A3D0350F655,segment_offset:0x1dc53d45,segment_size:0x6a3d0cb
export:D:\workspace\c\風吹半夏第1集-藍光1080P-第7段.flv
以上就是“Java怎么實現提取QSV文件視頻內容”這篇文章的所有內容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。