在 Android 的外部存储中写入文件

Posted

技术标签:

【中文标题】在 Android 的外部存储中写入文件【英文标题】:Write a file in external storage in Android 【发布时间】:2012-01-09 22:40:15 【问题描述】:

我想在外部存储 sdCard 中创建一个文件并写入它。我已经通过互联网搜索并尝试但没有得到结果,我也在 android Manifest 文件中添加了权限,我正在模拟器上执行此操作,我我正在尝试以下代码并得到一个 ERRR", "Could not create file"。

btnWriteSDFile = (Button) findViewById(R.id.btnWriteSDFile);
btnWriteSDFile.setOnClickListener(new OnClickListener() 
    //private Throwable e;

    @Override
    public void onClick(View v) 
        // write on SD card file data from the text box
        try 
            File myFile = new File("/sdcard/mysdfile.txt");
            myFile.createNewFile();
            FileOutputStream fOut = new FileOutputStream(myFile);
            OutputStreamWriter myOutWriter = new OutputStreamWriter(fOut);
            myOutWriter.append(txtData.getText());
            myOutWriter.close();
            fOut.close();

         catch (Exception e) 
              Log.e("ERRR", "Could not create file",e);
         
    // onClick
); // btnWriteSDFile

【问题讨论】:

把它放在你的“catch”块中,用打印到日志的错误更新你的问题:Log.e("ERRR", "Could not create file",e); 你得到什么样的错误信息,你能提供 logcat 的详细信息 你在 AndroidManifest.xml 文件中添加了 android.permission.WRITE_EXTERNAL_STORAGE 我在 AndroidManifest 文件中添加了权限,但在 logcat 中出现错误(ERRR 无法创建文件) 您是否在模拟器中添加了外部存储空间? 【参考方案1】:

您也可以使用此代码执行此操作。

 public class WriteSDCard extends Activity 

 private static final String TAG = "MEDIA";
 private TextView tv;

  /** Called when the activity is first created. */
@Override
 public void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);     
    tv = (TextView) findViewById(R.id.TextView01);
    checkExternalMedia();
    writeToSDFile();
    readRaw();
 

/** Method to check whether external media available and writable. This is adapted from
   http://developer.android.com/guide/topics/data/data-storage.html#filesExternal */

 private void checkExternalMedia()
      boolean mExternalStorageAvailable = false;
    boolean mExternalStorageWriteable = false;
    String state = Environment.getExternalStorageState();

    if (Environment.MEDIA_MOUNTED.equals(state)) 
        // Can read and write the media
        mExternalStorageAvailable = mExternalStorageWriteable = true;
     else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) 
        // Can only read the media
        mExternalStorageAvailable = true;
        mExternalStorageWriteable = false;
     else 
        // Can't read or write
        mExternalStorageAvailable = mExternalStorageWriteable = false;
       
    tv.append("\n\nExternal Media: readable="
            +mExternalStorageAvailable+" writable="+mExternalStorageWriteable);


/** Method to write ascii text characters to file on SD card. Note that you must add a 
   WRITE_EXTERNAL_STORAGE permission to the manifest file or this method will throw
   a FileNotFound Exception because you won't have write permission. */

private void writeToSDFile()

    // Find the root of the external storage.
    // See http://developer.android.com/guide/topics/data/data-  storage.html#filesExternal

    File root = android.os.Environment.getExternalStorageDirectory(); 
    tv.append("\nExternal file system root: "+root);

    // See http://***.com/questions/3551821/android-write-to-sd-card-folder

    File dir = new File (root.getAbsolutePath() + "/download");
    dir.mkdirs();
    File file = new File(dir, "myData.txt");

    try 
        FileOutputStream f = new FileOutputStream(file);
        PrintWriter pw = new PrintWriter(f);
        pw.println("Hi , How are you");
        pw.println("Hello");
        pw.flush();
        pw.close();
        f.close();
     catch (FileNotFoundException e) 
        e.printStackTrace();
        Log.i(TAG, "******* File not found. Did you" +
                " add a WRITE_EXTERNAL_STORAGE permission to the   manifest?");
     catch (IOException e) 
        e.printStackTrace();
       
    tv.append("\n\nFile written to "+file);


/** Method to read in a text file placed in the res/raw directory of the application. The
  method reads in all lines of the file sequentially. */

private void readRaw()
    tv.append("\nData read from res/raw/textfile.txt:");
    InputStream is = this.getResources().openRawResource(R.raw.textfile);
    InputStreamReader isr = new InputStreamReader(is);
    BufferedReader br = new BufferedReader(isr, 8192);    // 2nd arg is buffer size

    // More efficient (less readable) implementation of above is the composite expression
    /*BufferedReader br = new BufferedReader(new InputStreamReader(
            this.getResources().openRawResource(R.raw.textfile)), 8192);*/

    try 
        String test;    
        while (true)               
            test = br.readLine();   
            // readLine() returns null if no more lines in the file
            if(test == null) break;
            tv.append("\n"+"    "+test);
        
        isr.close();
        is.close();
        br.close();
     catch (IOException e) 
        e.printStackTrace();
    
    tv.append("\n\nThat is all");


【讨论】:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> 也必须添加到清单中。 与其他一些不同的是,在 8 级之前和 7 级之后工作 如果我告诉你我的状态是mountedcanWrite() = false?!我正在测试sd card getExternalStorageDirectory 在 Android 10 中已弃用,取而代之的是 Scoped Storage。 对于 android 10,您应该将 android:requestLegacyExternalStorage="true" 设置为应用程序范围以工作【参考方案2】:

要写入 Lollipop+ 设备中的外部存储,我们需要:

    在 Manifest 中添加以下权限:

           <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    

    请求用户批准:

           public static final int REQUEST_WRITE_STORAGE = 112; 
    
           private requestPermission(Activity context) 
               boolean hasPermission = (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED);
               if (!hasPermission) 
                  ActivityCompat.requestPermissions(context,
                     new String[]Manifest.permission.WRITE_EXTERNAL_STORAGE,
                   REQUEST_WRITE_STORAGE);
                else 
                 // You are allowed to write external storage:
                 String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/new_folder";
                 File storageDir = new File(path);
                 if (!storageDir.exists() && !storageDir.mkdirs()) 
                   // This should never happen - log handled exception!
                 
               
    

    在 Activity 中处理用户响应:

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) 
         super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    
         switch (requestCode)
         
          case Preferences.REQUEST_WRITE_STORAGE: 
             if (grantResults.length > 0 && grantResults[0] ==  PackageManager.PERMISSION_GRANTED) 
               Toast.makeText(this, "The app was allowed to write to your storage!", Toast.LENGTH_LONG).show();
               // Reload the activity with permission granted or use the features what required the permission
              else 
               Toast.makeText(this, "The app was not allowed to write to your storage. Hence, it cannot function properly. Please consider granting it this permission", Toast.LENGTH_LONG).show();
            
         
     
    

【讨论】:

是的,但是您仍然没有说明如何访问外部 /emulated/0/ 存储。【参考方案3】:

虽然上面的答案都是正确的,但我还是想加个提示来区分存储类型:

内部存储:应该说“私人存储”,因为它属于应用程序,不能共享。它的保存位置取决于应用程序的安装位置。如果该应用程序安装在 SD 卡上(我的意思是您将更多的外部存储卡放入手机中以获得更多空间来存储图像、视频等),您的文件将属于该应用程序意味着您的文件将在一张 SD 卡。如果应用安装在内部卡上(我是指手机随附的板载存储卡),您的文件将在内部卡中。 外部存储:应该说“公共存储”,因为它可以共享。该模式分为2组:私有外部存储和公共外部存储。基本都差不多,可以从本站咨询更多:https://developer.android.com/training/data-storage/files 真正的 SD 卡(我的意思是您将更多的外部存储卡放入手机中以获得更多空间来存储图像,视频,...):Android 文档中没有明确说明,所以很多人们可能会对如何在此卡中保存文件感到困惑。

这里是我上面提到的案例的源代码链接:https://github.com/mttdat/utils/blob/master/utils/src/main/java/mttdat/utils/FileUtils.java

【讨论】:

根据我数周以来的研究,内部存储是内置设备存储。 外部存储是一种非内部存储,但大部分时间存在于设备上,即 SD 卡。而且外部存储不等于可移动存储所以祝你好运(对我来说)尝试将某些东西传递给像闪存驱动器一样。【参考方案4】:

您应该阅读documentation on storing stuff externally on Android。您当前的代码可能存在许多问题,我认为查看文档可能会帮助您解决这些问题。

【讨论】:

【参考方案5】:

下面的代码创建一个Documents目录,然后为应用程序创建一个子目录并将文件保存到其中。

public class loadDataTooDisk extends AsyncTask<String, Integer, String> 
    String sdCardFileTxt;
    @Override
    protected String doInBackground(String... params)
    

        //check to see if external storage is avalibel
        checkState();
        if(canW == canR == true)
        
            //get the path to sdcard 
            File pathToExternalStorage = Environment.getExternalStorageDirectory();
            //to this path add a new directory path and create new App dir (InstroList) in /documents Dir
            File appDirectory = new File(pathToExternalStorage.getAbsolutePath()  + "/documents/InstroList");
            // have the object build the directory structure, if needed.
            appDirectory.mkdirs();
            //test to see if it is a Text file
            if ( myNewFileName.endsWith(".txt") )
            

                //Create a File for the output file data
                File saveFilePath = new File (appDirectory, myNewFileName);
                //Adds the textbox data to the file
                try
                    String newline = "\r\n";
                    FileOutputStream fos = new FileOutputStream (saveFilePath);
                    OutputStreamWriter OutDataWriter  = new OutputStreamWriter(fos);

                    OutDataWriter.write(equipNo.getText() + newline);
                    // OutDataWriter.append(equipNo.getText() + newline);
                    OutDataWriter.append(equip_Type.getText() + newline);
                    OutDataWriter.append(equip_Make.getText()+ newline);
                    OutDataWriter.append(equipModel_No.getText()+ newline);
                    OutDataWriter.append(equip_Password.getText()+ newline);
                    OutDataWriter.append(equipWeb_Site.getText()+ newline);
                    //OutDataWriter.append(equipNotes.getText());
                    OutDataWriter.close();

                    fos.flush();
                    fos.close();

                catch(Exception e)
                    e.printStackTrace();
                
            
        
        return null;
    

