kotlin 字符串_10个有用的Kotlin字符串扩展

kotlin 字符串

Kotlin is a relatively new programming language. It’s based on Java, and Kotlin code works in JVM. It can also be compiled to native apps (Kotlin Native) and JavaScript apps (Kotlin JS).

Kotlin是一种相对较新的编程语言。 它基于Java,并且Kotlin代码可在JVM中工作。 也可以将其编译为本机应用程序(Kotlin本机)和JavaScript应用程序(Kotlin JS)。

As an Android developer, I was happy to get more modern language than Java. In 2017 Google declared Kotlin as the official language for Android development; in 2019 they announced that Android will be “Kotlin-first.” Why Kotlin is better than Java?

作为一名Android开发人员,我很高兴获得比Java更现代的语言。 2017年,Google宣布Kotlin为Android开发的官方语言; 在2019年,他们宣布Android将成为“Kotlin第一”。 为什么Kotlin比Java更好?

  1. Kotlin supports optionals. Optionals help to avoid many crashes.

    Kotlin支持可选。 可选选项有助于避免多次崩溃。
  2. Kotlin is more concise. Less core, easier to read, easier to maintain.

    Kotlin更简洁。 更少的核心,更易于阅读,更易于维护。
  3. Kotlin supports extensions.

    Kotlin支持扩展。

Today we’ll talk about string extensions, which will make your code shorter, safer and generally better.

今天,我们将讨论string扩展,它将使您的代码更短,更安全且总体上更好。

These extensions work in Kotlin 1.3.70, but they must be compatible with other versions too. I work in Java environment, so I can’t guarantee they’ll work in Kotlin/Native and Kotlin/JS.

这些扩展可以在Kotlin 1.3.70中使用,但是它们也必须与其他版本兼容。 我在Java环境中工作,所以不能保证它们将在Kotlin / Native和Kotlin / JS中工作。

If you are also an iOS or Mac developer, you’ll probably be interested in my article 10 Useful Swift String Extensions.

如果您还是iOS或Mac开发人员,那么您可能会对我的文章 10有用的Swift字符串扩展 感兴趣

Image for post
Photo by Jonathan Chng on Unsplash
Jonathan ChngUnsplash上的 照片

1. MD5 / SHA哈希计算器 (1. MD5/SHA Hash Calculator)

Why would we calculate MD5 of a string? There can be many reasons. Save password in database, make some verification through insecure channel, check if file was calculated correctly. Same with SHA hashes.

为什么我们要计算string MD5? 可能有很多原因。 将密码保存在数据库中,通过不安全的通道进行一些验证,检查文件是否正确计算。 与SHA哈希相同。

Let’s start with MD5:

让我们从MD5开始:

md5 here is a calculated property (can be done as a function too). First, we use java.security.MessageDigest to calculate MD5 hash as byte array. Then we convert byte array to hex string.

md5这里是一个计算的属性(也可以作为函数来完成)。 首先,我们使用java.security.MessageDigest将MD5哈希计算为字节数组。 然后我们将字节数组转换为十六进制字符串。

SHA-1 is “Secure Hash Algorithm — 1”. Generally, SHA is a group of algorithms. There’s no big difference between from a programming point of view; we just need to change algorithm name in the MessageDigest.getInstance() call.

SHA-1是“安全哈希算法-1”。 通常,SHA是一组算法。 从编程的角度看,两者之间没有太大的区别。 我们只需要在MessageDigest.getInstance()调用中更改算法名称即可。

如何使用它 (How to use it)

val md5Hash = "test".md5 // 098f6bcd4621d373cade4e832627b4f6val sha1Hash = "test".sha1 // a94a8fe5ccb19ba61c4c0873d391e987982fbbd3
Image for post
Photo by Davide Baraldi on Unsplash
Davide BaraldiUnsplash上的 照片

2.检查字符串是否是有效的电子邮件地址 (2. Checking If a String Is a Valid Email Address)

Checking validity of an email address is a very common feature. From my personal experience, nine out of 10 Android apps allow or require user authentication. And nine out of 10 apps with authentication allow email/password as one of the methods. It’s a good practice to check the entered email address before sending it to server instead of wasting internet traffic and making unsuccessful registration/login call. If you develop backend, it’s critical to validate an email address before saving it to database.

