Android Studio Java导出CSV报open failed: EROFS只读文件系统求助
问题原因&修复方案
核心报错原因
你触发EROFS (Read-only file system)错误的直接原因是未指定合法可写的文件保存路径:
- 直接向
FileWriter传入纯文件名"monitor.csv"时,安卓会默认尝试写入系统根目录,该目录对普通应用是永久只读的,哪怕申请了存储权限也无法写入。
你代码里的其他隐性问题
- 存储权限配置不正确:安卓6.0(API 23)以上仅在清单文件声明存储权限无效,需要在代码中主动触发动态权限申请;安卓13及以上版本
READ_EXTERNAL_STORAGE/WRITE_EXTERNAL_STORAGE权限已废弃,公共目录读写需要适配分区存储规则。 - 输入内容获取时机错误:你在
onCreate生命周期就调用EditText#getText()获取输入内容,此时页面刚加载完成,用户还未填写任何信息,后续提交时拿到的永远是空字符串。 - 全局静态变量存储输入内容存在内存泄漏风险,也不符合安卓组件开发规范。
修复后的完整代码
第一步:先移除原有全局静态String变量,将输入框声明为类成员
第二步:修改文件保存路径为应用专属外部存储目录(该目录不需要申请任何存储权限,应用可直接读写)
第三步:将输入内容获取逻辑移到提交按钮点击事件中
package com.example.myapplication; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; import com.opencsv.CSVWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity implements View.OnClickListener { // 声明输入框为类成员变量 private EditText editRank, editName, editUnit, editAppt, editMobile, editLoanFrom, editLoanTo, editBlock, editFloor; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // onCreate中只做绑定控件,不读取内容 editRank = findViewById(R.id.editRank); editName = findViewById(R.id.editName); editUnit = findViewById(R.id.editUnit); editAppt = findViewById(R.id.editAppt); editMobile = findViewById(R.id.editMobile); editLoanFrom = findViewById(R.id.editLoanFrom); editLoanTo = findViewById(R.id.editLoanTo); editBlock = findViewById(R.id.editBlock); editFloor = findViewById(R.id.editFloor); Button btnSubmit = findViewById(R.id.btnSubmit); btnSubmit.setOnClickListener(this); } @Override public void onClick(View view) { // 点击提交时再读取用户输入的内容 String etRank = editRank.getText().toString().trim(); String etName = editName.getText().toString().trim(); String etUnit = editUnit.getText().toString().trim(); String etAppt = editAppt.getText().toString().trim(); String etMobile = editMobile.getText().toString().trim(); String etLoanFrom = editLoanFrom.getText().toString().trim(); String etLoanTo = editLoanTo.getText().toString().trim(); String etBlock = editBlock.getText().toString().trim(); String etFloor = editFloor.getText().toString().trim(); List<String[]> csvData = createCsvDataSpecial(etRank, etName, etUnit, etAppt, etMobile, etLoanFrom, etLoanTo, etBlock, etFloor); // 获取应用专属外部存储路径,不需要权限即可写入 File saveDir = getExternalFilesDir(null); File csvFile = new File(saveDir, "monitor.csv"); try (CSVWriter writer = new CSVWriter(new FileWriter(csvFile))) { writer.writeAll(csvData); } catch (IOException e) { e.printStackTrace(); } } private List<String[]> createCsvDataSpecial(String etRank, String etName, String etUnit, String etAppt, String etMobile, String etLoanFrom, String etLoanTo, String etBlock, String etFloor) { String[] heading = {"Rank", "Name", "Unit", "Appointment", "Mobile_No", "Loan_From", "Loan_To", "Block", "Floor"}; String[] data = {etRank, etName, etUnit, etAppt, etMobile, etLoanFrom, etLoanTo, etBlock, etFloor}; List<String[]> list = new ArrayList<>(); list.add(heading); list.add(data); return list; } }
拓展说明
- 生成的csv文件默认保存在
内部存储/Android/data/你的应用包名/files/路径下,可通过Android Studio的设备文件浏览器查看。 - 如果你需要让生成的csv文件在系统的文件管理器中对用户可见,可以适配安卓分区存储规则,使用MediaStore写入公共下载目录,或者调用系统存储访问框架(SAF)让用户自主选择文件保存位置。
内容的提问来源于stack exchange,提问作者Zefrom
相关产品推荐
相关产品推荐