这个构建文件名

   private String BuildNewFileName()
     // creates a new filr name
        Time today = new Time(Time.getCurrentTimezone());
        today.setToNow();

        StringBuilder sb = new StringBuilder();

        sb.append(today.year + "");                // Year)
        sb.append("_");
        sb.append(today.monthDay + "");          // Day of the month (1-31)
        sb.append("_");
        sb.append(today.month + "");              // Month (0-11))
        sb.append("_");
        sb.append(today.format("%k:%M:%S"));      // Current time
        sb.append(".txt");                      //Completed file name

        myNewFileName = sb.toString();
        //Replace (:) with (_)
        myNewFileName = myNewFileName.replaceAll(":", "_");

        return myNewFileName;
    

希望这会有所帮助!我花了很长时间才让它工作。

【讨论】:

您可以在手机等的“我的文件”中查找文件并打开查看文本。 Environment.getExternalStorageDirectory() 已弃用,这是解决方案的核心问题,总有一天会停止工作。【参考方案6】:

补充答案

写入外部存储后,某些文件管理器无法立即看到该文件。如果用户认为他们将某些内容复制到 SD 卡中,但随后无法在 SD 卡中找到,这可能会造成混淆。因此,在复制文件后,运行以下代码通知文件管理器它的存在。

MediaScannerConnection.scanFile(
        context,
        new String[]myFile.getAbsolutePath(),
        null,
        null);

请参阅documentation 和this answer 了解更多信息。

【讨论】:

【参考方案7】:

你可以发现这些方法在android中读写数据时很有用。

 public void saveData(View view) 
    String text = "This is the text in the file, this is the part of the issue of the name and also called the name od the college ";
    FileOutputStream fos = null;
    try 
        fos = openFileOutput("FILE_NAME", MODE_PRIVATE);
        fos.write(text.getBytes());
        Toast.makeText(this, "Data is saved "+ getFilesDir(), Toast.LENGTH_SHORT).show();
     catch (FileNotFoundException e) 
        e.printStackTrace();
     catch (IOException e) 
        e.printStackTrace();
    finally 
        if (fos!= null)
            try 
                fos.close();
             catch (IOException e) 
                e.printStackTrace();
            
        
    




public void logData(View view) 
    FileInputStream fis = null;

    try 
        fis = openFileInput("FILE_NAME");
        InputStreamReader isr = new InputStreamReader(fis);
        BufferedReader br = new BufferedReader(isr);
        StringBuilder sb=  new StringBuilder();
        String text;
        while((text = br.readLine()) != null)
            sb.append(text).append("\n");
            Log.e("TAG", text
            );
        

     catch (FileNotFoundException e) 
        e.printStackTrace();
     catch (IOException e) 
        e.printStackTrace();
    finally 
        if(fis != null)
            try 
                fis.close();
             catch (IOException e) 
                e.printStackTrace();
            
        
    


【讨论】:

【参考方案8】:
 ContextWrapper contextWrapper = new ContextWrapper(getApplicationContext()); //getappcontext for just this activity context get
 File file = contextWrapper.getDir(file_path, Context.MODE_PRIVATE);  
 if (!isExternalStorageAvailable() || isExternalStorageReadOnly()) 
  
  saveToExternalStorage.setEnabled(false);
 
 else
 
  External_File = new File(getExternalFilesDir(file_path), file_name);//if ready then create a file for external 
 


 try
  
   FileInputStream fis = new FileInputStream(External_File);
   DataInputStream in = new DataInputStream(fis);
   BufferedReader br =new BufferedReader(new InputStreamReader(in));
   String strLine;
   while ((strLine = br.readLine()) != null) 
   
    myData = myData + strLine;
   
   in.close();
  
  catch (IOException e) 
  
   e.printStackTrace();
  
  InputText.setText("Save data of External file::::  "+myData);


private static boolean isExternalStorageReadOnly() 
 
 String extStorageState = Environment.getExternalStorageState(); 
 if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(extStorageState))
  
  return true; 
  
 return false; 
 

private static boolean isExternalStorageAvailable()
 
 String extStorageState = Environment.getExternalStorageState(); 
 if (Environment.MEDIA_MOUNTED.equals(extStorageState))
  
  return true; 
  
 return false; 
 

【讨论】:

这段代码在哪里可以访问 saveToExternalStorage 对象?

以上是关于在 Android 的外部存储中写入文件的主要内容,如果未能解决你的问题,请参考以下文章

无法在文件夹中写入外部存储下载 - Android

如何将文件写入 Android 中的外部公共存储,以便它们在 Windows 中可见?

在读取/写入文件到内部/外部存储android时使用啥类和方法?

无法在Android上写入外部存储

课堂整理:写入和读取外部存储文件

Xamarin Forms:在 Android 设备的内部存储中写入文件