检查电子邮件地址的有效性是非常常见的功能。 根据我的个人经验,十分之九的Android应用程序允许或要求用户身份验证。 每10个具有身份验证功能的应用程序中就有9个允许使用电子邮件/密码作为方法之一。 在将输入的电子邮件地址发送到服务器之前,最好先检查一下输入的电子邮件地址,而不是浪费互联网流量并进行不成功的注册/登录呼叫。 如果您开发后端,那么在将电子邮件地址保存到数据库之前,必须先对其进行验证。

The simplest way to validate an email address is by using regular expressions. You can adjust expression for your needs. I’ll show what I chose for myself:

验证电子邮件地址的最简单方法是使用正则表达式。 您可以根据需要调整表情。 我将展示我为自己选择的内容:

This extensions offers a function, but calculated property is also an option.

该扩展提供了功能,但是计算属性也是一个选项。

如何使用它 (How to use it)

val email = "test@email.com"
if (email.isEmailValid()) {print("Email is valid. Continue registration")
} else {print("Email is not validate. Show error")
}
Image for post
Photo by Quino Al on Unsplash
图片由 Quino AlUnsplash拍摄

3.验证和格式化电话号码 (3. Validating and Formatting Phone Number)

Similarly to email, a phone number may require validation, and even more importantly, formatting. Phone number is unique only with country code, but users don’t usually enter it (they usually change country name of flag). This is a significant difference from email.

与电子邮件类似,电话号码可能需要验证,更重要的是,需要格式化。 电话号码仅在国家/地区代码中是唯一的,但用户通常不会输入(他们通常会更改标志的国家/地区名称)。 这与电子邮件有很大的不同。

Also, phone numbers for different countries have different formats. That’s why it can be done only with an external library.

另外,不同国家/地区的电话号码格式也不同。 这就是为什么只能使用外部库才能完成的原因。

For JVM code there’s Google library libphonenumber. There’s a special adaptation for libphonenumber-android. They’re almost identical.

对于JVM代码,有Google库libphonenumberlibphonenumber-android有一个特殊的改编。 它们几乎是相同的。

JVM版本 (JVM version)

This function returns a formatted phone number (starting with “+” and country code) if it’s valid, or null if not. Region is a country selected from a list. If the app is targeted to one country, it can be hardcoded value.

此函数返回有效的格式化电话号码(以“ +”和国家/地区代码开头),否则返回null 。 地区是从列表中选择的国家。 如果该应用定位到一个国家/地区,则可以采用硬编码形式。

如何使用它 (How to use it)

val phone = "(202)555-0156" // Phone number is fake, but has valid formatval formattedPhone = phone.formatPhoneNumber("US")
if (formattedPhone == null) {println("Phone number is not valid")
} else {println("Sending $formattedPhone to API")
}

Android版 (Android version)

This function returns formatted phone number (starting with “+” and country code) if it’s valid, or null if not. First argument is Android Context, for example, Activity.

此函数返回有效的格式化电话号码(以“ +”和国家(地区)代码开头),否则返回null 。 第一个参数是Android Context ,例如Activity

如何使用它 (How to use it)

val phone = "(202)555-0156" // Phone number is fake, but has valid formatval formattedPhone = phone.formatPhoneNumber(this, "US")
if (formattedPhone == null) {println("Phone number is not valid")
} else {println("Sending $formattedPhone to API")
}
Image for post
Photo by Owen Beard on Unsplash
Owen BeardUnsplash拍摄

4.检查里面有什么 (4. Checking What’s Inside)

What is inside the string? It can be a number, it can be a word, or it can be a password with special characters. Sometimes we need to find out what’s inside the string to know what to do next. Let’s write some extensions to do it.

string里面有什么? 它可以是数字,可以是单词,也可以是带有特殊字符的密码。 有时我们需要找出字符串中的内容以了解下一步的工作。 让我们写一些扩展来做到这一点。

如何使用它 (How to use it)

val cl = "Contains letters".containsLatinLetter // trueval cnl = "12345".containsLatinLetter // falseval cd = "Contains digits 123".containsDigit // trueval istr = "123".isIntegerNumber // trueval dstr = "12.9".toDecimalNumber // true

