下面类文件中,主要做的工作是:从ftp服务器上下载文件把本地文件替换、添加、或删除功能,在替换本地文件时会先备份一下本地的文件,若整个操作都完成了就会发出commit命令,表示全部替换成功。若中间操作有失败的,则把本地文件回滚到替换前的样子。

描述:

SynchroDataTest.cs(Winform页面类)中的addfiles数组代表要下载到本地的文件(有可能是添加或替换),delfiles数组是要把本地的这些文件删除的数组

  1. string[] addfiles = new string[] { "/SnmpWalk/ReadMe.txt", "/SnmpWalk/SnmpWalk.exe", "/IPMI/WMI取CPU使用率等/net中的WMI编程.docx", "/IPMI/dell IPMI V2 工作原理.docx" };
  2. string[] delfiles = new string[] { "/IPMI/使用IPMI远程控制管理DELL2850服务器.docx", "/IPMI/使用 ipmitool 实现 Linux 系统下对服务器的 ipmi 管理.docx", "/IPMI/使用 ipmit/没有此文件.jpg" };
  1. using System;
  2. using System.Text;
  3. using System.IO;
  4. using System.Net;
  5. using System.Net.Sockets;
  6.  
  7. namespace EricTestProject
  8. {
  9. class FTPClient
  10. {
  11. #region 构造函数
  12. /// <summary>
  13. /// 缺省构造函数
  14. /// </summary>
  15. public FTPClient()
  16. {
  17. strRemoteHost = "";
  18. strRemotePath = "/";
  19. strRemoteUser = "";
  20. strRemotePass = "";
  21. strRemotePort = 21;
  22. bConnected = false;
  23. } /// <summary>
  24. /// 构造函数
  25. /// </summary>
  26. /// <param name="remoteHost"></param>
  27. /// <param name="remotePath"></param>
  28. /// <param name="remoteUser"></param>
  29. /// <param name="remotePass"></param>
  30. /// <param name="remotePort"></param>
  31. public FTPClient(string remoteHost, string remotePath, string remoteUser, string remotePass, int remotePort)
  32. {
  33. strRemoteHost = remoteHost;
  34. strRemotePath = remotePath;
  35. strRemoteUser = remoteUser;
  36. strRemotePass = remotePass;
  37. strRemotePort = remotePort;
  38. Connect();
  39. }
  40. #endregion
  41.  
  42. #region 登陆
  43. /// <summary>
  44. /// FTP服务器IP地址
  45. /// </summary>
  46. private string strRemoteHost;
  47. public string RemoteHost
  48. {
  49. get
  50. {
  51. return strRemoteHost;
  52. }
  53. set
  54. {
  55. strRemoteHost = value;
  56. }
  57. }
  58. /// <summary>
  59. /// FTP服务器端口
  60. /// </summary>
  61. private int strRemotePort;
  62. public int RemotePort
  63. {
  64. get
  65. {
  66. return strRemotePort;
  67. }
  68. set
  69. {
  70. strRemotePort = value;
  71. }
  72. }
  73. /// <summary>
  74. /// 当前服务器目录
  75. /// </summary>
  76. private string strRemotePath;
  77. public string RemotePath
  78. {
  79. get
  80. {
  81. return strRemotePath;
  82. }
  83. set
  84. {
  85. strRemotePath = value;
  86. }
  87. }
  88. /// <summary>
  89. /// 登录用户账号
  90. /// </summary>
  91. private string strRemoteUser;
  92. public string RemoteUser
  93. {
  94. set
  95. {
  96. strRemoteUser = value;
  97. }
  98. }
  99. /// <summary>
  100. /// 用户登录密码
  101. /// </summary>
  102. private string strRemotePass;
  103. public string RemotePass
  104. {
  105. set
  106. {
  107. strRemotePass = value;
  108. }
  109. } /// <summary>
  110. /// 是否登录
  111. /// </summary>
  112. private Boolean bConnected;
  113. public bool Connected
  114. {
  115. get
  116. {
  117. return bConnected;
  118. }
  119. }
  120. #endregion
  121.  
  122. #region 链接
  123. /// <summary>
  124. /// 建立连接
  125. /// </summary>
  126. public void Connect()
  127. {
  128. socketControl = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  129. IPEndPoint ep = new IPEndPoint(IPAddress.Parse(RemoteHost), strRemotePort);
  130. // 链接
  131. try
  132. {
  133. socketControl.Connect(ep);
  134. }
  135. catch (Exception)
  136. {
  137. throw new IOException("Couldn't connect to remote server");
  138. } // 获取应答码
  139. ReadReply();
  140. if (iReplyCode != 220)
  141. {
  142. DisConnect();
  143. throw new IOException(strReply.Substring(4));
  144. } // 登陆
  145. SendCommand("USER " + strRemoteUser);
  146. if (!(iReplyCode == 331 || iReplyCode == 230))
  147. {
  148. CloseSocketConnect();//关闭连接
  149. throw new IOException(strReply.Substring(4));
  150. }
  151. if (iReplyCode != 230)
  152. {
  153. SendCommand("PASS " + strRemotePass);
  154. if (!(iReplyCode == 230 || iReplyCode == 202)
  155.  
  156. )
  157. {
  158. CloseSocketConnect();//关闭连接
  159. throw new IOException
  160.  
  161. (strReply.Substring(4));
  162. }
  163. }
  164. bConnected = true; // 切换到目录
  165. ChDir(strRemotePath);
  166. }
  167. /// <summary>
  168. /// 关闭连接
  169. /// </summary>
  170. public void DisConnect()
  171. {
  172. if (socketControl != null)
  173. {
  174. SendCommand("QUIT");
  175. }
  176. CloseSocketConnect();
  177. }
  178. #endregion
  179.  
  180. #region 传输模式 /// <summary>
  181. /// 传输模式:二进制类型、ASCII类型
  182. /// </summary>
  183. public enum TransferType { Binary, ASCII }; /// <summary>
  184. /// 设置传输模式
  185. /// </summary>
  186. /// <param name="ttType">传输模式</param>
  187. public void SetTransferType(TransferType ttType)
  188. {
  189. if (ttType == TransferType.Binary)
  190. {
  191. SendCommand("TYPE I");//binary类型传输
  192. }
  193. else
  194. {
  195. SendCommand("TYPE A");//ASCII类型传输
  196. }
  197. if (iReplyCode != 200)
  198. {
  199. throw new IOException(strReply.Substring(4));
  200. }
  201. else
  202. {
  203. trType = ttType;
  204. }
  205. }
  206. /// <summary>
  207. /// 获得传输模式
  208. /// </summary>
  209. /// <returns>传输模式</returns>
  210. public TransferType GetTransferType()
  211. {
  212. return trType;
  213. }
  214.  
  215. #endregion
  216.  
  217. #region 文件操作
  218. /// <summary>
  219. /// 获得文件列表
  220. /// </summary>
  221. /// <param name="strMask">文件名的匹配字符串</param>
  222. /// <returns></returns>
  223. public string[] Dir(string strMask)
  224. {
  225. // 建立链接
  226. if (!bConnected)
  227. {
  228. Connect();
  229. } //建立进行数据连接的socket
  230. Socket socketData = CreateDataSocket();
  231.  
  232. //传送命令
  233. SendCommand("NLST " + strMask); //分析应答代码
  234. if (!(iReplyCode == 150 || iReplyCode == 125 ||iReplyCode == 226))
  235. {
  236. throw new IOException(strReply.Substring(4));
  237. } //获得结果
  238. strMsg = "";
  239. while (true)
  240. {
  241. int iBytes = socketData.Receive(buffer,buffer.Length, 0);
  242. strMsg += Utf8Coding.GetString(buffer, 0, iBytes);
  243. if (iBytes < buffer.Length)
  244. {
  245. break;
  246. }
  247. }
  248. //char[] seperator = { '\n' };
  249. string[] strsFileList = strMsg.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
  250.  
  251. socketData.Close();//数据socket关闭时也会有返回码
  252. if (iReplyCode != 226)
  253. {
  254. ReadReply();
  255. if (iReplyCode != 226)
  256. {
  257. throw new IOException
  258.  
  259. (strReply.Substring(4));
  260. }
  261. }
  262. return strsFileList;
  263. }
  264. /// <summary>
  265. /// 获取文件大小
  266. /// </summary>
  267. /// <param name="strFileName">文件名</param>
  268. /// <returns>文件大小</returns>
  269. private long GetFileSize(string strFileName)
  270. {
  271. if (!bConnected)
  272. {
  273. Connect();
  274. }
  275. SendCommand("SIZE " + Path.GetFileName(strFileName));
  276. long lSize = 0;
  277. if (iReplyCode == 213)
  278. {
  279. lSize = Int64.Parse(strReply.Substring(4));
  280. }
  281. else
  282. {
  283. throw new IOException(strReply.Substring(4));
  284. }
  285. return lSize;
  286. }
  287. /// <summary>
  288. /// 删除
  289. /// </summary>
  290. /// <param name="strFileName">待删除文件名</param>
  291. public void Delete(string strFileName)
  292. {
  293. if (!bConnected)
  294. {
  295. Connect();
  296. }
  297. SendCommand("DELE " + strFileName);
  298. if (iReplyCode != 250)
  299. {
  300. throw new IOException(strReply.Substring(4));
  301. }
  302. }
  303. /// <summary>
  304. /// 重命名(如果新文件名与已有文件重名,将覆盖已有文件)
  305. /// </summary>
  306. /// <param name="strOldFileName">旧文件名</param>
  307. /// <param name="strNewFileName">新文件名</param>
  308. public void Rename(string strOldFileName, string strNewFileName)
  309. {
  310. if (!bConnected)
  311. {
  312. Connect();
  313. }
  314. SendCommand("RNFR " + strOldFileName);
  315. if (iReplyCode != 350)
  316. {
  317. throw new IOException(strReply.Substring(4));
  318. }
  319. // 如果新文件名与原有文件重名,将覆盖原有文件
  320. SendCommand("RNTO " + strNewFileName);
  321. if (iReplyCode != 250)
  322. {
  323. throw new IOException(strReply.Substring(4));
  324. }
  325. }
  326. #endregion
  327.  
  328. #region 上传和下载
  329. /// <summary>
  330. /// 下载一批文件
  331. /// </summary>
  332. /// <param name="strFileNameMask">文件名的匹配字符串</param>
  333. /// <param name="strFolder">本地目录(不得以\结束)</param>
  334. public void Get(string strFileNameMask, string strFolder)
  335. {
  336. if (!bConnected)
  337. {
  338. Connect();
  339. }
  340. string[] strFiles = Dir(strFileNameMask);
  341. foreach (string strFile in strFiles)
  342. {
  343. if (!strFile.Equals(""))//一般来说strFiles的最后一个元素可能是空字符串
  344. {
  345. Get(strFile, strFolder, strFile);
  346. }
  347. }
  348. }
  349. /// <summary>
  350. /// 下载一个文件
  351. /// </summary>
  352. /// <param name="strRemoteFileName">要下载的文件名</param>
  353. /// <param name="strFolder">本地目录(不得以\结束)</param>
  354. /// <param name="strLocalFileName">保存在本地时的文件名</param>
  355. public void Get(string strRemoteFileName, string strFolder, string strLocalFileName)
  356. {
  357. if (!bConnected)
  358. {
  359. Connect();
  360. }
  361. SetTransferType(TransferType.Binary);
  362. if (strLocalFileName.Equals(""))
  363. {
  364. strLocalFileName = strRemoteFileName;
  365. }
  366. if (!File.Exists(strLocalFileName))
  367. {
  368. Stream st = File.Create(strLocalFileName);
  369. st.Close();
  370. }
  371. //如果下载文件夹中已有此文件,则删除此文件在创建
  372. if (File.Exists(strFolder + "\\" + strLocalFileName))
  373. {
  374. File.Delete(strFolder + "\\" + strLocalFileName);
  375. }
  376. FileStream output = new FileStream(strFolder + "\\" + strLocalFileName, FileMode.Create);
  377. Socket socketData = CreateDataSocket();
  378. SendCommand("RETR " + strRemoteFileName);
  379. if (!(iReplyCode == 150 || iReplyCode == 125
  380. || iReplyCode == 226 || iReplyCode == 250))
  381. {
  382. throw new IOException(strReply.Substring(4));
  383. }
  384. while (true)
  385. {
  386. int iBytes = socketData.Receive(buffer, buffer.Length, 0);
  387. output.Write(buffer, 0, iBytes);
  388. if (iBytes <= 0)
  389. {
  390. break;
  391. }
  392. }
  393. output.Close();
  394. if (socketData.Connected)
  395. {
  396. socketData.Close();
  397. }
  398. if (!(iReplyCode == 226 || iReplyCode == 250))
  399. {
  400. ReadReply();
  401. if (!(iReplyCode == 226 || iReplyCode == 250))
  402. {
  403. throw new IOException(strReply.Substring(4));
  404. }
  405. }
  406. }
  407. /// <summary>
  408. /// 上传一批文件
  409. /// </summary>
  410. /// <param name="strFolder">本地目录(不得以\结束)</param>
  411. /// <param name="strFileNameMask">文件名匹配字符(可以包含*和?)</param>
  412. public void Put(string strFolder, string strFileNameMask)
  413. {
  414. string[] strFiles = Directory.GetFiles
  415.  
  416. (strFolder, strFileNameMask);
  417. foreach (string strFile in strFiles)
  418. {
  419. //strFile是完整的文件名(包含路径)
  420. Put(strFile);
  421. }
  422. }
  423. /// <summary>
  424. /// 上传一个文件
  425. /// </summary>
  426. /// <param name="strFileName">本地文件名</param>
  427. public void Put(string strFileName)
  428. {
  429. if (!bConnected)
  430. {
  431. Connect();
  432. }
  433. Socket socketData = CreateDataSocket();
  434. SendCommand("STOR " + Path.GetFileName(strFileName));
  435. if (!(iReplyCode == 125 || iReplyCode == 150))
  436. {
  437. throw new IOException(strReply.Substring(4));
  438. }
  439. FileStream input = new FileStream(strFileName, FileMode.Open);
  440. int iBytes = 0;
  441. while ((iBytes = input.Read(buffer, 0, buffer.Length)) > 0)
  442. {
  443. socketData.Send(buffer, iBytes, 0);
  444. }
  445. input.Close();
  446. if (socketData.Connected)
  447. {
  448. socketData.Close();
  449. }
  450. if (!(iReplyCode == 226 || iReplyCode == 250))
  451. {
  452. ReadReply();
  453. if (!(iReplyCode == 226 || iReplyCode == 250))
  454. {
  455. throw new IOException(strReply.Substring(4));
  456. }
  457. }
  458. }
  459.  
  460. #endregion
  461.  
  462. #region 目录操作
  463. /// <summary>
  464. /// 创建目录
  465. /// </summary>
  466. /// <param name="strDirName">目录名</param>
  467. public void MkDir(string strDirName)
  468. {
  469. if (!bConnected)
  470. {
  471. Connect();
  472. }
  473. SendCommand("MKD " + strDirName);
  474. if (iReplyCode != 257)
  475. {
  476. throw new IOException(strReply.Substring(4));
  477. }
  478. }
  479.  
  480. /// <summary>
  481. /// 删除目录
  482. /// </summary>
  483. /// <param name="strDirName">目录名</param>
  484. public void RmDir(string strDirName)
  485. {
  486. if (!bConnected)
  487. {
  488. Connect();
  489. }
  490. SendCommand("RMD " + strDirName);
  491. if (iReplyCode != 250)
  492. {
  493. throw new IOException(strReply.Substring(4));
  494. }
  495. }
  496.  
  497. /// <summary>
  498. /// 改变目录
  499. /// </summary>
  500. /// <param name="strDirName">新的工作目录名</param>
  501. public void ChDir(string strDirName)
  502. {
  503. if (strDirName.Equals(".") || strDirName.Equals(""))
  504. {
  505. return;
  506. }
  507. if (!bConnected)
  508. {
  509. Connect();
  510. }
  511. SendCommand("CWD " + strDirName);
  512. if (iReplyCode != 250)
  513. {
  514. throw new IOException(strReply.Substring(4));
  515. }
  516. this.strRemotePath = strDirName;
  517. }
  518.  
  519. #endregion
  520.  
  521. #region 内部变量
  522. /// <summary>
  523. /// 服务器返回的应答信息(包含应答码)
  524. /// </summary>
  525. private string strMsg;
  526. /// <summary>
  527. /// 服务器返回的应答信息(包含应答码)
  528. /// </summary>
  529. private string strReply;
  530. /// <summary>
  531. /// 服务器返回的应答码
  532. /// </summary>
  533. private int iReplyCode;
  534. /// <summary>
  535. /// 进行控制连接的socket
  536. /// </summary>
  537. private Socket socketControl;
  538. /// <summary>
  539. /// 传输模式
  540. /// </summary>
  541. private TransferType trType;
  542. /// <summary>
  543. /// 接收和发送数据的缓冲区
  544. /// </summary>
  545. private static int BLOCK_SIZE = 512;
  546. Byte[] buffer = new Byte[BLOCK_SIZE];
  547. /// <summary>
  548. /// 编码方式
  549. /// </summary>
  550. Encoding Utf8Coding = Encoding.UTF8;
  551. //Encoding ASCII = Encoding.ASCII;
  552. #endregion
  553.  
  554. #region 内部函数
  555.  
  556. /// <summary>
  557. /// 将一行应答字符串记录在strReply和strMsg
  558. /// 应答码记录在iReplyCode
  559. /// </summary>
  560. private void ReadReply()
  561. {
  562. strMsg = "";
  563. strReply = ReadLine();
  564. iReplyCode = Int32.Parse(strReply.Substring(0, 3));
  565. }
  566.  
  567. /// <summary>
  568. /// 建立进行数据连接的socket
  569. /// </summary>
  570. /// <returns>数据连接socket</returns>
  571. private Socket CreateDataSocket()
  572. {
  573. SendCommand("PASV");
  574. if (iReplyCode != 227)
  575. {
  576. throw new IOException(strReply.Substring(4));
  577. }
  578. int index1 = strReply.IndexOf('(');
  579. int index2 = strReply.IndexOf(')');
  580. string ipData =
  581. strReply.Substring(index1 + 1, index2 - index1 - 1);
  582. int[] parts = new int[6];
  583. int len = ipData.Length;
  584. int partCount = 0;
  585. string buf = "";
  586. for (int i = 0; i < len && partCount <= 6; i++)
  587. {
  588. char ch = Char.Parse(ipData.Substring(i, 1));
  589. if (Char.IsDigit(ch))
  590. buf += ch;
  591. else if (ch != ',')
  592. {
  593. throw new IOException("Malformed PASV strReply: " +
  594. strReply);
  595. }
  596. if (ch == ',' || i + 1 == len)
  597. {
  598. try
  599. {
  600. parts[partCount++] = Int32.Parse(buf);
  601. buf = "";
  602. }
  603. catch (Exception)
  604. {
  605. throw new IOException("Malformed PASV strReply: " + strReply);
  606. }
  607. }
  608. }
  609. string ipAddress = parts[0] + "." + parts[1] + "." +
  610. parts[2] + "." + parts[3];
  611. int port = (parts[4] << 8) + parts[5];
  612. Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  613. IPEndPoint ep = new IPEndPoint(IPAddress.Parse(ipAddress), port);
  614. try
  615. {
  616. s.Connect(ep);
  617. }
  618. catch (Exception)
  619. {
  620. throw new IOException("Can't connect to remote server");
  621. }
  622. return s;
  623. }
  624. /// <summary>
  625. /// 关闭socket连接(用于登录以前)
  626. /// </summary>
  627. private void CloseSocketConnect()
  628. {
  629. if (socketControl != null)
  630. {
  631. socketControl.Close();
  632. socketControl = null;
  633. }
  634. bConnected = false;
  635. }
  636.  
  637. /// <summary>
  638. /// 读取Socket返回的所有字符串
  639. /// </summary>
  640. /// <returns>包含应答码的字符串行</returns>
  641. private string ReadLine()
  642. {
  643. while (true)
  644. {
  645. int iBytes = socketControl.Receive(buffer,
  646.  
  647. buffer.Length, 0);
  648. strMsg += Utf8Coding.GetString(buffer, 0, iBytes);
  649. if (iBytes < buffer.Length)
  650. {
  651. break;
  652. }
  653. }
  654. char[] seperator = { '\n' };
  655. string[] mess = strMsg.Split(seperator);
  656. if (strMsg.Length > 2)
  657. {
  658. strMsg = mess[mess.Length - 2];
  659. //seperator[0]是10,换行符是由13和0组成的,分隔后10后面虽没有字符串,
  660. //但也会分配为空字符串给后面(也是最后一个)字符串数组,
  661. //所以最后一个mess是没用的空字符串
  662. //但为什么不直接取mess[0],因为只有最后一行字符串应答码与信息之间有空格
  663. }
  664. else
  665. {
  666. strMsg = mess[0];
  667. }
  668. if (!strMsg.Substring(3, 1).Equals(" "))//返回字符串正确的是以应答码(如220开头,后面接一空格,再接问候字符串)
  669. {
  670. return ReadLine();
  671. }
  672. return strMsg;
  673. }
  674. /// <summary>
  675. /// 发送命令并获取应答码和最后一行应答字符串
  676. /// </summary>
  677. /// <param name="strCommand">命令</param>
  678. private void SendCommand(String strCommand)
  679. {
  680. Byte[] cmdBytes = Utf8Coding.GetBytes((strCommand + "\r\n").ToCharArray());
  681. socketControl.Send(cmdBytes, cmdBytes.Length, 0);
  682. ReadReply();
  683. }
  684. #endregion
  685.  
  686. }
  687. }

