Đọc / ghi chuỗi từ / đến một tệp trong Android


213

Tôi muốn lưu một tệp vào bộ nhớ trong bằng cách nhập văn bản từ EditText. Sau đó, tôi muốn cùng một tệp trả về văn bản đã nhập ở dạng Chuỗi và lưu nó vào một Chuỗi khác sẽ được sử dụng sau này.

Đây là mã:

package com.omm.easybalancerecharge;


import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.telephony.TelephonyManager;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final EditText num = (EditText) findViewById(R.id.sNum);
        Button ch = (Button) findViewById(R.id.rButton);
        TelephonyManager operator = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
        String opname = operator.getNetworkOperatorName();
        TextView status = (TextView) findViewById(R.id.setStatus);
        final EditText ID = (EditText) findViewById(R.id.IQID);
        Button save = (Button) findViewById(R.id.sButton);

        final String myID = ""; //When Reading The File Back, I Need To Store It In This String For Later Use

        save.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub

                //Get Text From EditText "ID" And Save It To Internal Memory
            }
        });
        if (opname.contentEquals("zain SA")) {
            status.setText("Your Network Is: " + opname);
        } else {
            status.setText("No Network");
        }
        ch.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub

                //Read From The Saved File Here And Append It To String "myID"


                String hash = Uri.encode("#");
                Intent intent = new Intent(Intent.ACTION_CALL);
                intent.setData(Uri.parse("tel:*141*" + /*Use The String With Data Retrieved Here*/ num.getText()
                        + hash));
                startActivity(intent);
            }
        });
    }

Tôi đã bao gồm các ý kiến ​​để giúp bạn phân tích thêm các điểm của tôi về nơi tôi muốn các hoạt động được thực hiện / các biến được sử dụng.


2
câu hỏi là "làm thế nào để đọc / ghi vào / từ tập tin?"
Dmitri Gudkov

Bạn đã cân nhắc sử dụng tùy chọn của ứng dụng để lưu trữ chuỗi của mình chưa?
sd.us

4
BTW, hãy chắc chắn rằng bạn đã cấp quyền cho tệp mainfest, để hoạt động với bộ lưu trữ ...
Dmitri Gudkov

Đây là một nửa ứng dụng hoàn chỉnh của tôi với nhiều thay đổi để thực hiện. Ý tưởng của tôi là người dùng chỉ nhập ID một lần trong lần chạy đầu tiên của ứng dụng. Sau đó, ứng dụng sẽ tham chiếu ID được lưu trữ đó nhiều lần khi người dùng chạy ứng dụng. Quyền được thêm vào bảng kê khai.
Thiếu tá Aly

Câu trả lời:


334

Hy vọng điều này có thể hữu ích cho bạn.

Viết tập tin:

private void writeToFile(String data,Context context) {
    try {
        OutputStreamWriter outputStreamWriter = new OutputStreamWriter(context.openFileOutput("config.txt", Context.MODE_PRIVATE));
        outputStreamWriter.write(data);
        outputStreamWriter.close();
    }
    catch (IOException e) {
        Log.e("Exception", "File write failed: " + e.toString());
    } 
}

Đọc tài liệu:

private String readFromFile(Context context) {

    String ret = "";

    try {
        InputStream inputStream = context.openFileInput("config.txt");

        if ( inputStream != null ) {
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            String receiveString = "";
            StringBuilder stringBuilder = new StringBuilder();

            while ( (receiveString = bufferedReader.readLine()) != null ) {
                stringBuilder.append("\n").append(receiveString);
            }

            inputStream.close();
            ret = stringBuilder.toString();
        }
    }
    catch (FileNotFoundException e) {
        Log.e("login activity", "File not found: " + e.toString());
    } catch (IOException e) {
        Log.e("login activity", "Can not read file: " + e.toString());
    }

    return ret;
}

43
Nếu lớp không được mở rộng từ Activity, việc sử dụng phương thức "openFileInput ()" sẽ như thế này: context.openFileInput ()
Behzad

11
Lưu ý: Mã ở trên hoạt động tốt, nhưng Chuỗi kết quả sẽ không chứa bất kỳ ngắt dòng nào từ tệp. Để thêm ngắt dòng một lần nữa, hãy thay đổi dòng "stringBuilder.append (receiveString);" thành "stringBuilder.append (receiveString) .append (" \ n ");". Nếu bạn mong đợi các ký tự ngắt dòng khác (ví dụ: tệp văn bản Windows sẽ có \ r, v.v.), trong chuỗi cuối cùng của bạn, bạn sẽ phải điều chỉnh thêm một chút nữa.
cây xanh ở mọi nơi

