如何将位图保存在从 Internet 下载的内部存储中

Posted

技术标签:

【中文标题】如何将位图保存在从 Internet 下载的内部存储中【英文标题】:How to save bitmap on internal storage download from internet 【发布时间】:2013-11-14 12:50:22 【问题描述】:

我正在使用 Asynctask 从 Internet 下载图像。

我想将此图像保存到内部存储中,稍后我想使用此图像。

我可以下载成功,但我找不到它存储的内部存储路径。

这个下载Images.java

private class DownloadImages extends AsyncTask<String,Void,Bitmap> 

        private Bitmap DownloadImageBitmap()
            HttpURLConnection connection    = null;
            InputStream is                  = null;

            try 
                URL get_url     = new URL("http://www.medyasef.com/wp-content/themes/medyasef/images/altlogo.png");
                connection      = (HttpURLConnection) get_url.openConnection();
                connection.setDoInput(true);
                connection.setDoOutput(true);
                connection.connect();
                is              = new BufferedInputStream(connection.getInputStream());
                final Bitmap bitmap = BitmapFactory.decodeStream(is);
               // ??????????

             catch (MalformedURLException e) 
                e.printStackTrace();
             catch (IOException e) 
                e.printStackTrace();
            
            finally 
                connection.disconnect();
                try 
                    is.close();
                 catch (IOException e) 
                    e.printStackTrace();
                
            

            return null;
        

        @Override
        protected Bitmap doInBackground(String... params) 
            return DownloadImageBitmap();
        

    

任何帮助将不胜感激。 :)

谢谢。

【问题讨论】:

android Saving created bitmap to directory on sd card的可能重复 您已获得位图final Bitmap bitmap = BitmapFactory.decodeStream(is); 使用此位图以备将来使用。有什么大不了的? 看这个答案***.com/a/7887114/964741 【参考方案1】:

您可以像这样在内部存储中保存和加载图像: 保存:

public static void saveFile(Context context, Bitmap b, String picName) 
    FileOutputStream fos; 
    try  
        fos = context.openFileOutput(picName, Context.MODE_PRIVATE); 
        b.compress(Bitmap.CompressFormat.PNG, 100, fos);  
      
    catch (FileNotFoundException e)  
        Log.d(TAG, "file not found"); 
        e.printStackTrace(); 
      
    catch (IOException e)  
        Log.d(TAG, "io exception"); 
        e.printStackTrace(); 
     finally 
        fos.close();
    

加载中:

public static Bitmap loadBitmap(Context context, String picName) 
    Bitmap b = null; 
    FileInputStream fis; 
    try  
        fis = context.openFileInput(picName); 
        b = BitmapFactory.decodeStream(fis);   
      
    catch (FileNotFoundException e)  
        Log.d(TAG, "file not found"); 
        e.printStackTrace(); 
      
    catch (IOException e)  
        Log.d(TAG, "io exception"); 
        e.printStackTrace(); 
     finally 
        fis.close();
    
    return b; 
 

但是如果您想在应用程序关闭时再次找到它,则需要以某种方式保存 imageName。我会推荐一个 SQLLite 数据库,它将 imageNames 映射到数据库中的条目。

【讨论】:

您好,这个答案对我有用。但我还有一个问题。我的文件名 data/data//files/picName 但我想要这样。数据/数据//files/**images**/picName 我不确定您是否可以在内部存储中使用“/”。您可能必须用其他东西替换它们。 pathName.replaceAll("/", "_"); 另外,为了让你的 nameScheme:split[] = string.split("/")。然后 split[4] = " ** "+split[4]+" ** "; fis = context.openFileInput(picName);是我的解决方案,我错过了 context for openFileInput()【参考方案2】:

试试这个:

String path = Environment.getExternalStorageDirectory().toString();
OutputStream fOut = null;
String imageName = "yourImageName";
File file = new File(path, imageName);
try 
    fOut = new FileOutputStream(file);
    if (!yourBitmap.compress(Bitmap.CompressFormat.JPEG, 90, fOut)) 
        Log.e("Log", "error while saving bitmap " + path + imageName);
    
 catch (FileNotFoundException e) 
    // TODO Auto-generated catch block
    e.printStackTrace();

【讨论】:

首先感谢您的回答,但我不想要外部存储。【参考方案3】:

我在 Kotlin 上的解决方案。 (基于另一个答案)

import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import java.io.FileInputStream
import java.io.FileNotFoundException
import java.io.FileOutputStream
import java.io.IOException

class InternalStorageProvider(var context: Context) 

fun saveBitmap(bitmap: Bitmap, imageName: String) 
    var fileOutputStream: FileOutputStream? = null
    try 
        fileOutputStream = context.openFileOutput(imageName, Context.MODE_PRIVATE)
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream)
     catch (e: FileNotFoundException) 
        e.printStackTrace()
     catch (e: IOException) 
        e.printStackTrace()
     finally 
        fileOutputStream?.close()
    


fun loadBitmap(picName: String): Bitmap? 
    var bitmap: Bitmap? = null
    var fileInputStream: FileInputStream? = null
    try 
        fileInputStream = context.openFileInput(picName)
        bitmap = BitmapFactory.decodeStream(fileInputStream)
     catch (e: FileNotFoundException) 
        e.printStackTrace()
     catch (e: IOException) 
        e.printStackTrace()
     finally 
        fileInputStream?.close()
    

    return bitmap


【讨论】:

你能解释一下你是如何初始化这个类的吗?使用InternalStorageProvider(context).saveBitmap(bitmap, filename) 调用此类时遇到问题。我做错什么了吗? 请提供一些细节。你是在Activity、Fragment还是其他类中试试下面的代码 我从片段中调用这个类。如果我将此代码放在片段中,它就可以工作。这是一个有点奇怪的问题,因为由于某种原因我无法将此类导入片段:import com.packagename... helpers.InternalStorageProvider 未解决。如果我删除上下文构造函数导入工作。 猜猜看,在片段中工作。无论如何,我稍后会对此进行探索,我只是想知道我的语法是否正常,看起来是这样。我还是 Kotlin 的新手,我正在将我的代码从 Java 重写为 Android ..【参考方案4】:

您是否考虑过使用 Glide 库(或 Picasso)来下载图片?这样您就可以抽象出 Http 连接、磁盘保存、内存和磁盘缓存、离线功能等所有低级细节。此外,如果您选择 Glide,您会在图像加载时自动获得一些整齐的淡入淡出动画。

示例(科特林)

下载到磁盘:

Glide.with(applicationContext)
   .load(user.picUrl)
   .downloadOnly(object : SimpleTarget<File>() 
      override fun onResourceReady(res: File, glideAnimation: GlideAnimation<in File>) 
   )

从缓存加载,如果缓存不可用则下载:

Glide.with(callingActivity.applicationContext)
   .load(wallPostViewHolder.mUser!!.picUrl)
   .skipMemoryCache(true)
   .diskCacheStrategy(DiskCacheStrategy.SOURCE)
   .into(wallPostViewHolder.vPic)

【讨论】:

【参考方案5】:

当您对此进行编程并运行该应用程序时,有时需要从您的模拟器/手机中卸载该应用程序(如果您已将文件定义为文件夹,并且您更正了该文件,但在模拟器的内存中/手机还是文件夹)

【讨论】:

【参考方案6】:

如果您使用的是 kotlin,请使用以下函数。你必须提供一个存储图像的路径,一个位图(转换你的图像,然后将该位图传递给这个函数),如果你想降低图像的质量,那么提供 %age 即 10%。

fun cacheToLocal(localPath: String, bitmap: Bitmap, quality: Int = 100) 
        val file = File(localPath)
        file.createNewFile()
        val ostream = FileOutputStream(file)
        bitmap.compress(Bitmap.CompressFormat.JPEG, quality, ostream)
        ostream.flush()
        ostream.close()
    

【讨论】:

以上是关于如何将位图保存在从 Internet 下载的内部存储中的主要内容,如果未能解决你的问题,请参考以下文章

C++如何把位图保存到数组中

将位图保存到位置

在从 Internet 下载数据期间,在 AsyncTask 的 onProgressUpdate 中显示确定的 ProgressBar

如何检查 ImageView 是不是包含位图?

如何使用 Glide 将图像保存到内部存储?

如何将位图添加到电话库?