Let’s say we need to check if a password is valid. This is for a new password, not verifying an existing one. The new password requires one digit, one Latin letter, and one non-alphanumeric character. Also, we don’t want spaces in password, except first and last characters, we just trim them. The last validation — length. We want our password to contain six to 20 characters.

假设我们需要检查密码是否有效。 这是用于新密码,而不是验证现有密码。 新密码需要一个数字,一个拉丁字母和一个非字母数字字符。 另外,我们不希望密码中的空格,除了第一个和最后一个字符外,我们只对它们进行修饰。 最后一次验证-长度。 我们希望密码包含6到20个字符。

val password = "yt6Hbb2.s(ma**213"val password2 = "yt6Hbb2sma213"val isPasswordValid = !password.isAlphanumeric && password.containsDigit && password.containsLatinLetter && password.length > 6 && password.length < 20 // trueval isPassword2Valid = !password2.isAlphanumeric && password2.containsDigit && password2.containsLatinLetter && password2.length > 6 && password2.length < 20 // false, doesn't contain non-alphanumeric characters
Image for post
Photo by Erda Estremera on Unsplash
Erda EstremeraUnsplash上的 照片

6.存储和检索本地设置 (6. Storing and Retrieving Local Settings)

This extension is Android-specific. Kotlin is an official language for Android development. More and more Play Store apps use Kotlin. Development time is shorter, quality is better, and at the same time there is full compatibility and interoperability with Java.

此扩展程序特定于Android。 Kotlin是Android开发的官方语言。 越来越多的Play商店应用使用Kotlin。 开发时间更短,质量更好,同时与Java具有完全的兼容性和互操作性。

Android apps have several ways to store local settings, but the most simple and native way is SharedPreferences.

Android应用程序有几种存储本地设置的方法,但是最简单和本机的方法是SharedPreferences

First argument is applicationContext: Context. If you run function from Activity, it can pass itself (as Activity is subclass of Context) or better, applicationContext.

第一个参数是applicationContext: Context 。 如果从Activity运行函数,则它可以传递自身(因为ActivityContext子类)或更好的是applicationContext

Second argument is value: Map<String, Any>. Maps in Kotlin are easy to create and use. In this extension Any can be any non-null value, but only five types will be saved: Int, Float, Long, Boolean and String.

第二个参数是value: Map<String, Any> 。 Kotlin中的地图易于创建和使用。 在此扩展中, Any可以是任何非null值,但是将仅保存五种类型: IntFloatLongBooleanString

Argument clear should be true if all fields in SharedPreferences, which are not in value, should be removed from SharedPreferences.

论点clear ,如果在各个领域应该是真实的SharedPreferences ,这是不是在value ,应被删除SharedPreferences

Another detail about SharedPreferences is background saving. There are two ways to save SharedPreferences: commit and apply. The difference is that commit applies changes immediately. apply does it in the background, which can make your app faster, but doesn’t guarantee immediate saving. In most cases apply is preferred, that’s why now argument should be false almost always.

关于SharedPreferences另一个细节是后台保存。 保存SharedPreferences有两种方法: commitapply 。 区别在于commit会立即应用更改。 apply会在后台执行此操作,这可以使您的应用更快,但不能保证立即保存。 在大多数情况下, apply是首选,这就是为什么now参数几乎总是false的原因。

如何使用它 (How to use it)

This example shows how an app can store game settings:

此示例显示了应用如何存储游戏设置:

"com.app.options".save(applicationContext,mapOf(
"volume" to 0.8f,
"fullscreen" to true
)
)val volume = "options".load(applicationContext)["volume"] as? Float // 0.8

Please note that here SharedPreferences are saved with apply. At the same time, it can be used immediately. It happens because SharedPreferences are stored in phone memory. If the app crashes right after, there’s a small chance that value won’t be saved, especially if it’s big.

请注意,此处SharedPreferencesapply一起保存。 同时,可以立即使用。 这是因为SharedPreferences存储在手机内存中。 如果该应用程序立即崩溃,则很有可能无法保存该值,尤其是当它很大时。

Image for post
Photo by Caspar Camille Rubin on Unsplash
Caspar Camille RubinUnsplash拍摄的照片