26
nơi tập tin cấu hình này lưu trong thiết bị thực? tôi không thể tìm thấy nó để kiểm tra :(
Mahdi

4
Tôi nghĩ rằng, việc đóng các luồng nên nằm trong finalkhối như trong câu trả lời của @SharkAlley
Yurii K

4
@Kenji tệp được lưu trong thư mục tệp của ứng dụng (ví dụ: /data/data/<package_name>/files/config.txt). Quá trình của ứng dụng có thể truy cập vào nó nhưng không phải tất cả các quy trình trong HĐH. Việc triển khai có thể khác nhau tùy thuộc vào phiên bản Android mà thiết bị của bạn chạy. Bạn có thể kiểm tra việc triển khai của AOSP trực tuyến. Ví dụ: đối với Android 8.1_r5: android.googlesource.com/pl
platform / frameworks / base /

187

Đối với những người tìm kiếm một chiến lược chung để đọc và viết một chuỗi vào tệp:

Đầu tiên, lấy một đối tượng tập tin

Bạn sẽ cần đường dẫn lưu trữ. Đối với bộ nhớ trong, sử dụng:

File path = context.getFilesDir();

Đối với bộ nhớ ngoài (thẻ SD), sử dụng:

File path = context.getExternalFilesDir(null);

Sau đó tạo đối tượng tệp của bạn:

File file = new File(path, "my-file-name.txt");

Viết một chuỗi vào tập tin

FileOutputStream stream = new FileOutputStream(file);
try {
    stream.write("text-to-write".getBytes());
} finally {
    stream.close();
}

Hoặc với Google ổi

Chuỗi nội dung = Files.toString (tệp, StandardCharsets.UTF_8);

Đọc tệp thành một chuỗi

int length = (int) file.length();

byte[] bytes = new byte[length];

FileInputStream in = new FileInputStream(file);
try {
    in.read(bytes);
} finally {
    in.close();
}

String contents = new String(bytes);   

Hoặc nếu bạn đang sử dụng Google Guava

String contents = Files.toString(file,"UTF-8");

Để hoàn thiện tôi sẽ đề cập đến

String contents = new Scanner(file).useDelimiter("\\A").next();

không yêu cầu thư viện, nhưng điểm chuẩn chậm hơn 50% - 400% so với các tùy chọn khác (trong các thử nghiệm khác nhau trên Nexus 5 của tôi).

Ghi chú

Đối với mỗi chiến lược này, bạn sẽ được yêu cầu bắt IOException.

Mã hóa ký tự mặc định trên Android là UTF-8.

Nếu bạn đang sử dụng bộ nhớ ngoài, bạn sẽ cần thêm vào bảng kê khai của mình:

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

hoặc là

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

Quyền viết có nghĩa là quyền đọc, vì vậy bạn không cần cả hai.


Ví dụ, tôi muốn người dùng xem tất cả các bài đăng của anh ấy, và khi anh ấy đi đến một màn hình khác và quay lại, tôi có cần vẽ lại không hay vì nó được lưu vào bộ nhớ cache, nó chỉ cần kéo nó ra khỏi bộ đệm và chỉ hiển thị nó, nếu nó chỉ cần kéo nó ra, làm cách nào để thêm một điều kiện nếu nói không truy vấn máy chủ của tôi
Lion789

4
Đừng làm như thế new File(path + "/my-file-name.txt");. Điều này bất chấp nhiều ý nghĩa của File. Sử dụng new File(path, "my-file-name.txt");thay thế.
JimmyB

@HannoBinder Android luôn chạy trên Linux, vì vậy dấu phân cách được đảm bảo là "/". Lợi ích của việc sử dụng Tệp mới (đường dẫn, "my-file-name.txt") trong ngữ cảnh này là gì? (Tôi rất vui khi cập nhật câu trả lời nếu có lý do.)
SharkAlley

1
Filelà có lý do. Trong trường hợp của bạn, bạn cũng có thể bỏ qua Filevà chỉ cần làm new FileInputStream(path + "/my-file-name.txt");, điều mà tôi không khuyên dùng. (Điều gì xảy ra nếu pathcó dấu vết /chẳng hạn?)
JimmyB

Chỉnh sửa theo đề nghị của bạn. Cảm ơn :)
SharkAlley

37
public static void writeStringAsFile(final String fileContents, String fileName) {
    Context context = App.instance.getApplicationContext();
    try {
        FileWriter out = new FileWriter(new File(context.getFilesDir(), fileName));
        out.write(fileContents);
        out.close();
    } catch (IOException e) {
        Logger.logError(TAG, e);
    }
}

public static String readFileAsString(String fileName) {
    Context context = App.instance.getApplicationContext();
    StringBuilder stringBuilder = new StringBuilder();
    String line;
    BufferedReader in = null;

    try {
        in = new BufferedReader(new FileReader(new File(context.getFilesDir(), fileName)));
        while ((line = in.readLine()) != null) stringBuilder.append(line);

    } catch (FileNotFoundException e) {
        Logger.logError(TAG, e);
    } catch (IOException e) {
        Logger.logError(TAG, e);
    } 

    return stringBuilder.toString();
}

7
Ứng dụng!? nó nghĩa là gì!
alap

@alap Có phải cái gì đó @Eugene đang sử dụng để truy xuất bối cảnh ứng dụng một cách tĩnh. Anh ấy cần nó cho context.getFilesDir(). Bạn chỉ có thể thay thế các lần xuất hiện new File(context.getFilesDir(), fileName)bằng một Fileđối tượng hoặc Stringđược truyền vào hàm thay vì fileName.
lorenzo-s

7

Chỉ cần sửa đổi một chút về đọc chuỗi từ phương thức tệp để có hiệu suất cao hơn

private String readFromFile(Context context, String fileName) {
    if (context == null) {
        return null;
    }

    String ret = "";

    try {
        InputStream inputStream = context.openFileInput(fileName);

        if ( inputStream != null ) {
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream);               

            int size = inputStream.available();
            char[] buffer = new char[size];

            inputStreamReader.read(buffer);

            inputStream.close();
            ret = new String(buffer);
        }
    }catch (Exception e) {
        e.printStackTrace();
    }

    return ret;
}

6

kiểm tra mã dưới đây.

Đọc từ một tập tin trong hệ thống tập tin.

