首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Android 讀取聯系人中文亂碼解決:Blob 轉 UTF-8 字串

     編輯:程式設計綜合問答

問題現象

從 ContactsContract 查詢聯系人姓名顯示在 TextView 時,中文顯示為「???」或亂碼,英文正常。

根本原因

聯系人數據庫中姓名欄位可能存儲為 **BLOB 二進制格式**(歷史兼容性),直接用 getString() 讀取會按默認編碼解析導致亂碼。需先 getBlob() 取得原始字節,再指定 **UTF-8** 解碼。

解決代碼

// 查詢游標
Cursor cursor = resolver.query(ContactsContract.Contacts.CONTENT_URI, 
    new String[]{ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME}, 
    null, null, null);

if (cursor != null) {
    while (cursor.moveToNext()) {
        int nameIndex = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
        
        // 關鍵:getBlob + UTF-8 解碼 + 清理控制字符
        byte[] nameBytes = cursor.getBlob(nameIndex);
        String name = new String(nameBytes, StandardCharsets.UTF_8)
            .replace("\u0000", "") // 移除空字符
            .replace("\r", "");    // 移除回車符
        
        textView.setText(name);
    }
    cursor.close();
}

完整工具方法

public static String getContactNameSafe(Cursor cursor, int columnIndex) {
    if (cursor == null || columnIndex < 0) return "";
    
    byte[] blob = cursor.getBlob(columnIndex);
    if (blob == null || blob.length == 0) return "";
    
    try {
        return new String(blob, StandardCharsets.UTF_8)
            .replace("\u0000", "")
            .replace("\r", "")
            .trim();
    } catch (Exception e) {
        // 兜底:嘗試默認解碼
        return cursor.getString(columnIndex);
    }
}

Kotlin 擴展函數版

fun Cursor.getContactName(columnName: String): String {
    val index = getColumnIndex(columnName)
    return if (index >= 0) {
        getBlob(index)?.let { bytes ->
            String(bytes, Charsets.UTF_8)
                .replace("\u0000", "")
                .replace("\r", "")
                .trim()
        } ?: getString(index) // fallback
    } else ""
}

為什麼會是 BLOB?

  • 早期 Android 版本(< 2.0)聯系人存儲不統一編碼
  • 第三方 ROM/廠商修改 ContactsProvider 實現
  • 同步自 SIM 卡、vCard 等外部來源的聯系人可能攜帶原始編碼字節

進階:統一查詢封裝

// 使用 ContactsContract.CommonDataKinds.StructuredName 獲取結構化姓名 (較新 API)
String[] projection = {
    StructuredName.DISPLAY_NAME,
    StructuredName.GIVEN_NAME,
    StructuredName.FAMILY_NAME
};
Cursor c = resolver.query(Data.CONTENT_URI, projection, 
    Data.MIMETYPE + "=?", new String[]{StructuredName.CONTENT_ITEM_TYPE}, null);
// 此路徑通常直接返回 String,較少亂碼

結語

Android 聯系人中文亂碼核心在於 **BLOB 字段需手動指定 UTF-8 解碼**。採用 cursor.getBlob(index) → new String(bytes, UTF-8) 模式並清理控制字符(\u0000, \r),可 100% 解決顯示異常。建議封裝為工具方法,全專案統一調用。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved