【问题标题】:Attempting to insert an image into a sqlite database API 21尝试将图像插入到 sqlite 数据库 API 21
【发布时间】:2025-11-29 07:05:03
【问题描述】:

我是 android 新手,如果这是一个简单的问题,请原谅我,但我正在尝试在 API 21 中将图像插入我的数据库,因此我无法使用 Files.readAllBytes。我在这里找到了一些将图像转换为数组的代码,但我不确定它是如何工作的,也不确定它返回什么。然后我想使用数组并执行ContentValues.put("Head", (the array) )。提前谢谢大家。

public boolean insertAvatar(Image Head) {
    SQLiteDatabase db = this.getWritableDatabase();
    ContentValues contentValues = new ContentValues();
    //File head = new File("C:capaa\\src\\main\\res\\drawable\\head2.png");

    File head = new File("C:capaa\\src\\main\\res\\drawable\\head2.png"); 
    try {
        read(head); // calling the convert method on my head file 
    }catch (IOException e){ }
    ContentValues.put("Head",head); // this is the line im not sure about 

    long ins = db.insert("Avatar", null, contentValues);
    return true;
}

//converts to bytes
public byte[] read(File file) throws IOException {
    ByteArrayOutputStream ous = null;
    InputStream ios = null;
    try {
        byte[] buffer = new byte[4096];
        ous = new ByteArrayOutputStream();
        ios = new FileInputStream(file);
        int read = 0;
        while ((read = ios.read(buffer)) != -1) {
            ous.write(buffer, 0, read);
        }
    }finally {
        try {
            if (ous != null)
                ous.close();
        } catch (IOException e) {
        }

        try {
            if (ios != null)
                ios.close();
        } catch (IOException e) {
        }
    }
    return ous.toByteArray();
}

【问题讨论】:

  • "C:capaa\\src\\main\\res\\drawable\\head2.png"C: 之后缺少反斜杠是故意的吗?如果这应该适用于 Android,为什么要使用明显的 Windows 路径?
  • @stickybit 我试图在我的可绘制文件夹中获取一张图片,然后剪切路径,因为它对于这篇文章来说是巨大的。您知道获取可绘制文件的最佳方法,还是列出整个路径的唯一方法?我可以简单地做“drawable/head2.png”
  • @stickybit 我也试过 "String HeadUri = "drawable://" + R.drawable.head2;"但在读取方法 cri 中仍然无法识别

标签: android arrays sqlite


【解决方案1】:

read 方法应该返回一个字节[],然后您可以简单地使用:-

ContentValues.put("Head",read(head)); 

insert 便利方法将 read 返回的 byte[] 转换为适当的字符串 x'f1f2f3f0......',其中每个十六进制值是数组中的一个字节,这是由 insert 便捷方法生成的 SQL 中使用的字符串。

  • 请注意,如果图像接近 1MB,或者绝对大小为 2MB,那么您在检索数据时可能会遇到问题,因为 CursorWindow(存储行的缓冲区)是 1MB,更高版本是 2MB。因为至少 1 行(非常低效)必须适合 CursorWindow。
  • 一般不建议将图像存储在数据库中,而是将图像文件的路径存储在数据库中。

【讨论】:

  • 对于将如此庞大的数据写入 sqlite 数据库,您有何看法?它不会减慢读数吗?我也不知道 ContentValues.put 函数是否会给你一个字节实际可以占用的长度,因为字节只能保存 -128 到 127 之间的值。介意分享更多吗?另外,一列可以在 sqlite 中包含的最大字符串长度是多少?不过我会对此进行研究。
  • 感谢您的回复,只是一个简单的问题,我认为我的文件路径是错误的。我尝试使用 String "HeadUri = "drawable://" + R.drawable.head2;"但仍然没有运气
【解决方案2】:

为什么要将整个图像插入数据库?当您只有以下几个选项时?

Opt1:将图像保存在本地设备存储中,并将路径存储到您的数据库中,这是一个字符串。

Opt2:使用像Picasso这样优化好的图像库并直接从链接加载图像,Picasso 会以非常好的水平为您捕获图像,您可以阅读更多关于如果您想了解更多信息,库缓存文件的方式。

Opt3:@MikeT 上面的回答,就像他说的那样,当图像大小超过 1MB 时,您可能无法检索数据,对此,它会使您的数据库变得如此繁重,所以这不是一个好方法。

关于 opt1 的一些提示:

您可以创建一个如下所示的简单表格:

关于 opt2 的一些提示:

implementation 'com.squareup.picasso:picasso:2.71828' 添加到您的 build.gradle(Module: app) 并构建。

然后你可以使用如下库:

Picasso.get()
    .load(imgUrl)
    .error(R.drawable.user_placeholder_error)/*just incase fetching image failed, this drawable will show up instead. it's up to you, you can remove it either way.*/
    .into(imageView);//a reference to the imageView you want to display the image on

祝你好运,希望它会有所帮助。

【讨论】: