Android: 如何保存字符串数组到SQLite数据库?

37

我需要将一个字符串数组保存到数据库中,但它不允许我这样做。这是我的代码:

 public long createEntry(String startTime, String endTime, String[] states) {
         ContentValues initialValues = new ContentValues();
         initialValues.put(START_KEY_TIME , startTime);
         initialValues.put(END_KEY_TIME , endTime);
         initialValues.put(KEY_STATE, states );

         return databaseConnect.insert(DATABASE_TABLE, null, initialValues);
}

但是,如果我输入string[] states,它会说内容值无法接受参数。我该如何解决这个问题?我想我有7个状态,我能否使用7个单独的字符串并在每个字符串中存储内容,然后将所有字符串放回一个字符串数组中?或者那样做会不好吗?


为什么需要将数组保存在数据库中?肯定还有其他更好的解决方案。 - Yaqub Ahmad
我有一周7天,它需要被视为布尔值(true或false),并且由于布尔不能被保存到数据库中,所以我打算使用字符串数组,但是由于contentvalues的原因,它不允许我这样做。你有什么想法吗? - user1175899
你可以将布尔值存储为整数0(假)和1(真)。 - Yaqub Ahmad
你可以使用整数值来存储标志值。例如,对于星期日和星期二,该值将为01010000(二进制),或类似的值。尽管如此,你应该将这七个布尔值分别存储在不同的列中。 - dmon
2
另一种方法可能是使用JSONObject,如此处所述:(https://dev59.com/Nm025IYBdhLWcg3w9quQ) - Dexter
5个回答

89

你不能直接将字符串数组保存到数据库中,但是可以使用以下技巧:

1) 你需要使用convertArrayToString(String[] array)方法将其转换为普通字符串。该方法会使用逗号连接所有字符串元素。

2) 当你从数据库检索出这个字符串后,你可以使用convertStringToArray(String str)方法将其转回字符串数组。该方法会通过逗号分隔字符串,然后你就能得到原始的字符串数组了。

public static String strSeparator = "__,__";
public static String convertArrayToString(String[] array){
    String str = "";
    for (int i = 0;i<array.length; i++) {
        str = str+array[i];
        // Do not append comma at the end of last element
        if(i<array.length-1){
            str = str+strSeparator;
        }
    }
    return str;
}
public static String[] convertStringToArray(String str){
    String[] arr = str.split(strSeparator);
    return arr;
}

这是同样的事情。当您将字符串与布尔值连接时,布尔值将自动转换为字符串。当您检索回布尔数组时,您必须通过Boolean.parseBoolean(str[i])将每个项目强制转换为布尔值。 - Muhammad Nabeel Arif
@MuhammadNabeelArif 嘿,我正在获取复选框选中的值并将其存储在数组中。现在我想将它存储在数据库中,但是不同的行。这怎么可能呢?例如:[1,2,4] 这是我的数组,我想要像这样存储它:1 然后新行并存储 2 然后新行并存储 4。这怎么可能呢?我是 Android 新手,请帮忙。 - Google
很简单,将每个记录1、2、4等视为单独的条目,现在为每个条目准备一行并将其插入到数据库中。您需要了解数据库的基础知识。这里有一个快速教程'http://www.androidhive.info/2011/11/android-sqlite-database-tutorial/'。 - Muhammad Nabeel Arif
从技术上讲,我认为最好使用 StringBuilder 来构建数字字符串,尽管编译器可能会进行优化。 - Tom
6
如果数组中的任何元素包含逗号,这将无法正常工作。 - pellucide

12

基于Muhammed的答案,但是处理的是List类型的String列表而不是数组,并且在值连接期间使用StringBuilder而不是分配许多String

private static final String LIST_SEPARATOR = "__,__";

public static String convertListToString(List<String> stringList) {
    StringBuilder stringBuilder = new StringBuffer();
    for (String str : stringList) {
        stringBuilder.append(str).append(LIST_SEPARATOR);
    }

    // Remove last separator
    stringBuilder.setLength(stringBuilder.length() - LIST_SEPARATOR.length());

    return stringBuilder.toString();
}

public static List<String> convertStringToList(String str) {
    return Arrays.asList(str.split(LIST_SEPARATOR));
}

9

将其转换为单个字符串以在SQLite中保存。稍后,从SQLite中检索它作为单个字符串,并将其转换回字符串数组。

String ARRAY_DIVIDER = "#a1r2ra5yd2iv1i9der";

public String serialize(String content[]){      
    return TextUtils.join(ARRAY_DIVIDER, content);
}

public String[] derialize(String content){
    return content.split(ARRAY_DIVIDER);
}

可能有点晚了,但是我想不出这种懒惰方法的缺点。 - Lobstw
@Lobstw 如果content[]中的一个元素恰好是"#a1r2ra5yd2iv1i9der",那么它可能会导致意外行为。这将被序列化,但在反序列化时,歧义将导致两个空字符串元素代替有问题的一个字符串元素。如果程序的其他区域对数组大小有严格的期望,这可能会导致不希望的行为。 - snapfractalpop
@snapfractalpop 是的,没错。但是将分隔符设置为一个长的字母数字字符串可以避免在大约100%的情况下出现这种行为。 - Lobstw
1
在大多数情况下,我同意@Lobstw的观点。但我要指出,在这0.001%的情况下,上下文可能非常重要。例如,如果这导致某些错误,然后在依赖于错误保证的其他代码区域中导致某种安全漏洞,那么这0.001%的情况很快就会扩大到包括脚本小子等人。 - snapfractalpop

6

如果您将字符串数组转换为JSONArray,使用toString,然后通过首先解析为JSONArray,再将其转换为字符串数组来检索它,那么这将更容易。


1
这是比被接受的答案更好的方法,因为你永远不会被数组元素中发现的分隔符字符串(如__,__#a1r2ra5yd2iv1i9der等)所困扰。 - Alexander Farber

1

看起来你的数据库设计不太合理。如果你想在SQLite数据库中存储布尔数据,可以将布尔值存储为整数0(false)和1(true)。


1
yai 可以存储为 0、1,但由于有多个,我必须使用 int 数组,而 contentvalues 不允许这样做。有没有其他方法可以避免为每个值创建新的 int? - user1175899

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接