7.从字符串解析JSON (7. Parsing JSON From a String)

Java and Kotlin allow you to parse JSON into JSONObject or JSONArray classes (depending on content). Let’s add some syntactic sugar to make it faster and without exceptions. If String contains a valid JSON, function will return JSONObject or JSONArray, otherwise null.

Java和Kotlin允许您将JSON解析为JSONObjectJSONArray类(取决于内容)。 让我们添加一些语法糖以使其更快并且毫无例外。 如果String包含有效的JSON,则函数将返回JSONObjectJSONArray ,否则返回null

如何使用它 (How to use it)

Let’s parse JSON string and convert it to String again:

让我们解析JSON字符串,然后再次将其转换为String

val json = "{\"key\": \"value\"}".jsonObject  // {"key": "value"}val jsonAgain = json?.toString() // "{"key": "value"}"val stringFromJson = json?.getString("key") // "value"
Image for post
Photo by Jonatan Lewczuk on Unsplash
Jonatan LewczukUnsplash上的 照片

8.最后路径组件 (8. Last Path Component)

Apple Foundation has a very useful property lastPathComponent. If String contains a path or URL, it returns last component (after last ‘/’). Let’s replicate it as a Kotlin extension.

苹果基金会有一个非常有用的属性lastPathComponent 。 如果String包含路径或URL,则它将返回最后一个组件(在最后一个'/'之后)。 让我们将其复制为Kotlin扩展。

But first, I’d like to make two notes:

但首先,我想做两点说明:

  1. Path can end with trailing slash. The extension function should return path component before it; otherwise, it won’t process URLs.

    路径可以以斜杠结尾。 扩展功能应该在其之前返回路径组件; 否则,它将不会处理URL。
  2. Some systems (Microsoft Windows, for example) use backslash instead of slash. We should handle it too.

    某些系统(例如Microsoft Windows)使用反斜杠而不是斜杠。 我们也应该处理。

如何使用它 (How to use it)

val lpc1 = "https://google.com/chrome/".lastPathComponent // chromeval lpc2 = "C:\\Windows\\Fonts\\font.ttf".lastPathComponent // font.ttfval lpc3 = "/dev/null".lastPathComponent // null
Image for post
Photo by Plush Design Studio on Unsplash
图片由 Plush Design StudioUnsplash

9.字符串颜色 (9. Color From a String)

Color is represented differently in different environments. Android uses simple integers. It has Color class, but it just contains helper functions. Another representation is AWT Color class, which incapsulates four integer values for red, green, blue and alpha components.

颜色在不同环境中的表示方式有所不同。 Android使用简单的整数。 它具有Color类,但仅包含辅助函数。 另一种表示形式是AWT Color类,它封装了红色,绿色,蓝色和alpha分量的四个整数值。

将十六进制String解析为AWT Color (Parsing hex String to AWT Color)

如何使用它 (How to use it)

val c = "#010203".awtColor
print
(c.toString()) // java.awt.Color[r=1,g=2,b=3]

将十六进制字符串解析为Android颜色 (Parsing hex String to Android Color)

This class returns Int because Android uses Int in its views.

此类返回Int因为Android在其视图中使用Int

如何使用它 (How to use it)

val colorHex = "#010203"val color = colorHex.asColor // -16711165val nonColorHex = "abcdef"val nonColor = nonColorHex.asColor // null

You may ask: Why use extension if it replaces one line of code with another line of code?

您可能会问:如果扩展名将一行代码替换为另一行代码,为什么要使用扩展名?

val color1 = Color.parseColor(hexString)val color2 = hexString.asColor

There are two differences:

有两个区别:

  1. asColor extension can be chained. For example: hexString.asColor?.toString()

    可以链接asColor扩展。 例如: hexString.asColor?.toString()

  2. null instead of exception. You don’t need to wrap it in try-catch block. You’ll just get null if it’s not a valid color.

    null而不是异常。 您无需将其包装在try-catch块中。 如果它不是有效的颜色,则只会得到null

Image for post
Photo by Clay Banks on Unsplash
Clay BanksUnsplash拍摄的照片

10.将字符串格式设置为信用卡号 (10. Format String as Credit Card Number)

