如何正确使用存储访问框架 (SAF) 和 URI 编辑共享存储中的文本文件?

问题描述

(编辑)@blackapps 的回答:将“w”更改为“wt”。它有效!

//-------------------------------------------//

我按照tutorial写了一个简单的文本编辑器,但是结果很奇怪。

我要实现的功能一个记录我今天想吃什么的文本文件

我第一次将“菠萝”写入文本文件。文本文件内容是“菠萝”。但是,我第二次将“apple”写入文本文件。文本文件内容是“applepple”。看起来只是替换了之前内容的前五个字符。

我的问题是:如何让内容记录为“apple”而不是“applepple”?我想使用 SAF 和 URI。我不想使用直接路径访问文件

我在下载文件夹中创建并编辑了文本文件。 我在 Android 11,targetSdkVersion 30 上运行该应用程序。 代码如下:

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //--call this only once
//        createFile(MediaStore.Downloads.INTERNAL_CONTENT_URI);
    }

    private String todayFood = "pineapple";//change here to apple
    private static final int CREATE_FILE = 1;
    private static final int OPEN_FILE = 2;

    private void createFile(Uri pickerInitialUri) {
        Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        intent.setType("text/plain");
        intent.putExtra(Intent.EXTRA_TITLE,"foodFile");
        intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI,pickerInitialUri);

        startActivityForResult(intent,CREATE_FILE);
    }

    public void onopenFileBtn(View v){//button click event
        openFile(MediaStore.Downloads.INTERNAL_CONTENT_URI);
    }

    private void openFile(Uri pickerInitialUri) {
        Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        intent.setType("text/plain");
        intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI,OPEN_FILE);
    }

    @Override
    public void onActivityResult(int requestCode,int resultCode,Intent resultData) {
        super.onActivityResult(requestCode,resultCode,resultData);
        if (requestCode == OPEN_FILE && resultCode == Activity.RESULT_OK) {
            Uri uri = null;
            if (resultData != null) {
                uri = resultData.getData();
                outputToFile(uri);
            }
        } else if (requestCode == CREATE_FILE && resultCode == Activity.RESULT_OK) {
            System.out.println("create successful");
        }
    }

    public void outputToFile(Uri fileUri) {
        try {
            ParcelFileDescriptor pfd = getContentResolver().openFileDescriptor(fileUri,"w");
            FileOutputStream fileOutputStream = new FileOutputStream(pfd.getFileDescriptor());
            fileOutputStream.write(todayFood.getBytes());
            fileOutputStream.close();
            pfd.close();
        } catch (FileNotFoundException e) {
            e.printstacktrace();
        } catch (IOException e) {
            e.printstacktrace();
        }
    }
}

以下是权限:

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

android:requestLegacyExternalStorage="true"

如果您能提供任何帮助,我将不胜感激。

//-------------------------------------------//

//--我尝试过的:

我尝试使用直接路径,并且它工作正常。我认为原因是它创建了一个文件来替换原始文件。但是,我只是不想使用直接路径。

public void outputToFile(Uri fileUri) {
    File dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
    File f = new File(dir.getPath(),"foodFile.txt");

    try {
        FileOutputStream outputStream = new FileOutputStream(f);
        outputStream.write(todayFood.getBytes());
        outputStream.close();
    } catch (Exception e) {
        e.printstacktrace();
    }
}

我试过用 PrintWriter 来清除内容,但它也需要先创建 File 的直接路径,然后再放入 PrintWriter。

public void outputToFile(Uri fileUri) {
    File dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
    try {
        File f = new File(dir.getPath(),"foodFile.txt");
        PrintWriter writer = new PrintWriter(f);
        writer.print("");
        writer.close();
    } catch (Exception e) {
        e.printstacktrace();
    }
}

我试过用OutputStream来创建PrintWriter,但是没有用。

public void outputToFile(Uri fileUri) {
    try {
        ParcelFileDescriptor pfd = getContentResolver().openFileDescriptor(fileUri,"w");
        OutputStream outputStream = new FileOutputStream(pfd.getFileDescriptor());
        PrintWriter writer = new PrintWriter(outputStream);
        writer.print("");
        writer.write("apple");
        writer.close();
        pfd.close();
    } catch (FileNotFoundException e) {
        e.printstacktrace();
    } catch (IOException e) {
        e.printstacktrace();
    }
}

我也尝试在另一个文件夹(如 Document 文件夹)中创建和编辑文本文件,但它也不起作用。

我已尝试请求运行时权限,但还有一个我现在无法解决的问题。

解决方法

试试下面的代码。

public void outputToFile(String text) {
File dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
try {
   File logFile = new File(dir.getPath(),"abc.txt");
   BufferedWriter buf = new BufferedWriter(new FileWriter(logFile,true)); 
   buf.append(text);
   buf.newLine();
   buf.close();
} catch (Exception e) {
    e.printStackTrace();
}
}