一、字符编码工具

1.1 中文转Unicode

1
2
3
4
5
6
7
8
9
10
11
12
public static String unicodeEncode(String string) {
char[] utfBytes = string.toCharArray();
String unicodeBytes = "";
for (int i = 0; i < utfBytes.length; i++) {
String hexB = Integer.toHexString(utfBytes[i]);
if (hexB.length() <= 2) {
hexB = "00" + hexB;
}
unicodeBytes = unicodeBytes + "\\u" + hexB;
}
return unicodeBytes;
}

1.2 Unicode转中文

1
2
3
4
5
6
7
8
9
10
public static String unicodeDecode(String string) {
Pattern pattern = Pattern.compile("(\\\\u(\\p{XDigit}{4}))");
Matcher matcher = pattern.matcher(string);
char ch;
while (matcher.find()) {
ch = (char) Integer.parseInt(matcher.group(2), 16);
string = string.replace(matcher.group(1), ch + "");
}
return string;
}

1.3 字符串转为16进制字符串

1
2
3
4
5
6
7
8
9
10
11
12
public static String encode(String text) {
if (null == text) {
return null;
}

StringBuffer buf = new StringBuffer();
byte[] bytes = text.getBytes();
for (byte b : bytes) {
buf.append(String.format("%02x", b));
}
return buf.toString();
}

1.4 16进制字符串转普通字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public static String decode(String encodeStr) {
if (null == encodeStr) {
return null;
}

// 一个字节会转为两个16进制字符
if (encodeStr.length() % 2 != 0) {
throw new IllegalArgumentException("错误的编码字符串");
}

byte[] bytes = new byte[encodeStr.length() / 2];
for (int i = 0; i < bytes.length; i++) {
bytes[i] = (byte) Integer.parseInt(encodeStr.substring(i * 2, i * 2 + 2), 16);
}

return new String(bytes);
}