FileInputStream fis = null;
    try {

        fis = context.openFileInput(fileName);
        InputStreamReader isr = new InputStreamReader(fis);
        // READ STRING OF UNKNOWN LENGTH
        StringBuilder sb = new StringBuilder();
        char[] inputBuffer = new char[2048];
        int l;
        // FILL BUFFER WITH DATA
        while ((l = isr.read(inputBuffer)) != -1) {
            sb.append(inputBuffer, 0, l);
        }
        // CONVERT BYTES TO STRING
        String readString = sb.toString();
        fis.close();

    catch (Exception e) {

    } finally {
        if (fis != null) {
            fis = null;
        }
    }

bên dưới mã là để ghi tập tin vào hệ thống tập tin nội bộ.

FileOutputStream fos = null;
    try {

        fos = context.openFileOutput(fileName, Context.MODE_PRIVATE);
        fos.write(stringdatatobestoredinfile.getBytes());
        fos.flush();
        fos.close();

    } catch (Exception e) {

    } finally {
        if (fos != null) {
            fos = null;
        }
    }

Tôi nghĩ rằng điều này sẽ giúp bạn.


3

Tôi là một người mới bắt đầu và đấu tranh để có được điều này để làm việc ngày hôm nay.

Dưới đây là lớp học mà tôi đã kết thúc. Nó hoạt động nhưng tôi đã tự hỏi làm thế nào không hoàn hảo giải pháp của tôi. Dù sao, tôi đã hy vọng một số bạn có kinh nghiệm hơn trong dân gian có thể sẵn sàng xem lớp IO của tôi và cho tôi một số lời khuyên. Chúc mừng!

public class HighScore {
    File data = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator);
    File file = new File(data, "highscore.txt");
    private int highScore = 0;

    public int readHighScore() {
        try {
            BufferedReader br = new BufferedReader(new FileReader(file));
            try {
                highScore = Integer.parseInt(br.readLine());
                br.close();
            } catch (NumberFormatException | IOException e) {
                e.printStackTrace();
            }
        } catch (FileNotFoundException e) {
            try {
                file.createNewFile();
            } catch (IOException ioe) {
                ioe.printStackTrace();
            }
            e.printStackTrace();
        }
        return highScore;
    }

    public void writeHighScore(int highestScore) {
        try {
            BufferedWriter bw = new BufferedWriter(new FileWriter(file));
            bw.write(String.valueOf(highestScore));
            bw.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Bạn không cần phải tạo một tệp mới nếu không có tệp nào ở đó.
rml

1

điều đầu tiên chúng ta cần là các quyền trong AndroidManifest.xml

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

Vì vậy, trong một lớp Kotlin asyncTask, chúng tôi xử lý việc tạo tệp

    import android.os.AsyncTask
    import android.os.Environment
    import android.util.Log
    import java.io.*
    class WriteFile: AsyncTask<String, Int, String>() {
        private val mFolder = "/MainFolder"
        lateinit var folder: File
        internal var writeThis = "string to cacheApp.txt"
        internal var cacheApptxt = "cacheApp.txt"
        override fun doInBackground(vararg writethis: String): String? {
            val received = writethis[0]
            if(received.isNotEmpty()){
                writeThis = received
            }
            folder = File(Environment.getExternalStorageDirectory(),"$mFolder/")
            if(!folder.exists()){
                folder.mkdir()
                val readME = File(folder, cacheApptxt)
                val file = File(readME.path)
                val out: BufferedWriter
                try {
                    out = BufferedWriter(FileWriter(file, true), 1024)
                    out.write(writeThis)
                    out.newLine()
                    out.close()
                    Log.d("Output_Success", folder.path)
                } catch (e: Exception) {
                    Log.d("Output_Exception", "$e")
                }
            }
            return folder.path

    }

        override fun onPostExecute(result: String) {
            super.onPostExecute(result)

            if(result.isNotEmpty()){
                //implement an interface or do something
                Log.d("onPostExecuteSuccess", result)
            }else{
                Log.d("onPostExecuteFailure", result)
            }
        }

    }

Tất nhiên, nếu bạn đang sử dụng Android trên Api 23, bạn phải xử lý yêu cầu cho phép ghi vào bộ nhớ thiết bị. Một cái gì đó như thế này

    import android.Manifest
    import android.content.Context
    import android.content.pm.PackageManager
    import android.os.Build
    import androidx.appcompat.app.AppCompatActivity
    import androidx.core.app.ActivityCompat
    import androidx.core.content.ContextCompat

    class ReadandWrite {
        private val mREAD = 9
        private val mWRITE = 10
        private var readAndWrite: Boolean = false
        fun readAndwriteStorage(ctx: Context, atividade: AppCompatActivity): Boolean {
            if (Build.VERSION.SDK_INT < 23) {
                readAndWrite = true
            } else {
                val mRead = ContextCompat.checkSelfPermission(ctx, Manifest.permission.READ_EXTERNAL_STORAGE)
                val mWrite = ContextCompat.checkSelfPermission(ctx, Manifest.permission.WRITE_EXTERNAL_STORAGE)

                if (mRead != PackageManager.PERMISSION_GRANTED) {
                    ActivityCompat.requestPermissions(atividade, arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), mREAD)
                } else {
                    readAndWrite = true
                }

                if (mWrite != PackageManager.PERMISSION_GRANTED) {
                    ActivityCompat.requestPermissions(atividade, arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), mWRITE)
                } else {
                    readAndWrite = true
                }
            }
            return readAndWrite
        }
    }

sau đó trong một hoạt động, thực hiện cuộc gọi.

  var pathToFileCreated = ""
    val anRW = ReadandWrite().readAndwriteStorage(this,this)
    if(anRW){
        pathToFileCreated =  WriteFile().execute("onTaskComplete").get()
        Log.d("pathToFileCreated",pathToFileCreated)
    }

những quyền lưu trữ nội bộ không hợp lệ.
Thư ký

0

Kotlin

class FileReadWriteService {

    private var context:Context? = ContextHolder.instance.appContext

    fun writeFileOnInternalStorage(fileKey: String, sBody: String) {
        val file = File(context?.filesDir, "files")
        try {
            if (!file.exists()) {
                file.mkdir()
            }
            val fileToWrite = File(file, fileKey)
            val writer = FileWriter(fileToWrite)
            writer.append(sBody)
            writer.flush()
            writer.close()
        } catch (e: Exception) {
            Logger.e(classTag, e)
        }
    }

    fun readFileOnInternalStorage(fileKey: String): String {
        val file = File(context?.filesDir, "files")
        var ret = ""
        try {
            if (!file.exists()) {
                return ret
            }
            val fileToRead = File(file, fileKey)
            val reader = FileReader(fileToRead)
            ret = reader.readText()
            reader.close()
        } catch (e: Exception) {
            Logger.e(classTag, e)
        }
        return ret
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.