作為一個Java程式設計師,這 8 個開源類庫你必須知道!
昨天在青銅時代群裡看到讀者朋友們在討論 Java 最常用的工具類,我覺得大家推薦的確實都挺常見的,我自己用的頻率也蠻高的。恰好我在 programcreek 上看到過一篇類似的文章,就想著梳理一下分享給大家。
在 Java 中,工具類通常用來定義一組執行通用操作的方法。本篇文章將會向大家展示 8 個工具類以及它們最常用的方法,類的排名和方法的排名均來自可靠的資料,從 GitHub 上最受歡迎的 50000 個開源 Java 專案中精心挑選。
為了方便大家的理解,我會在介紹每個類的方法時寫一段小 Demo,這樣大家就能知道每個方法該怎麼用。放心吧,方法是幹嘛的我也不會保密的。?
1)IOUtils
org.apache.commons.io.IOUtils
,操作 IO 流的工具類,下面是其常用的方法。
closeQuietly()
,關閉 IO 流,並且忽略 null 值和異常。
IOUtils.closeQuietly(output);
copy()
,將位元組從輸入流複製到輸出流。
IOUtils.copy(inputStream, new FileOutputStream(File));
toByteArray()
,以byte[]
的形式獲取輸入流中的內容。
URLConnection conn = new URL(url).openConnection();
InputStream is = conn.getInputStream();
byte[] result = IOUtils.toByteArray(is);
write()
,將字元或者位元組寫入輸出流中。
IOUtils.write("沉默王二", response.getOutputStream(), "UTF-8");
toInputStream()
,將指定的字元轉成輸入流。
String content=req.getParameter("content");
InputStream inputStream=IOUtils.toInputStream(content,"utf-8");
readLines()
,從輸入流中一行一行地讀取,並按照指定的字元編碼返回字串列表。
List<String> lines = IOUtils.readLines(new InputStreamReader(new FileInputStream(file), "utf-8"));
copyLarge()
,從輸入流中複製內容到輸出流,超過 2GB。
private File downloadFile(HttpResponse response) {
File dir = new File("downloadedFiles");
if (!dir.exists()) {
dir.mkdir();
}
File outputFile = new File("downloadedFiles/temp" + RandomStringUtils.randomAlphanumeric(3));
try {
IOUtils.copyLarge(response.getEntity().getContent(), new FileOutputStream(outputFile));
return outputFile;
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
request.releaseConnection();
}
}
readFully()
,把輸入流中的內容讀入到位元組陣列中。
byte[] intArray = new byte[Bytes.SIZEOF_INT];
IOUtils.readFully(in, intArray);
2)FileUtils
org.apache.commons.io.FileUtils
,操作檔案或者目錄的工具類,下面是其常用的方法。
deleteDirectory()
,刪除目錄。
FileUtils.deleteDirectory(file);
readFileToString()
,把檔案的內容讀入到字串中。
String fileAsString = FileUtils.readFileToString(reportFile);
deleteQuietly()
,刪除檔案,但不丟擲異常。
FileUtils.deleteQuietly(outputFile);
copyFile()
,把檔案複製到一個新的位置。
FileUtils.copyFile(source, dest);
writeStringToFile()
,把字串寫入到檔案。
FileUtils.writeStringToFile(templateFile, generatedText, Charset.forName("UTF-8"));
forceMkdir()
,強制建立目錄,包括任何必需但不存在的父目錄。
File uploadDirectory = new File(this.uploadPath);
if (!uploadDirectory.exists()) {
FileUtils.forceMkdir(uploadDirectory);
}
write()
,把字元或者位元組寫入到檔案。
FileUtils.write(new File("C:\\Users\\cmower\\test.txt"), "沉默王二", "utf-8");
listFiles()
,列出指定目錄下的所有檔案。
public void processResultsDirectory(String dirName) {
File root = new File(dirName);
try {
Collection<File> files = FileUtils.listFiles(root,
new RegexFileFilter(jmeterJTLFileName),
DirectoryFileFilter.DIRECTORY);
for (Iterator<File> iterator = files.iterator(); iterator.hasNext();) {
File file = (File) iterator.next();
parse(file);
}
} catch (Exception e) {
e.printStackTrace();
}
}
copyDirectory()
,將目錄下的所有子目錄及檔案複製到新的目錄。
FileUtils.copyDirectory(source, dest);
forceDelete()
,強制刪除檔案或者目錄及其所有子目錄和檔案。
FileUtils.forceDelete(tmpFile);
3)StringUtils
org.apache.commons.lang3.StringUtils
,操作字串的工具類,並且是 null 安全的,下面是其常用的方法。
isBlank()
,檢查字元是否為空字串"",或者 null,或者空格。
if (StringUtils.isBlank(name))
{
throw new IllegalArgumentException("姓名不能為空");
}
檢查結果如下所示。
StringUtils.isBlank(null) = true
StringUtils.isBlank("") = true
StringUtils.isBlank(" ") = true
StringUtils.isBlank("沉默王二") = false
StringUtils.isBlank(" 沉默王二 ") = false
-
isNotBlank()
,與isBlank()
檢查的結果相反。 -
isEmpty()
,檢查字元是否為空字串"",或者 null;和isBlank()
不同,不包括空格的檢查。
if (StringUtils.isEmpty(name)) {
throw new IllegalArgumentException("姓名不能為 null 或者空字串");
}
檢查結果如下所示。
StringUtils.isEmpty(null) = true
StringUtils.isEmpty("") = true
StringUtils.isEmpty(" ") = false
StringUtils.isEmpty("沉默王二") = false
StringUtils.isEmpty(" 沉默王二 ") = false
-
isNotEmpty()
,與isEmpty()
檢查的結果相反。 -
join()
,將多個元素連線成一個字串。
StringUtils.join(null) = null
StringUtils.join([]) = ""
StringUtils.join([null]) = ""
StringUtils.join(["沉默", "王二"]) = "沉默王二"
StringUtils.join([null, "", "一枚有趣的程式設計師"]) = "一枚有趣的程式設計師"
equals()
,比較兩個字元序列是否相等。
StringUtils.equals(null, null) = true
StringUtils.equals(null, "沉默王二") = false
StringUtils.equals("沉默王二", null) = false
StringUtils.equals("沉默王二", "沉默王二") = true
StringUtils.equals("cmower", "CMOWER") = false
split()
,把字串拆分為陣列,拆分符為空白字元。
StringUtils.split(null) = null
StringUtils.split("") = []
StringUtils.split("沉默王二 沉默王三") = ["沉默王二", "沉默王三"]
StringUtils.split("沉默王二 沉默王三") = ["沉默王二", "沉默王三"]
StringUtils.split(" 沉默王二 ") = ["沉默王二"]
replace()
,替換另一個字串中所有出現的字串。
StringUtils.replace(null, *, *) = null
StringUtils.replace("", *, *) = ""
StringUtils.replace("any", null, *) = "any"
StringUtils.replace("any", *, null) = "any"
StringUtils.replace("any", "", *) = "any"
StringUtils.replace("沉默王二", "二", null) = "沉默王二"
StringUtils.replace("沉默王二", "二", "") = "沉默王"
StringUtils.replace("沉默王二", "二", "三") = "沉默王三"
4)FilenameUtils
org.apache.commons.io.FilenameUtils
,操作檔名或者路徑的工具類,下面是其常用的方法。
getExtension()
,獲取檔案的副檔名。
FilenameUtils.getExtension("牛逼.txt"); --> "txt"
FilenameUtils.getExtension("a/b/牛逼.jpg"); --> "jpg"
FilenameUtils.getExtension("a/牛逼.txt/c"); --> ""
FilenameUtils.getExtension("a/b/c"); --> ""
getBaseName()
,獲取單純的檔名或者路徑名,檔案時去掉路徑和副檔名;路徑時去掉父級路徑。
FilenameUtils.getBaseName("a/b/牛逼.txt"); --> "牛逼"
FilenameUtils.getBaseName("牛逼.txt"); --> "牛逼"
FilenameUtils.getBaseName("a/b/c"); --> c
FilenameUtils.getBaseName("a/b/c/"); --> ""
getName()
,如果是檔案時,獲取檔名和字尾,去掉路徑;如果是路徑時,去掉父級路徑。
FilenameUtils.getName("a/b/牛逼.txt"); --> "牛逼.txt"
FilenameUtils.getName("牛逼.txt"); --> "牛逼.txt"
FilenameUtils.getName("a/b/c"); --> c
FilenameUtils.getName("a/b/c/"); --> ""
concat()
,將路徑和檔名連線在一起。
FilenameUtils.concat("/foo/", "bar"); --> /foo/bar
FilenameUtils.concat("/foo", "bar"); --> /foo/bar
FilenameUtils.concat("/foo", "/bar"); --> /bar
FilenameUtils.concat("/foo", "C:/bar"); --> C:/bar
FilenameUtils.concat("/foo", "C:bar"); --> C:bar (*)
FilenameUtils.concat("/foo/a/", "../bar"); --> foo/bar
FilenameUtils.concat("/foo/", " ../../bar"); --> null
FilenameUtils.concat("/foo/", "/bar"); --> /bar
FilenameUtils.concat("/foo/.. ", "/bar"); --> /bar
FilenameUtils.concat("/foo", " bar/c.txt"); --> /foo/bar/c.txt
FilenameUtils.concat("/foo/c.txt", "bar"); --> /foo/c.txt/bar (!)
wildcardMatch()
,檢查檔名是否匹配指定的格式。
wildcardMatch("c.txt", "*.txt") --> true
wildcardMatch("c.txt", "*.jpg") --> false
wildcardMatch("a/b/c.txt", "a/b/*") --> true
wildcardMatch("c.txt", "*.???") --> true
wildcardMatch("c.txt", "*.????") --> false
separatorsToUnix()
,將所有分隔符轉換為正斜槓的 Unix 分隔符。
FilenameUtils.separatorsToUnix("my/unix/filename");
getFullPath()
,獲取檔案的完整路徑。
getFullPath("C:\a\b\c.txt" --> C:\a\b\
getFullPath("~/a/b/c.txt" --> ~/a/b/
getFullPath("a.txt" --> ""
5)ArrayUtils
org.apache.commons.lang3.ArrayUtils
,運算元組的工具類,下面是其常用的方法。
contains()
,檢查陣列中是否包含某個值
public static boolean containsAll(Object[] one, Object[] two) {
for (Object b : two) {
if (!ArrayUtils.contains(one, b)) {
return false;
}
}
return true;
}
addAll()
,將所有元素新增到一個陣列中。
ArrayUtils.addAll(null, null) = null
ArrayUtils.addAll(array1, null) = cloned copy of array1
ArrayUtils.addAll(null, array2) = cloned copy of array2
ArrayUtils.addAll([], []) = []
ArrayUtils.addAll([null], [null]) = [null, null]
ArrayUtils.addAll(["a", "b", "c"], ["1", "2", "3"]) = ["a", "b", "c", "1", "2", "3"]
clone()
,淺拷貝一個陣列。
public QualityGateTask[] getQueue() {
return (QualityGateTask[]) ArrayUtils.clone(queue);
}
isEmpty()
,檢查陣列是否為 null 或者沒有元素。
if (ArrayUtils.isEmpty(objectIds)) {
throw new IllegalArgumentException("物件的ID不能為空");
}
add()
,在陣列中新增一個新的元素,原陣列不變。
ArrayUtils.add(null, true) = [true]
ArrayUtils.add([true], false) = [true, false]
ArrayUtils.add([true, false], true) = [true, false, true]
subarray()
,根據起始下標和結束下標擷取一個子陣列。
public byte[] fetchData(String blobKey, long startIndex, long l) {
CountingInputStream inputStream = new CountingInputStream(getInputStream(blobKey));
byte[] bytes = new byte[(int) l];
try {
int readSize = inputStream.read(bytes, (int) startIndex, (int) l);
if (readSize < l) {
bytes = ArrayUtils.subarray(bytes, 0, readSize - 1);
}
} catch (IOException e) {
LOGGER.warn("Failed to read bytes", e);
} finally {
try {
inputStream.close();
} catch (IOException ignored) {
LOGGER.warn("Exception while closing inputStream", ignored);
}
}
return bytes;
}
indexOf()
,找出指定陣列的下標。
ArrayUtils.indexOf(idxVal, i);
6)DigestUtils
org.apache.commons.codec.digest.DigestUtils
,加密的工具類,下面是其常用的方法。
md5Hex()
,計算字串的 MD5 摘要,並返回 32 位的十六進位制字元。
DigestUtils.md5Hex("沉默王二");
md5()
,計算字串的 MD5 摘要,並返回 16 個元素的位元組陣列。
DigestUtils.md5("沉默王二");
7)StringEscapeUtils
org.apache.commons.text.StringEscapeUtils
,字串的轉義和反轉義工具類,下面是其常用的方法。
unescapeHtml4()
,反轉義 HTML。
StringEscapeUtils.unescapeHtml4("<div></div>");--> <div></div>
escapeHtml4()
,轉義 HTML。
StringEscapeUtils.escapeHtml4("<div></div>");--> <div></div>
escapeJava()
,轉義 Java。
StringEscapeUtils.escapeJava("沉默王二");--> \u6C89\u9ED8\u738B\u4E8C
unescapeJava()
StringEscapeUtils.escapeJava("\u6C89\u9ED8\u738B\u4E8C");--> 沉默王二
8)BeanUtils
大多數 Java 開發人員習慣於建立 getter/setter
的JavaBean,然後通過呼叫相應的 getXxx
和 setXxx
方法訪問對應欄位。但在某些情況下,需要動態訪問 Java 物件的屬性,org.apache.commons.beanutils.BeanUtils
就派上用場了。
copyProperties()
,拷貝所有屬性。
private static void dto2Entity() {
UserDTO user = new UserDTO();
user.setId(1l);
user.setUsername("joking");
user.setCreationDate("2016-04-20");
EUser u = new EUser();
ConvertUtils.register(new DateStringConverter(), Date.class);
try {
BeanUtils.copyProperties(u, user);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
其中 UserDTO 類的原始碼如下所示。
public class UserDTO implements Serializable {
private static final long serialVersionUID = 2963408818099106614L;
private long id;
private String username;
private String creationDate;
// getter/setter
@Override
public String toString() {
return "UserDTO [id=" + id + ", username=" + username + ", creationDate=" + creationDate + "]";
}
}
其中 EUser 類的原始碼如下所示。
public class EUser implements Serializable {
private static final long serialVersionUID = -692192937932555368L;
private long id;
private String username;
private Date creationDate;
//getter/setter
@Override
public String toString() {
return "EUser [id=" + id + ", username=" + username + ", creationDate=" + creationDate + "]";
}
}
其中 DateStringConverter 類的原始碼如下所示。
public class DateStringConverter implements Converter {
@SuppressWarnings("unchecked")
@Override
public <T> T convert(Class<T> type, Object value) {
if(type.equals(Date.class) && String.class.isInstance(value)) {
return (T)DateUtils.convert((String)value);
} else if(type.equals(String.class) && Date.class.isInstance(value)){
return (T)DateUtils.format((Date)value);
} else {
return (T)value;
}
}
}
getProperty()
,返回 bean 指定的屬性值。
String fieldValue = BeanUtils.getProperty(value, fieldName);
setProperty()
,設定 bean 指定的屬性值。
BeanUtils.setProperty(object, propertyName, value);
說實在的,沒想到整理起來這麼費事,不知不覺 5 個小時過去了。每個類都有很多方法,還要為每個方法敲一個 Demo,真的是很辛苦。但為了你們,再苦再累二哥也心甘情願啊。
雖然是技術文,但我想大家應該仍然能感受到我的文風比較幽默風趣。上次和純潔的微笑、江南一點雨他們在南京小聚的時候,他們也感慨說:“之前一直未曾謀面,這次一見,二哥真心文如其人啊,騷氣。”這話真不是貶義詞,這年頭,生活壓力這麼大,像我這樣能夠對生活保持樂觀的人不多了,希望你們在閱讀我的文章時也能夠感受到快樂,我是認真的!
原創不易,如果覺得有點用的話,請不要吝嗇你手中點讚的權力;如果想要第一時間看到二哥更新的文章,請掃描下方的二維碼,關注沉默王三公眾號。我們下篇文章見!
相關文章
- 作為程式設計師,這些實用工具你必須要知道!程式設計師
- 作為一個程式設計師,CPU的這些硬核知識你必須會!程式設計師
- 想要成為一個合格的Java程式設計師, 你必須要做到這些!Java程式設計師
- Python常用的開源框架,這三個你必須知道!Python框架
- 作為軟體工程師,你必須知道的20個常識軟體工程工程師
- Java程式設計師必須瞭解的7個效能指標,你都知道嗎?Java程式設計師指標
- 每個Java程式設計師必須知道的5個JVM命令列標誌Java程式設計師JVM命令列
- 這幾個python常用的庫你必須知道!Python
- 作為程式設計師必須知道的程式語言編年史程式設計師
- 程式設計師必須知道的幾個國外IT網站程式設計師網站
- 每個Java程式設計師必備的8個開發工具Java程式設計師
- 作為一個Java 程式設計師 你應該會什麼Java程式設計師
- 優秀程式設計師必須知道的32個演算法,提高你的開發效率程式設計師演算法
- Python你必須知道的十個庫Python
- Java程式設計師必須掌握的5個註解!Java程式設計師
- Python 這10個字典操作你必須知道Python
- 作為Android開發你必須知道的Java反射機制AndroidJava反射
- Web開發者和設計師必須要知道的 iOS 8 十個變化WebiOS
- 網頁設計師必須知道的6個小技巧網頁
- Java程式設計師必須掌握的7個Java效能指標!Java程式設計師指標
- 程式設計師必須知道的幾個Git程式碼託管平臺程式設計師Git
- 作為程式設計師必須掌握的Java虛擬機器中的22個重難點程式設計師Java虛擬機
- 設計師升職加薪必須知道的10個設計網站網站
- 每個Java程式設計師都必須知道的四種負載均衡演算法Java程式設計師負載演算法
- 身為Java程式設計師,這些開源工具你一定要學會!Java程式設計師開源工具
- 前端設計師必須知道的10個重要的CSS技巧前端CSS
- Java程式設計師微服務架構你必須要掌握的十個要點Java程式設計師微服務架構
- 職場科普,Python這6個字典操作你必須知道!Python
- 作為一個程式設計師,記憶體和磁碟的這些事情,你不得不知道啊!!!程式設計師記憶體
- 15個IT程式設計師必須思考的問題程式設計師
- 每個程式設計師都必須遵守的程式設計原則程式設計師
- 你必須知道的幾種java容器(集合類)Java
- 列舉幾個Java程式設計師通用的、必須掌握的框架Java程式設計師框架
- Java程式設計師必須要掌握這10種工具,缺一不可!Java程式設計師
- 作為ui設計師,你必須要熟練的幾款設計軟體UI
- 程式設計師必須掌握的五個seo知識程式設計師
- 作為一個程式設計師,你的進步完全取決於你自己程式設計師
- 作為一個程式設計師 你的進步完全取決於你自己程式設計師