C#通过FTP账号上传、修改、删除文件 FTPClient的更多相关文章

  1. java FTP 上传下载删除文件

    在JAVA程序中,经常需要和FTP打交道,比如向FTP服务器上传文件.下载文件,本文简单介绍如何利用jakarta commons中的FTPClient(在commons-net包中)实现上传下载文件 ...

  2. 使用ftp软件上传下载php文件时换行丢失bug

    正 文:   在使用ftp软件上传下载php源文件时,我们偶尔会发现在本地windows下notepad++编辑器写好的php文件,在使用ftp上传到linux服务器后,php文件的换行符全部丢失了, ...

  3. 使用ftp软件上传下载php文件时换行丢失bug(全部变为一行)

    文章来源:http://www.piaoyi.org/computer/ftp-php-r-n-bug.html 正 文: 在使用ftp软件上传下载php源文件时,我们偶尔会发现在本地windows下 ...

  4. Linux学习笔记:使用ftp命令上传和下载文件

    Linux中如何使用ftp命令,包括如何连接ftp服务器,上传or下载文件以及创建文件夹.虽然现在有很多ftp桌面应用(例如:FlashFXP),但是在服务器.SSH.远程会话中掌握命令行ftp的使用 ...

  5. ****使用ftp软件上传下载php文件时换行符丢失bug

    在使用ftp软件上传下载php源文件时,我们偶尔会发现在本地windows下notepad++编辑器写好的php文件,在使用ftp上传到linux服务器后,php文件的换行符全部丢失了,导致php文件 ...

  6. FTP服务器上传,下载文件

    public class FtpUtil { /** * * @param host FTP服务器地址 * @param port FTP服务器端口 * @param username FTP登录账号 ...

  7. github 上传或删除 文件 命令

    git clone https://github.com/onionhacker/bananaproxy.git cd ~/../.. git config --global user.email & ...

  8. 通过代码链接ftp上传下载删除文件

    因为我的项目是Maven项目,首先要导入一个Maven库里的包:pom.xml <dependency>            <groupId>com.jcraft</ ...

  9. 七牛云-上传、删除文件,工具类(Day49)

    要求: 1. java1.8以上 2. Maven: 这里的version指定了一个版本范围,每次更新pom.xml的时候会尝试去下载7.5.x版本中的最新版本,你可以手动指定一个固定的版本. < ...

随机推荐

  1. bounds的深入研究

    一.bounds的深入研究 1>frame:是以父控件的左上角为原点,描述的是一块区域的可视范围,    bounds:是以自己内容左上角为原点,描述的是可视范围在内容范围显示的区域 2> ...

  2. 编程书籍分享--pdf

    作为程序员,我觉得我们应该多学习.多思考.多分享. 今天就花费了一点时间把这几年搜集的编程资料上传到了网上做个分享, 其中涵盖.net .java.js.html5.css3.mysql.sqlser ...

  3. MYSQL ERROR 1130: Host is not allowed to connect to this MySQL server

    今天安装MYSQL遇到MYSQL ERROR 1130: Host is not allowed to connect to this MySQL server, 试了很多办法都不行 skip-gra ...

  4. 加密算法 - RSA

    与DES不同,RSA算法中,每个通信主体都有两个钥匙,一个公钥一个私钥. 就是有2把钥匙1.使用publicKey可以对数据进行加密2.使用Key才能对数据进行解密单方向传输用公钥加密的数据,只有私钥 ...

  5. CSS3 calc() 会计算的属性

    calc是英文单词calculate(计算)的缩写,是css3的一个新增的功能,你可以使用calc()给元素的border.margin.pading.font-size和width等属性设置动态值. ...

  6. hbase rowkey设计的注意事项

    充分利用有序性 1.1 如果要scan操作,且不是很频繁,可以利用rowkey的有序性将需要一起扫描的数据放到一起.例如直接用时间戳.这样就可以按时间scan了.这个只要是简单的全表扫描都行. 1.2 ...

  7. Qt的事件模型(5种使用办法,通常重新实现event handler即可。只有定义控件才需要管理信号的发射)

    Qt的事件模型 1.事件的概念 应用程序对象将系统消息接收为 Qt 事件.应用程序可以按照不同的粒度对事件加以监控.过滤并做出响应. 在 Qt 中,事件是指从 QEvent继承 的对象.Qt将事件发送 ...

  8. Windows.document对象

    一.找到元素: docunment.getElementById("id"):根据id找,最多找一个:var a =docunment.getElementById("i ...

  9. 【CF】196 Div.2 D. Book of Evil

    显然这个图是一课树,看着题目首先联想到LCA(肯定是可以解的).但是看了一下数据大小,应该会TLE.然后,忽然想到一个前面做过的题目,大概是在一定条件下树中某结点旋转成为根后查询最长路径.结果灵感就来 ...

  10. C++ Prime:指针和const

    与引用一样,也可以令指针指向常量或非常量,类似于常量引用,指向常量的指针不能用于改变其所指对象的值.要想存放常量对象的地址,只能使用指向常量的指针: const double pi = 3.14; / ...