1.5 汉字 转换为对应的 UTF-8编码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public static String convertStringToUTF8(String s) {
if (s == null || s.equals("")) {
return null;
}
StringBuffer sb = new StringBuffer();
try {
char c;
for (int i = 0; i < s.length(); i++) {
c = s.charAt(i);
if (c >= 0 && c <= 255) {
sb.append(c);
} else {
byte[] b;
b = Character.toString(c).getBytes("utf-8");
for (int j = 0; j < b.length; j++) {
int k = b[j];
// 转换为unsigned integer 无符号integer
/*
* if (k < 0) k += 256;
*/
k = k < 0 ? k + 256 : k;
// 返回整数参数的字符串表示形式 作为十六进制(base16)中的无符号整数
// 该值以十六进制(base16)转换为ASCII数字的字符串
sb.append(Integer.toHexString(k).toUpperCase());

// url转置形式
// sb.append("%" +Integer.toHexString(k).toUpperCase());
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return sb.toString();
}

1.6 UTF-8编码 转换为对应的 汉字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public static String convertUTF8ToString(String s) {
if (s == null || s.equals("")) {
return null;
}
try {
s = s.toUpperCase();
int total = s.length() / 2;
// 标识字节长度
int pos = 0;
byte[] buffer = new byte[total];
for (int i = 0; i < total; i++) {
int start = i * 2;
// 将字符串参数解析为第二个参数指定的基数中的有符号整数。
buffer[i] = (byte) Integer.parseInt(s.substring(start, start + 2), 16);
pos++;
}
// 通过使用指定的字符集解码指定的字节子阵列来构造一个新的字符串。
// 新字符串的长度是字符集的函数,因此可能不等于子数组的长度。
return new String(buffer, 0, pos, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return s;
}

二、http工具

2.1 get基础工具

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public static String sendArgsGet(String url, String param, HashMap<String,String> args) {
String result = "";
BufferedReader read= null;
try {
String urlNameString = url + "?" + param;
URL realUrl = new URL(urlNameString);
// 打开和URL之间的连接
URLConnection conn = realUrl.openConnection();
// 设置通用的请求属性
for(String key : args.keySet() ){
conn.setRequestProperty(key,args.get(key));
}
conn.setReadTimeout(8000);
// 建立实际的连接
conn.connect();
// 获取所有响应头字段
//Map<String, List<String>> map = connection.getHeaderFields();
// 遍历所有的响应头字段
//for (String key : map.keySet()) {
// System.out.println(key + "--->" + map.get(key));
//}
// 定义 BufferedReader输入流来读取URL的响应
read= new BufferedReader(new InputStreamReader(
conn.getInputStream()));
String line;
while ((line = read.readLine()) != null) {
result += line;
}
} catch (Exception e) {
System.out.println("发送GET请求出现异常!" + e);
e.printStackTrace();
}
// 使用finally块来关闭输入流
finally {
try {
if (read!= null) {
read.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
return result;
}

使用方法:

1
2
3
4
5
6
7
8
9
private static void getTest(){
String url = "https://c.runoob.com/wp-content/themes/toolrunoob/option/ajax.php";
String msg = "type=checkIP&REMOTE_ADDR="+"125.72.228.21";

HashMap<String, String> arg = new HashMap<String,String>();
arg.put("Content-Type","application/json;charset=utf-8");

System.out.println(sendArgsGet(url,msg,arg));
}

2.2 post基础工具

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
public static String sendArgsPost(String url, String param, HashMap<String,String> args) {
PrintWriter out = null;
BufferedReader read = null;
String result = "";
try {
URL realUrl = new URL(url);
// 打开和URL之间的连接
URLConnection conn = realUrl.openConnection();
// 设置通用的请求属性
for(String key : args.keySet() ){
conn.setRequestProperty(key,args.get(key));
}

// 发送POST请求必须设置如下两行
conn.setDoOutput(true);
conn.setDoInput(true);
// 获取URLConnection对象对应的输出流
out = new PrintWriter(conn.getOutputStream());
// 发送请求参数
out.print(param);
// flush输出流的缓冲
out.flush();
// 定义BufferedReader输入流来读取URL的响应
read = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line;
while ((line = read.readLine()) != null) {
result += line;
}
} catch (Exception e) {
System.out.println("发送 POST 请求出现异常!" + e);
e.printStackTrace();
}
// 使用finally块来关闭输出流、输入流
finally {
try {
if (out != null) {
out.close();
}
if (read != null) {
read.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
return result;
}

使用方法:

1
2
3
4
5
6
7
8
9
10
private static void postTest(){
String url = "http://xxxxxxx:xxx/serviceAgent/rest/bestpay/queryKfVouMerchantInfo";
String msg = "{\"appkey\":\"6004050001\",\"activityType\":\"VOUCHER\",\"merchantCode\":\"3178000008997749\",\"pageNum\":0,\"pageSize\":0,\"provinceCode\":\"999900\"}";


HashMap<String, String> arg = new HashMap<String,String>();
arg.put("Content-Type","application/json;charset=utf-8");

System.out.println(sendArgsPost(url,msg,arg));
}

三、https工具

公用方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
    private static final class DefaultTrustManager implements X509TrustManager {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}

@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}

@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}

private static HttpsURLConnection getHttpsURLConnection(String uri, String method) throws IOException {
SSLContext ctx = null;
try {
ctx = SSLContext.getInstance("TLS");
ctx.init(new KeyManager[0], new TrustManager[] { new DefaultTrustManager() }, new SecureRandom());
} catch (KeyManagementException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
SSLSocketFactory ssf = ctx.getSocketFactory();

URL url = new URL(uri);
HttpsURLConnection httpsConn = (HttpsURLConnection) url.openConnection();
httpsConn.setSSLSocketFactory(ssf);
httpsConn.setHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String arg0, SSLSession arg1) {
return true;
}
});
httpsConn.setRequestMethod(method);
httpsConn.setDoInput(true);
httpsConn.setDoOutput(true);
return httpsConn;
}

private static byte[] getBytesFromStream(InputStream is) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] kb = new byte[1024];
int len;
while ((len = is.read(kb)) != -1) {
baos.write(kb, 0, len);
}
byte[] bytes = baos.toByteArray();
baos.close();
is.close();
return bytes;
}

private static void setBytesToStream(OutputStream os, byte[] bytes) throws IOException {
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
byte[] kb = new byte[1024];
int len;
while ((len = bais.read(kb)) != -1) {
os.write(kb, 0, len);
}
os.flush();
os.close();
bais.close();
}

3.1 get基础工具

1
2
3
4
5
6
7
8
9
public static String sendGet(String url, String param, HashMap<String,String> args) throws IOException {
String urlNameString = url + "?" + param;
HttpsURLConnection httpsConn = getHttpsURLConnection(urlNameString, "GET");
// 设置通用的请求属性
for(String key : args.keySet() ){
httpsConn.setRequestProperty(key,args.get(key));
}
return new String(getBytesFromStream(httpsConn.getInputStream()));
}

3.2 post基础工具

1
2
3
4
5
6
7
8
9
public static String sendPost(String url, String param, HashMap<String,String> args) throws IOException {
HttpsURLConnection httpsConn = getHttpsURLConnection(url, "POST");
// 设置通用的请求属性
for(String key : args.keySet() ){
httpsConn.setRequestProperty(key,args.get(key));
}
setBytesToStream(httpsConn.getOutputStream(), param.getBytes());
return new String(getBytesFromStream(httpsConn.getInputStream()));
}

四、ftp工具

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
@Slf4j
public class FtpUtil {

/*
public static void main(String args[]) {
try {
//1.获取连接
FTPClient ftpClient = FtpUtil.connectFtpServer("ip", port, "user", "passwd", "UTF-8");
uploadFile(ftpClient,new File("D:\\Program Files\\sts-bundle\\sts-3.9.4.RELEASE\\lombok.jar"),"/home/fendo/tt");
FtpUtil.closeFTPConnect(ftpClient);
} catch (Exception e) {
e.printStackTrace();
}
}
*/

/**
* 连接 FTP 服务器
*
* @param addr FTP 服务器 IP 地址
* @param port FTP 服务器端口号
* @param username 登录用户名
* @param password 登录密码
* @return
* @throws Exception
*/
public static FTPClient connectFtpServer(String addr, int port, String username, String password, String controlEncoding) {
FTPClient ftpClient = new FTPClient();
try {
/**设置文件传输的编码*/
ftpClient.setControlEncoding(controlEncoding);

/**连接 FTP 服务器
* 如果连接失败,则此时抛出异常,如ftp服务器服务关闭时,抛出异常:
* java.net.ConnectException: Connection refused: connect*/
ftpClient.connect(addr, port);
/**登录 FTP 服务器
* 1)如果传入的账号为空,则使用匿名登录,此时账号使用 "Anonymous",密码为空即可*/
if (StringUtils.isBlank(username)) {
ftpClient.login("Anonymous", "");
} else {
ftpClient.login(username, password);
}

/** 设置传输的文件类型
* BINARY_FILE_TYPE:二进制文件类型
* ASCII_FILE_TYPE:ASCII传输方式,这是默认的方式
* ....
*/
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);

ftpClient.enterLocalPassiveMode();//设置ftp上传为被动模式,防止上传文件为空

/**
* 确认应答状态码是否正确完成响应
* 凡是 2开头的 isPositiveCompletion 都会返回 true,因为它底层判断是:
* return (reply >= 200 && reply < 300);
*/
int reply = ftpClient.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
/**
* 如果 FTP 服务器响应错误 中断传输、断开连接
* abort:中断文件正在进行的文件传输,成功时返回 true,否则返回 false
* disconnect:断开与服务器的连接,并恢复默认参数值
*/
ftpClient.abort();
ftpClient.disconnect();
} else {
}
} catch (IOException e) {
e.printStackTrace();
log.error(">>>>>FTP服务器连接登录失败,请检查连接参数是否正确,或者网络是否通畅*********");
}
return ftpClient;
}

/**
* 使用完毕,应该及时关闭连接
* 终止 ftp 传输
* 断开 ftp 连接
*
* @param ftpClient
* @return
*/
public static FTPClient closeFTPConnect(FTPClient ftpClient) {
try {
if (ftpClient != null && ftpClient.isConnected()) {
ftpClient.abort();
ftpClient.disconnect();
}
} catch (IOException e) {
e.printStackTrace();
}
return ftpClient;
}

/**
* 下载 FTP 服务器上指定的单个文件,而且本地存放的文件相对部分路径 会与 FTP 服务器结构保持一致
*
* @param ftpClient :连接成功有效的 FTP客户端连接
* @param absoluteLocalDirectory :本地存储文件的绝对路径,如 E:\gxg\ftpDownload
* @param relativeRemotePath :ftpFile 文件在服务器所在的绝对路径,此方法强制路径使用右斜杠"\",如 "\video\2018.mp4"
* @return
*/
public static void downloadSingleFile(FTPClient ftpClient, String absoluteLocalDirectory, String relativeRemotePath) {
/**如果 FTP 连接已经关闭,或者连接无效,则直接返回*/
if (!ftpClient.isConnected() || !ftpClient.isAvailable()) {
log.error(">>>>>FTP服务器连接已经关闭或者连接无效*********");
return;
}
if (StringUtils.isBlank(absoluteLocalDirectory) || StringUtils.isBlank(relativeRemotePath)) {
log.error(">>>>>下载时遇到本地存储路径或者ftp服务器文件路径为空,放弃...*********");
return;
}
try {
/**没有对应路径时,FTPFile[] 大小为0,不会为null*/
FTPFile[] ftpFiles = ftpClient.listFiles(relativeRemotePath);
FTPFile ftpFile = null;
if (ftpFiles.length >= 1) {
ftpFile = ftpFiles[0];
}
if (ftpFile != null && ftpFile.isFile()) {
/** ftpFile.getName():获取的是文件名称,如 123.mp4
* 必须保证文件存放的父目录必须存在,否则 retrieveFile 保存文件时报错
*/
File localFile = new File(absoluteLocalDirectory, relativeRemotePath);
if (!localFile.getParentFile().exists()) {
localFile.getParentFile().mkdirs();
}
OutputStream outputStream = new FileOutputStream(localFile);
String workDir = relativeRemotePath.substring(0, relativeRemotePath.lastIndexOf("\\"));
if (StringUtils.isBlank(workDir)) {
workDir = "/";
}
/**文件下载前,FTPClient工作目录必须切换到文件所在的目录,否则下载失败
* "/" 表示用户根目录*/
ftpClient.changeWorkingDirectory(workDir);
/**下载指定的 FTP 文件 到本地
* 1)注意只能是文件,不能直接下载整个目录
* 2)如果文件本地已经存在,默认会重新下载
* 3)下载文件之前,ftpClient 工作目录必须是下载文件所在的目录
* 4)下载成功返回 true,失败返回 false
*/
ftpClient.retrieveFile(ftpFile.getName(), outputStream);

outputStream.flush();
outputStream.close();
log.info(">>>>>FTP服务器文件下载完毕*********" + ftpFile.getName());
}
} catch (IOException e) {
e.printStackTrace();
}
}

/**
* 遍历 FTP 服务器指定目录下的所有文件(包含子孙文件)
*
* @param ftpClient :连接成功有效的 FTP客户端连接
* @param remotePath :查询的 FTP 服务器目录,如果文件,则视为无效,使用绝对路径,如"/"、"/video"、"\\"、"\\video"
* @param relativePathList :返回查询结果,其中为服务器目录下的文件相对路径,如:\1.png、\docs\overview-tree.html 等
* @return
*/
public static List<String> loopServerPath(FTPClient ftpClient, String remotePath, List<String> relativePathList) {
/**如果 FTP 连接已经关闭,或者连接无效,则直接返回*/
if (!ftpClient.isConnected() || !ftpClient.isAvailable()) {
log.error("ftp 连接已经关闭或者连接无效......");
return relativePathList;
}
try {
/**转移到FTP服务器根目录下的指定子目录
* 1)"/":表示用户的根目录,为空时表示不变更
* 2)参数必须是目录,当是文件时改变路径无效
* */
ftpClient.changeWorkingDirectory(remotePath);
/** listFiles:获取FtpClient连接的当前下的一级文件列表(包括子目录)
* 1)FTPFile[] ftpFiles = ftpClient.listFiles("/docs/info");
* 获取服务器指定目录下的子文件列表(包括子目录),以 FTP 登录用户的根目录为基准,与 FTPClient 当前连接目录无关
* 2)FTPFile[] ftpFiles = ftpClient.listFiles("/docs/info/springmvc.txt");
* 获取服务器指定文件,此时如果文件存在时,则 FTPFile[] 大小为 1,就是此文件
* */
FTPFile[] ftpFiles = ftpClient.listFiles();
if (ftpFiles != null && ftpFiles.length > 0) {
for (FTPFile ftpFile : ftpFiles) {
if (ftpFile.isFile()) {
String relativeRemotePath = remotePath + "\\" + ftpFile.getName();
relativePathList.add(relativeRemotePath);
} else {
loopServerPath(ftpClient, remotePath + "\\" + ftpFile.getName(), relativePathList);
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
return relativePathList;
}


/**
* 上传本地文件 或 目录 至 FTP 服务器----保持 FTP 服务器与本地 文件目录结构一致
*
* @param ftpClient 连接成功有效的 FTPClinet
* @param uploadFile 待上传的文件 或 文件夹(此时会遍历逐个上传)
* @throws Exception
*/
public static void uploadFile(FTPClient ftpClient, File uploadFile, String dstDirectory) {
/**如果 FTP 连接已经关闭,或者连接无效,则直接返回*/
if (!ftpClient.isConnected() || !ftpClient.isAvailable()) {
log.error(">>>>>FTP服务器连接已经关闭或者连接无效*****放弃文件上传****");
return;
}
if (uploadFile == null || !uploadFile.exists()) {
log.error(">>>>>待上传文件为空或者文件不存在*****放弃文件上传****");
return;
}
try {
/**如果被上传的是文件时*/
FileInputStream input = new FileInputStream(uploadFile);
/** storeFile:将本地文件上传到服务器
* 1)如果服务器已经存在此文件,则不会重新覆盖,即不会再重新上传
* 2)如果当前连接FTP服务器的用户没有写入的权限,则不会上传成功,但是也不会报错抛异常
* */
ftpClient.changeWorkingDirectory(dstDirectory);
ftpClient.storeFile(uploadFile.getName(), input);
input.close();
log.info(">>>>>文件上传成功****" + uploadFile.getPath());

} catch (IOException e) {
e.printStackTrace();
}
}

/**
* 上传本地文件 或 目录 至 FTP 服务器----保持 FTP 服务器与本地 文件目录结构一致
*
* @param ftpClient 连接成功有效的 FTPClinet
* @param uploadFile 待上传的文件 或 文件夹(此时会遍历逐个上传)
* @throws Exception
*/
public static void uploadFiles(FTPClient ftpClient, File uploadFile) {
/**如果 FTP 连接已经关闭,或者连接无效,则直接返回*/
if (!ftpClient.isConnected() || !ftpClient.isAvailable()) {
log.error(">>>>>FTP服务器连接已经关闭或者连接无效*****放弃文件上传****");
return;
}
if (uploadFile == null || !uploadFile.exists()) {
log.error(">>>>>待上传文件为空或者文件不存在*****放弃文件上传****");
return;
}
try {
if (uploadFile.isDirectory()) {
/**如果被上传的是目录时
* makeDirectory:在 FTP 上创建目录(方法执行完,服务器就会创建好目录,如果目录本身已经存在,则不会再创建)
* 1)可以是相对路径,即不以"/"开头,相对的是 FTPClient 当前的工作路径,如 "video"、"视频" 等,会在当前工作目录进行新建目录
* 2)可以是绝对路径,即以"/"开头,与 FTPCLient 当前工作目录无关,如 "/images"、"/images/2018"
* 3)注意多级目录时,必须确保父目录存在,否则创建失败,
* 如 "video/201808"、"/images/2018" ,如果 父目录 video与images不存在,则创建失败
* */
ftpClient.makeDirectory(uploadFile.getName());
/**变更 FTPClient 工作目录到新目录
* 1)不以"/"开头表示相对路径,新目录以当前工作目录为基准,即当前工作目录下不存在此新目录时,变更失败
* 2)参数必须是目录,当是文件时改变路径无效*/
ftpClient.changeWorkingDirectory(uploadFile.getName());

File[] listFiles = uploadFile.listFiles();
for (int i = 0; i < listFiles.length; i++) {
File loopFile = listFiles[i];
if (loopFile.isDirectory()) {
/**如果有子目录,则迭代调用方法进行上传*/
uploadFiles(ftpClient, loopFile);
/**changeToParentDirectory:将 FTPClient 工作目录移到上一层
* 这一步细节很关键,子目录上传完成后,必须将工作目录返回上一层,否则容易导致文件上传后,目录不一致
* */
ftpClient.changeToParentDirectory();
} else {
/**如果目录中全是文件,则直接上传*/
FileInputStream input = new FileInputStream(loopFile);
ftpClient.storeFile(loopFile.getName(), input);
input.close();
log.info(">>>>>文件上传成功****" + loopFile.getPath());
}
}
} else {
/**如果被上传的是文件时*/
FileInputStream input = new FileInputStream(uploadFile);
/** storeFile:将本地文件上传到服务器
* 1)如果服务器已经存在此文件,则不会重新覆盖,即不会再重新上传
* 2)如果当前连接FTP服务器的用户没有写入的权限,则不会上传成功,但是也不会报错抛异常
* */
ftpClient.storeFile(uploadFile.getName(), input);
input.close();
log.info(">>>>>文件上传成功****" + uploadFile.getPath());
}
} catch (IOException e) {
e.printStackTrace();
}
}

/**
* 同步本地目录与 FTP 服务器目录
* 1)约定:FTP 服务器有,而本地没有的,则下载下来;本地有,而ftp服务器没有的,则将本地多余的删除
* 2)始终确保本地与 ftp 服务器内容一致
* 2)让 FTP 服务器与 本地目录保持结构一致,如 服务器上是 /docs/overview-tree.html,则本地也是 localDir/docs/overview-tree.html
*
* @param ftpClient 连接成功有效的 FTPClinet
* @param localSyncFileDir :与 FTP 目录进行同步的本地目录
*/
public static void syncLocalDir(FTPClient ftpClient, String localSyncFileDir) throws IOException {
/**如果 FTP 连接已经关闭,或者连接无效,则直接返回*/
if (!ftpClient.isConnected() || !ftpClient.isAvailable() || StringUtils.isBlank(localSyncFileDir)) {
log.error(">>>>>FTP服务器连接已经关闭或者连接无效*********");
return;
}

/** 获取本地存储目录下的文件*/
Collection<File> fileCollection = FileWmxUtil.localLrunGetistFiles(new File(localSyncFileDir));
log.info(">>>>>本地存储目录共有文件数量*********" + fileCollection.size());

/**获取 FTP 服务器下的相对路径*/
List<String> relativePathList = new ArrayList<>();
relativePathList = loopServerPath(ftpClient, "", relativePathList);
log.info(">>>>>FTP 服务器端共有文件数量*********" + relativePathList.size());

/**
* 遍历 本地存储目录下的文件
* 1)如果本地文件在 FTP 服务器上不存在,则删除它
* 2)如果本地文件在 FTP 服务器上存在,则比较两种大小
* 如果大小不一致,则重新下载
*/
for (File localFile : fileCollection) {
String localFilePath = localFile.getPath();
String localFileSuffi = localFilePath.replace(localSyncFileDir, "");
if (relativePathList.contains(localFileSuffi)) {
/**本地此文件在 FTP 服务器存在
* 1)比较大小,如果本地文件与服务器文件大小一致,则跳过
* 2)如果大小不一致,则删除本地文件,重新下载
* 3)最后都要删除relativePathList中的此元素,减轻后一次循环的压力*/
FTPFile[] ftpFiles = ftpClient.listFiles(localFileSuffi);
log.error(">>>>>本地文件 在 FTP 服务器已存在*********" + localFile.getPath());
if (ftpFiles.length >= 1 && localFile.length() != ftpFiles[0].getSize()) {
downloadSingleFile(ftpClient, localSyncFileDir, localFileSuffi);
log.error(">>>>>本地文件与 FTP 服务器文件大小不一致,重新下载*********" + localFile.getPath());
}
relativePathList.remove(localFileSuffi);
} else {
log.error(">>>>>本地文件在 FTP 服务器不存在,删除本地文件*********" + localFile.getPath());
/**本地此文件在 FTP 服务器不存在
* 1)删除本地文件
* 2)如果当前文件所在目录下文件已经为空,则将此父目录也一并删除*/
localFile.delete();
File parentFile = localFile.getParentFile();
while (parentFile.list().length == 0) {
parentFile.delete();
parentFile = parentFile.getParentFile();
}
}
}
for (int i = 0; i < relativePathList.size(); i++) {
log.info(">>>>> FTP 服务器存在新文件,准备下载*********" + relativePathList.get(i));
downloadSingleFile(ftpClient, localSyncFileDir, relativePathList.get(i));
}
}

/**
* 删除服务器的文件
*
* @param ftpClient 连接成功且有效的 FTP客户端
* @param deleteFiles 待删除的文件或者目录,为目录时,会逐个删除,
* 路径必须是绝对路径,如 "/1.png"、"/video/3.mp4"、"/images/2018"
* "/" 表示用户根目录,则删除所有内容
*/
public static void deleteServerFiles(FTPClient ftpClient, String deleteFiles) {
/**如果 FTP 连接已经关闭,或者连接无效,则直接返回*/
if (!ftpClient.isConnected() || !ftpClient.isAvailable()) {
log.error(">>>>>FTP服务器连接已经关闭或者连接无效*****放弃文件上传****");
return;
}
try {
/** 尝试改变当前工作目录到 deleteFiles
* 1)changeWorkingDirectory:变更FTPClient当前工作目录,变更成功返回true,否则失败返回false
* 2)如果变更工作目录成功,则表示 deleteFiles 为服务器已经存在的目录
* 3)否则变更失败,则认为 deleteFiles 是文件,是文件时则直接删除
*/
boolean changeFlag = ftpClient.changeWorkingDirectory(deleteFiles);
if (changeFlag) {
/**当被删除的是目录时*/
FTPFile[] ftpFiles = ftpClient.listFiles();
for (FTPFile ftpFile : ftpFiles) {
log.info("----------------::::" + ftpClient.printWorkingDirectory());
if (ftpFile.isFile()) {
boolean deleteFlag = ftpClient.deleteFile(ftpFile.getName());
if (deleteFlag) {
log.info(">>>>>删除服务器文件成功****" + ftpFile.getName());
} else {
log.error(">>>>>删除服务器文件失败****" + ftpFile.getName());
}
} else {
/**printWorkingDirectory:获取 FTPClient 客户端当前工作目录
* 然后开始迭代删除子目录
*/
String workingDirectory = ftpClient.printWorkingDirectory();
deleteServerFiles(ftpClient, workingDirectory + "/" + ftpFile.getName());
}
}
/**printWorkingDirectory:获取 FTPClient 客户端当前工作目录
* removeDirectory:删除FTP服务端的空目录,注意如果目录下存在子文件或者子目录,则删除失败
* 运行到这里表示目录下的内容已经删除完毕,此时再删除当前的为空的目录,同时将工作目录移动到上移层级
* */
String workingDirectory = ftpClient.printWorkingDirectory();
ftpClient.removeDirectory(workingDirectory);
ftpClient.changeToParentDirectory();
} else {
/**deleteFile:删除FTP服务器上的文件
* 1)只用于删除文件而不是目录,删除成功时,返回 true
* 2)删除目录时无效,方法返回 false
* 3)待删除文件不存在时,删除失败,返回 false
* */
boolean deleteFlag = ftpClient.deleteFile(deleteFiles);
if (deleteFlag) {
log.info(">>>>>删除服务器文件成功****" + deleteFiles);
} else {
log.error(">>>>>删除服务器文件失败****" + deleteFiles);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}

}

六、sftp工具类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
@Slf4j
public class SFtpUtil {

private ChannelSftp sftp;

private Session session;
/**
* SFTP 登录用户名
*/
private String username;
/**
* SFTP 登录密码
*/
private String password;
/**
* 私钥
*/
private String privateKey;
/**
* SFTP 服务器地址IP地址
*/
private String host;
/**
* SFTP 端口
*/
private int port;


/**
* 构造基于密码认证的sftp对象
*/
public SFtpUtil(String username, String password, String host, int port) {
this.username = username;
this.password = password;
this.host = host;
this.port = port;
}

/**
* 构造基于秘钥认证的sftp对象
*/
public SFtpUtil(String username, String host, int port, String privateKey) {
this.username = username;
this.host = host;
this.port = port;
this.privateKey = privateKey;
}

public SFtpUtil() {
}


/**
* 连接sftp服务器
*/
public void login() {
try {
JSch jsch = new JSch();
if (privateKey != null) {
jsch.addIdentity(privateKey);// 设置私钥
}

session = jsch.getSession(username, host, port);

if (password != null) {
session.setPassword(password);
}
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");

session.setConfig(config);
session.connect();

Channel channel = session.openChannel("sftp");
channel.connect();

sftp = (ChannelSftp) channel;
} catch (JSchException e) {
e.printStackTrace();
}
}

/**
* 关闭连接 server
*/
public void logout() {
if (sftp != null) {
if (sftp.isConnected()) {
sftp.disconnect();
}
}
if (session != null) {
if (session.isConnected()) {
session.disconnect();
}
}
}


/**
* 将输入流的数据上传到sftp作为文件。文件完整路径=basePath+directory
*
* @param directory 上传到该目录
* @param sftpFileName sftp端文件名
*/
public boolean upload(String directory, String sftpFileName, InputStream input) throws SftpException {
try {
//sftp.mkdir(directory);
if (directory != null && !"".equals(directory)) {
sftp.cd(directory);
}
sftp.put(input, sftpFileName); //上传文件
return true;
} catch (SftpException e) {
return false;
}
}

public void mkdir(String directory) throws SftpException {
sftp.mkdir(directory);
}

public void cd(String directory) throws SftpException {
if (directory != null && !"".equals(directory) && !"/".equals(directory)) {
sftp.cd(directory);
}

}

/**
* 下载文件。
*
* @param directory 下载目录
* @param downloadFile 下载的文件
* @param saveFile 存在本地的路径
*/
public void download(String directory, String downloadFile, String saveFile) {
System.out.println("download:" + directory + " downloadFile:" + downloadFile + " saveFile:" + saveFile);

File file = null;
try {
if (directory != null && !"".equals(directory)) {
sftp.cd(directory);
}
file = new File(saveFile);
sftp.get(downloadFile, new FileOutputStream(file));
} catch (SftpException e) {
e.printStackTrace();
if (file != null) {
file.delete();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
if (file != null) {
file.delete();
}
}

}

/**
* 下载文件
*
* @param directory 下载目录
* @param downloadFile 下载的文件名
* @return 字节数组
*/
public byte[] download(String directory, String downloadFile) throws SftpException, IOException {
if (directory != null && !"".equals(directory)) {
sftp.cd(directory);
}
InputStream is = sftp.get(downloadFile);

byte[] fileData = IOUtils.toByteArray(is);

return fileData;
}


/**
* 删除文件
*
* @param directory 要删除文件所在目录
* @param deleteFile 要删除的文件
*/
public void delete(String directory, String deleteFile) throws SftpException {
if (directory != null && !"".equals(directory)) {
sftp.cd(directory);
}
sftp.rm(deleteFile);
}


/**
* 列出目录下的文件
*
* @param directory 要列出的目录
*/
public Vector<?> listFiles(String directory) throws SftpException {
return sftp.ls(directory);
}

public boolean isExistsFile(String directory, String fileName) {

List<String> findFilelist = new ArrayList();
ChannelSftp.LsEntrySelector selector = new ChannelSftp.LsEntrySelector() {
@Override
public int select(ChannelSftp.LsEntry lsEntry) {
if (lsEntry.getFilename().equals(fileName)) {
findFilelist.add(fileName);
}
return 0;
}
};

try {
sftp.ls(directory, selector);
} catch (SftpException e) {
e.printStackTrace();
}

if (findFilelist.size() > 0) {
return true;
} else {
return false;
}
}

//上传文件测试
/* public static void main(String[] args) throws SftpException, IOException {
SFtpUtil sftp = new SFtpUtil("user", "passwd", "ip", port);
sftp.login();
File file = new File("D:\\Program Files\\sts-bundle\\sts-3.9.4.RELEASE\\lombok.jar");
InputStream is = new FileInputStream(file);
boolean b = sftp.upload("/home/sftp_user/", "lombok.jar", is);
log.info("{}",b);
sftp.logout();
String s = "D:\\Program Files\\sts-bundle\\sts-3.9.4.RELEASE\\lombok.jar";
s = "/Program Files/sts-bundle/sts-3.9.4.RELEASE/lombok.jar";
String name = s.substring((s.lastIndexOf("\\")==-1?s.lastIndexOf("/"):s.lastIndexOf("\\"))+1);
log.info("{}",name);

}*/
}

七、shell工具

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
public class ShellUtil {

/* public static void main(String[] args) throws Exception {
JSch jsch = new JSch(); // 创建JSch对象
String userName = "";// 用户名
String password = "";// 密码
String host = "";// 服务器地址
int port = 22;// 端口号
//String cmd = "cat /data/hello.txt";// 要运行的命令
String cmd = "netstat -nltp";// 要运行的命令
System.out.println(execCommod(host,port, userName,password,cmd));
}*/

public static String execCommod(String host, int port, String userName, String password, String cmd) throws Exception {
JSch jsch = new JSch(); // 创建JSch对象
Session session = jsch.getSession(userName, host, port); // 根据用户名,主机ip,端口获取一个Session对象
session.setPassword(password); // 设置密码
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config); // 为Session对象设置properties
int timeout = 60000000;
session.setTimeout(timeout); // 设置timeout时间
session.connect(); // 通过Session建立链接
ChannelExec channelExec = (ChannelExec) session.openChannel("exec");
channelExec.setCommand(cmd);
channelExec.setInputStream(null);
channelExec.setErrStream(System.err);
channelExec.connect();
InputStream in = channelExec.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in, Charset.forName("UTF-8")));
String buf = null;
StringBuffer sb = new StringBuffer();
while ((buf = reader.readLine()) != null) {
sb.append(buf+"\r\n");
}
reader.close();
channelExec.disconnect();
if (null != session) {
session.disconnect();
}

return sb.toString();
}

}

八、名字生成工具

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
    public static String getName() {
Random random = new Random();
String[] Surname = {"赵", "钱", "孙", "李", "周", "吴", "郑", "王", "冯", "陈", "褚", "卫", "蒋", "沈", "韩", "杨", "朱", "秦", "尤", "许", "何", "吕", "施", "张", "孔", "曹", "严", "华", "金", "魏", "陶", "姜", "戚", "谢", "邹", "喻", "柏", "水", "窦", "章", "云", "苏", "潘", "葛", "奚", "范", "彭", "郎", "鲁", "韦", "昌", "马", "苗", "凤", "花", "方", "俞", "任", "袁", "柳", "酆", "鲍", "史", "唐", "费", "廉", "岑", "薛", "雷", "贺", "倪", "汤", "滕", "殷", "罗", "毕", "郝", "邬", "安", "常", "乐", "于", "时", "傅", "皮", "卞", "齐", "康", "伍", "余", "元", "卜", "顾", "孟", "平", "黄", "和", "穆", "萧", "尹", "姚", "邵", "湛", "汪", "祁", "毛", "禹", "狄", "米", "贝", "明", "臧", "计", "伏", "成", "戴", "谈", "宋", "茅", "庞", "熊", "纪", "舒", "屈", "项", "祝", "董", "梁", "杜", "阮", "蓝", "闵", "席", "季"};
String girl = "秀娟英华慧巧美娜静淑惠珠翠雅芝玉萍红娥玲芬芳燕彩春菊兰凤洁梅琳素云莲真环雪荣爱妹霞香月莺媛艳瑞凡佳嘉琼勤珍贞莉桂娣叶璧璐娅琦晶妍茜秋珊莎锦黛青倩婷姣婉娴瑾颖露瑶怡婵雁蓓纨仪荷丹蓉眉君琴蕊薇菁梦岚苑婕馨瑗琰韵融园艺咏卿聪澜纯毓悦昭冰爽琬茗羽希宁欣飘育滢馥筠柔竹霭凝晓欢霄枫芸菲寒伊亚宜可姬舒影荔枝思丽 ";
String boy = "伟刚勇毅俊峰强军平保东文辉力明永健世广志义兴良海山仁波宁贵福生龙元全国胜学祥才发武新利清飞彬富顺信子杰涛昌成康星光天达安岩中茂进林有坚和彪博诚先敬震振壮会思群豪心邦承乐绍功松善厚庆磊民友裕河哲江超浩亮政谦亨奇固之轮翰朗伯宏言若鸣朋斌梁栋维启克伦翔旭鹏泽晨辰士以建家致树炎德行时泰盛雄琛钧冠策腾楠榕风航弘";
int index = random.nextInt(Surname.length - 1);
String name = Surname[index]; //获得一个随机的姓氏
int i = random.nextInt(3);//可以根据这个数设置产生的男女比例
if (i == 2) {
int j = random.nextInt(girl.length() - 2);
if (j % 2 == 0) {
//name = "女-" + name + girl.substring(j, j + 2);
name = name + girl.substring(j, j + 2);
} else {
name = name + girl.substring(j, j + 1);
}
} else {
int j = random.nextInt(girl.length() - 2);
if (j % 2 == 0) {
name = name + boy.substring(j, j + 2);
} else {
name = name + boy.substring(j, j + 1);
}
}
return name;
}

持续更新中~~~

更多工具点击这里: https://www.hutool.cn/docs/