Some Android apps sell items or services, which can’t be paid by In-App Purchases. For the Java server app store, it uses and shows the credit card number to user. Usually apps keep it as a string without spaces. But 16 (or sometimes more) digits without any separation are not comfortable for users.

某些Android应用会出售商品或服务,而这些商品或服务无法通过“应用内购买”付款。 对于Java服务器应用商店,它使用并向用户显示信用卡号。 通常,应用程序将其保留为无空格的string 。 但是,没有分隔符的16(或更多)数字对于用户来说并不舒服。

This simple extension adds space after each four characters of a string:

这个简单的扩展在字符串的每个四个字符之后添加空格:

如何使用它 (How to use it)

val ccFormatted = "1234567890123456".creditCardFormatted // "1234 5678 9012 3456"

奖励:JSON的安全工作 (Bonus: Safe Work with JSON)

JSON and XML are two popular formats for data load, save, exchange, etc. It’s hard to imagine API call without one of these formats.

JSON和XML是用于数据加载,保存,交换等的两种流行格式。很难想象没有这些格式之一的API调用。

Java offers rather comfortable classes: JSONObject and JSONArray. Kotlin can use any Java class, so it’s a Kotlin way to parse and write JSON too. JSONObject and JSONArray are available in Android.

Java提供了相当舒适的类: JSONObjectJSONArray 。 Kotlin可以使用任何Java类,因此它也是解析和编写JSON的Kotlin方法。 JSONObjectJSONArray在Android中可用。

Why extend these classes? The problem is that they throw exception if something goes wrong. If anything goes wrong. For example, if you try to get the wrong data type, or if you refer to a field that doesn’t exist.

为什么要扩展这些类? 问题是,如果出现问题,它们将引发异常。 如果出了什么问题。 例如,如果您尝试获取错误的数据类型,或者您引用的字段不存在。

try {val obj = JSONObject()
obj.put("str", "abc")val strAsInt = obj.getInt("str") // org.json.JSONException: Value abc at str of type java.lang.String cannot be converted to intval noKey = obj.getString("iamnothere") // org.json.JSONException: No value for iamnothere
} catch (e: JSONException) {
e.printStackTrace()
}

There’s nothing wrong with exceptions; it’s a good way to handle such situations. But sometimes we need to pull only existing fields and ignore (keep as null) fields, which are not in API response.

例外没有错。 这是处理此类情况的好方法。 但是有时候我们只需要提取现有字段并忽略(保持为null )字段,这些字段不在API响应中。

Without extensions it can be done this way:

没有扩展,可以通过以下方式完成:

val firstName: String?try {
firstName = json.getString("first_name")
} catch (e: JSONException) {
firstName = null
}val lastName: String?try {
lastName = json.getString("last_name")
} catch (e: JSONException) {
lastName = null
}

Looks very long, right? Now imagine that server returns "null" instead of null. Code will grow for each field. This can be solved with extension:

看起来很长吧? 现在想象服务器返回"null"而不是null 。 每个领域的代码都会增加。 这可以通过扩展来解决:

This extension has some additional features like String trimming. It will be better if you look at it carefully instead of copying it to your project. Features like replacing "null" to null can be added this way:

该扩展名具有一些其他功能,例如字符串修整。 如果您仔细查看而不是将其复制到项目中,将会更好。 可以通过以下方式添加将"null"替换为null功能:

fun JSONObject.getStringOrNull(name: String): String? =try {val str = getString(name).trim()
if (str == "null") return nullreturn str
}catch (e: JSONException) {null
}

如何使用它 (How to use it)

val firstName = json.getStringOrNull("first_name")val lastName = json.getStringOrNull("last_name")

注意 (Note)

An alternative way to parse JSON is using external libraries: GSON or Moshi.

解析JSON的另一种方法是使用外部库: GSONMoshi

结论 (Conclusion)

You can be a JVM developer, Android developer, or more exotic Kotlin Native developer—I hope these extensions will be useful for you.

您可以是JVM开发人员,Android开发人员,或者是更多奇特的Kotlin Native开发人员-我希望这些扩展对您有用。

See you next time. Happy coding!

下次见。 编码愉快!

翻译自: https://medium.com/better-programming/10-useful-kotlin-string-extensions-46772b653f71

kotlin 字符串

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值