【Android】數(shù)據(jù)存儲(chǔ)全方案之文件存儲(chǔ)

作者:鄒峰立,微博:zrunker椒功,郵箱:zrunker@yahoo.com白嘁,微信公眾號(hào):書客創(chuàng)作坑鱼,個(gè)人平臺(tái):www.ibooker.cc

本文選自書客創(chuàng)作平臺(tái)第6篇文章絮缅。閱讀原文 鲁沥。

書客創(chuàng)作

Android中可以在設(shè)備本身的存儲(chǔ)設(shè)備或者外接設(shè)備中創(chuàng)建用戶存儲(chǔ)的保存數(shù)據(jù)的文件。這些文件在默認(rèn)狀態(tài)下是不能在不能的程序間共享盟蚣,但是可以通過Content Provider進(jìn)行數(shù)據(jù)共享黍析。

文件存儲(chǔ)不對(duì)存儲(chǔ)的內(nèi)容進(jìn)行任何的格式化處理,所有數(shù)據(jù)都是原封不動(dòng)地保存到文件當(dāng)中屎开,因而它比較適合用于存儲(chǔ)一些簡(jiǎn)單的文本數(shù)據(jù)或二進(jìn)制數(shù)據(jù)阐枣。

文件存儲(chǔ)有兩種方式,一種是存儲(chǔ)到手機(jī)內(nèi)存中(memory)奄抽,一種是存儲(chǔ)到sd卡中蔼两。該如何實(shí)現(xiàn)這兩種方式呢?

首先要理解什么是文件的操作模式逞度?

  1. MODE_PRIVATE:當(dāng)指定同樣文件名時(shí)會(huì)覆蓋原文件中的內(nèi)容额划。
  2. MODE_APPEND:當(dāng)該文件已存在時(shí)就往文件中追加內(nèi)容,不會(huì)創(chuàng)建新文件档泽。
  3. 還有另外兩種(android4.2被廢棄)俊戳,MODE_ WORLD_ READABLE和MODE_WORLD _WRITEABLE揖赴,這兩種模式表示允許其他的應(yīng)用程序?qū)ξ覀兂绦蛑械奈募M(jìn)行讀寫操作。

通過案例說明該如何進(jìn)行文件存儲(chǔ):本案例中有一個(gè)EditText當(dāng)點(diǎn)擊‘保存到內(nèi)存’按鈕將會(huì)把EditText輸入內(nèi)容保存到內(nèi)存文件testmemory.json抑胎,當(dāng)點(diǎn)擊‘讀取內(nèi)存’按鈕將會(huì)把testmemory.json中的數(shù)據(jù)讀取出來燥滑,顯示到TextView上。當(dāng)點(diǎn)擊‘保存到SD卡’按鈕將會(huì)把EditText輸入內(nèi)容保存到內(nèi)存文件testsd.json阿逃,當(dāng)點(diǎn)擊‘讀取SD卡’按鈕將會(huì)把testsd.json中的數(shù)據(jù)讀取出來铭拧,顯示到TextView上。

布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <EditText
        android:id="@+id/edittext"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:inputType="textMultiLine"
        android:padding="15dp" />

    <Button
        android:id="@+id/btn_memory"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="@string/save_memory" />

    <Button
        android:id="@+id/btn_sd"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="@string/save_sd" />

    <Button
        android:id="@+id/btn_read_memory"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="@string/read_memory" />

    <Button
        android:id="@+id/btn_read_sd"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="@string/read_sd" />

    <TextView
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/read_text"
        android:padding="10dp" />
</LinearLayout>

效果圖:


效果圖

一恃锉、存儲(chǔ)到手機(jī)內(nèi)存中

理解:既然是想將數(shù)據(jù)保存到文件當(dāng)中搀菩,那么對(duì)于文件的讀寫,必然要借助于流破托。如果要將文件存儲(chǔ)到內(nèi)存中,可以借助于Content類提供的openFileOutput和openFileInput兩個(gè)方法來操作文件的寫入寫出炼团。

/**
 * @param name 文件名
 * @param mode 文件的操作模式
 */
FileOutputStream openFileOutput(String name, int mode);

注:openFileOutput方法是用來獲取文件輸出流瘟芝,用于寫入內(nèi)容易桃。在該方法中,參數(shù)name是指文件名不可以包含路徑锌俱,因?yàn)樗械奈募际悄J(rèn)存儲(chǔ)到/data/data/<package name>/files/目錄下。

/**
 * @param name 文件名
 */
FileInputStream openFileInput(String name)造寝;

注:openFileInput方法是用來獲取文件輸入流,用來讀取內(nèi)容吭练。同樣诫龙,在該方法中鲫咽,參數(shù)name是指文件名不可以包含路徑。

實(shí)現(xiàn):

定義數(shù)據(jù)保存方法:writeMemoryData(Object obj)

/**
  * 保存數(shù)據(jù)到內(nèi)存
  *
  * @param obj 待保存數(shù)據(jù)
  * @return true/false(成功/失敗)
  */
private boolean writeMemoryData(Object obj) {
    boolean bool = false;
    FileOutputStream fos = null;
    try {
       // 構(gòu)建Properties
       Properties properties = new Properties();
       // Properties添加數(shù)據(jù)
       properties.put(mKey, obj);
       fos = this.openFileOutput("testmemory.json", Context.MODE_PRIVATE);
       // 將數(shù)據(jù)寫入文件(流)
       properties.store(fos, "測(cè)試文件");
       bool = true;
    } catch (FileNotFoundException e) {
       e.printStackTrace();
    } catch (IOException e) {
       e.printStackTrace();
    } finally {
       if (fos != null)
          try {
              fos.close();
          } catch (IOException e) {
              e.printStackTrace();
          }
    }
    return bool;
}

注:上面代碼中提到Properties锦聊,可以理解為屬性設(shè)置文件集箩绍,它繼承Hashtable<Object, Object>,而Hashtable繼承Map材蛛,所以可以把Properties當(dāng)中Map來使用,通過保存鍵值對(duì)相關(guān)信息芽淡。

定義數(shù)據(jù)讀取方法:readMemoryData(String key)

/**
 * 讀取內(nèi)存數(shù)據(jù)
 *
 * @param key 數(shù)據(jù)對(duì)應(yīng)鍵值
 * @return 待讀取的數(shù)據(jù)
 */
private Object readMemoryData(String key) {
   Object obj = null;
   FileInputStream fis = null;
   try {
       // 構(gòu)建Properties
       Properties properties = new Properties();
       fis = this.openFileInput("testmemory.json");
       // 加載文件
       properties.load(fis);
       obj = properties.get(key);
   } catch (FileNotFoundException e) {
       e.printStackTrace();
   } catch (IOException e) {
       e.printStackTrace();
   } finally {
       if (fis != null)
          try {
             fis.close();
          } catch (IOException e) {
             e.printStackTrace();
          }
   }
   return obj;
}

注:參數(shù)key是用來取Properties中保存的數(shù)據(jù)吐绵。

到這里就要開始寫邏輯實(shí)現(xiàn):

/**
 * 文件存儲(chǔ)
 * Created by 鄒峰立 on 2017/9/19 0019.
 */
public class FileActivity extends AppCompatActivity implements View.OnClickListener {
    private EditText editText;
    private TextView textView;
    private final String mKey = "mKey";

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

        initView();
    }

    // 初始化控件
    private void initView() {
        editText = findViewById(R.id.edittext);
        textView = findViewById(R.id.text);
        Button saveMemoryBtn = findViewById(R.id.btn_memory);
        saveMemoryBtn.setOnClickListener(this);
        Button readMemoryBtn = findViewById(R.id.btn_read_memory);
        readMemoryBtn.setOnClickListener(this);
    }

    // 按鈕點(diǎn)擊事件監(jiān)聽
    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btn_memory:// 保存到內(nèi)存
                String text = editText.getText().toString().trim();
                if (!TextUtils.isEmpty(text)) {
                    boolean bool = writeMemoryData(text);
                    if (bool) {
                        Toast.makeText(this, "寫入成功", Toast.LENGTH_SHORT).show();
                        editText.setText("");
                    } else
                        Toast.makeText(this, "寫入失敗", Toast.LENGTH_SHORT).show();
                }
                break;
            case R.id.btn_read_memory:// 讀取內(nèi)存
                String str = readMemoryData(mKey).toString();
                textView.setText(str);
                break;
        }
    }
}

因?yàn)樯厦嬉呀?jīng)提到writeMemoryData和readMemoryData己单,所以這里省略了writeMemoryData和readMemoryData耙饰,只是用來簡(jiǎn)單說明具體實(shí)現(xiàn)邏輯。

二廷痘、存儲(chǔ)到sd卡中

內(nèi)存存儲(chǔ)一般只用于存儲(chǔ)小數(shù)據(jù)件已,當(dāng)數(shù)據(jù)量較大的時(shí)候,可以將大數(shù)據(jù)保存到SD卡相關(guān)文件當(dāng)中兄猩。

Environment類簡(jiǎn)介:

Environment可以說是操作SD卡一個(gè)非常重要的類鉴未。

  1. Environment兩個(gè)重要常量:
  • Environment.MEDIA_MOUNTED:外部存儲(chǔ)器可讀可寫。
  • Environment.MEDIA_ MOUNTED_ READ_ONLY:外部存儲(chǔ)器只讀淹真。
  1. Environment常用方法:
  • getExternalStorageDirectory():獲取SDCard的目錄连茧,/mnt/sdcard。
  • getExternalStorageState():獲取外部存儲(chǔ)器的當(dāng)前狀態(tài)值纱。

在本案例當(dāng)中坯汤,需要借助于Environment判斷SD卡狀態(tài)(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)),以及獲取SD卡目錄(Environment.getExternalStorageDirectory())疆偿。

定義數(shù)據(jù)寫入SD卡文件方法:writeSdData(Object obj)

/**
 * 寫入SD卡文件
 *
 * @param obj 待寫入對(duì)象
 */
private boolean writeSdData(Object obj) {
    boolean bool = false;
    if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {// 判斷外部存儲(chǔ)是否可讀可寫
       RandomAccessFile raf = null;
       try {
          // 獲取SD卡路徑
          File sdDir = Environment.getExternalStorageDirectory();
          // 獲取SD卡目錄 /mnt/sdcard。
          String sdPath = sdDir.getAbsolutePath();
          // 創(chuàng)建文件
          File file = new File(sdPath, "testsd.json");
          if (!file.exists()) {
             boolean bool1 = file.createNewFile();
             if (!bool1)
                return false;
             }


//            FileOutputStream fos = null;
//            try {
//                fos = new FileOutputStream(file);
//                fos.write(obj.toString().getBytes());
//            } catch (FileNotFoundException e) {
//                e.printStackTrace();
//            } catch (IOException e) {
//                e.printStackTrace();
//            } finally {
//                try {
//                    if (fos != null)
//                        fos.close();
//                } catch (IOException e) {
//                    e.printStackTrace();
//                }
//            }


             // 指定文件創(chuàng)建RandomAccessFile對(duì)象
             raf = new RandomAccessFile(file, "rw");
             // 將文件記錄指針移動(dòng)最后
             raf.seek(file.length());
             // 寫入內(nèi)容
             raf.write(obj.toString().getBytes());
             bool = true;
       } catch (FileNotFoundException e) {
             e.printStackTrace();
       } catch (IOException e) {
             e.printStackTrace();
       } finally {
           try {
               if (raf != null)
                  raf.close();
           } catch (IOException e) {
               e.printStackTrace();
           }
       }
   }
   return bool;
}

注:這里有寫了兩種方式對(duì)文件進(jìn)行寫入,一種是通過FileOutputStream直接寫入处铛,另外一種通過RandomAccessFile對(duì)象對(duì)文件寫入。這里主要區(qū)別在于RandomAccessFile對(duì)象可以指定文件寫入位置奕塑,操作更加方便家肯。而FileOutputStream雖然提供了一個(gè)FileOutputStream(File file, boolean append)的構(gòu)造方法,當(dāng)append為true的時(shí)候换棚,會(huì)在文件尾部進(jìn)行寫入反镇,當(dāng)append為false的時(shí)候會(huì)覆蓋之前的文件,但是沒法制定寫入具體位置颇蜡。

定義讀取SD卡文件內(nèi)容方法:readSdData()

/**
 * 讀取SD卡文件內(nèi)容
 */
private String readSdData() {
    StringBuilder sb = new StringBuilder();
    if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {// 判斷外部存儲(chǔ)是否可讀可寫
       // 獲取SD卡路徑
       File sdDir = Environment.getExternalStorageDirectory();
       // 獲取SD卡目錄 /mnt/sdcard辆亏。
       String sdPath = sdDir.getAbsolutePath();
       // 創(chuàng)建文件
       File file = new File(sdPath, "testsd.json");

       InputStream is = null;
       try {
          is = new FileInputStream(file);
          int len;
          byte[] buffer = new byte[1024];
          while ((len = is.read(buffer)) != -1) {
             sb.append(new String(buffer, 0, len));
          }
       } catch (FileNotFoundException e) {
             e.printStackTrace();
       } catch (IOException e) {
             e.printStackTrace();
       } finally {
             try {
                if (is != null)
                   is.close();
             } catch (IOException e) {
                   e.printStackTrace();
             }
       }
   }
   return sb.toString();
}

到這里就可以開始寫具體邏輯實(shí)現(xiàn):

/**
 * 文件存儲(chǔ)
 * Created by 鄒峰立 on 2017/9/19 0019.
 */
public class FileActivity extends AppCompatActivity implements View.OnClickListener {
    private EditText editText;
    private TextView textView;

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

        initView();
    }

    // 初始化控件
    private void initView() {
        editText = findViewById(R.id.edittext);
        textView = findViewById(R.id.text);
        Button sdBtn = findViewById(R.id.btn_sd);
        sdBtn.setOnClickListener(this);
        Button readSdBtn = findViewById(R.id.btn_read_sd);
        readSdBtn.setOnClickListener(this);
    }

    // 按鈕點(diǎn)擊事件監(jiān)聽
    @Override
    public void onClick(View view) {
        switch (view.getId()) {
             case R.id.btn_sd:// 保存到SD卡
                String text = editText.getText().toString().trim();
                if (!TextUtils.isEmpty(text)) {
                    boolean bool = writeSdData(text);
                    if (bool) {
                        Toast.makeText(this, "寫入成功", Toast.LENGTH_SHORT).show();
                        editText.setText("");
                    } else
                        Toast.makeText(this, "寫入失敗", Toast.LENGTH_SHORT).show();
                }
                break;
             case R.id.btn_read_sd:// 讀取SD卡
                String str = readSdData();
                textView.setText(str);
                break;
        }
    }
}

因?yàn)樯厦嬉呀?jīng)提到writeSdData和readSdData扮叨,所以這里省略了writeSdData和readSdData彻磁,只是用來簡(jiǎn)單說明具體實(shí)現(xiàn)邏輯。

可能遇到問題:

問題1:沒有安裝SD卡衷蜓。當(dāng)手機(jī)沒有安裝SD卡情況下,是沒法進(jìn)行數(shù)據(jù)保存斋陪。

問題2、當(dāng)程序運(yùn)行的時(shí)候缔赠,會(huì)發(fā)現(xiàn)無論如何操作都無法保存數(shù)據(jù)友题,這是為什么呢?這是因?yàn)镾D卡文件的讀取和寫入需要權(quán)限度宦,所以需要在AndroidManifest.xml文件中添加如下權(quán)限:

<!-- 往sdcard中讀取數(shù)據(jù)的權(quán)限 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<!-- 在sdcard中寫入文件的權(quán)限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- 在sdcard中創(chuàng)建/刪除文件的權(quán)限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />

問題3戈抄、當(dāng)再次運(yùn)行程序的時(shí)候,會(huì)發(fā)現(xiàn)在Android6.0+版本中,依然無法保存數(shù)據(jù)行贪,這又是為什么呢?這是由于Android從6.0開始對(duì)使用權(quán)限做了大的改動(dòng)崭捍,其中將【對(duì)外部存儲(chǔ)設(shè)備的讀寫權(quán)限】放到了運(yùn)行時(shí)申請(qǐng)的列表里啰脚,App的開發(fā)者必須要主動(dòng)的申請(qǐng)?jiān)L問設(shè)備的權(quán)限,這樣才能使用外部存儲(chǔ)設(shè)備粒梦。當(dāng)然系統(tǒng)軟件除外荸实。那么又該如何動(dòng)態(tài)申請(qǐng)權(quán)限呢?

這里要用到兩個(gè)方法:

/**
 * @param context 上下文對(duì)象
 * @param permission 待檢測(cè)權(quán)限
 */
int checkSelfPermission(@NonNull Context context, @NonNull String permission)

該方法是用來檢測(cè)權(quán)限permission泄朴,如果檢測(cè)結(jié)果等于PackageManager.PERMISSION_GRANTED說明當(dāng)前應(yīng)用程序可使用該權(quán)限露氮。

/**
 * @param activity 活動(dòng)頁面
 * @param permissions 權(quán)限組-請(qǐng)求權(quán)限集合
 * @param requestCode 請(qǐng)求碼-一般用在請(qǐng)求結(jié)果回調(diào)方法用來進(jìn)行請(qǐng)求權(quán)限組判斷
 */
ActivityCompat.requestPermissions(final @NonNull Activity activity,
            final @NonNull String[] permissions, final @IntRange(from = 0) int requestCode)

所以對(duì)于上面SD卡操作邏輯可以修改為:

/**
 * 文件存儲(chǔ)
 * Created by 鄒峰立 on 2017/9/19 0019.
 */
public class FileActivity extends AppCompatActivity implements View.OnClickListener {
    private final int PERMISSION_OPER_EXTERNAL_STORAGE = 55;
    private String[] permissions = {
            Manifest.permission.READ_EXTERNAL_STORAGE,
            Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS,
            Manifest.permission.WRITE_EXTERNAL_STORAGE
    };
    private int sdOperType = 0;
    private EditText editText;
    private TextView textView;

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

        initView();
    }

    // 初始化控件
    private void initView() {
        editText = findViewById(R.id.edittext);
        textView = findViewById(R.id.text);
        Button sdBtn = findViewById(R.id.btn_sd);
        sdBtn.setOnClickListener(this);
        Button readSdBtn = findViewById(R.id.btn_read_sd);
        readSdBtn.setOnClickListener(this);
    }

    // 按鈕點(diǎn)擊事件監(jiān)聽
    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btn_sd:// 保存到SD卡
                applyPermission();
                sdOperType = 1;
                break;
            case R.id.btn_read_sd:// 讀取SD卡
                applyPermission();
                sdOperType = 2;
                break;
        }
    }

    // 判斷是否可以操作SD
    private boolean isOperSd() {
        return hasPermission(permissions);
    }

    // Android6.0 動(dòng)態(tài)申請(qǐng)文件讀寫權(quán)限
    private void applyPermission() {
        if (!hasPermission(permissions)) {
            requestPermission(PERMISSION_OPER_EXTERNAL_STORAGE, permissions);
        }
    }

    // 權(quán)限請(qǐng)求回調(diào)
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        switch (requestCode) {
            case PERMISSION_OPER_EXTERNAL_STORAGE:// SD卡讀寫權(quán)限成功
                switch (sdOperType) {
                    case 1:// 保存數(shù)據(jù)到SD卡
                        if (isOperSd()) {
                            String text1 = editText.getText().toString().trim();
                            if (!TextUtils.isEmpty(text1)) {
                                boolean bool = writeSdData(text1);
                                if (bool) {
                                    Toast.makeText(this, "寫入成功", Toast.LENGTH_SHORT).show();
                                    editText.setText("");
                                } else
                                    Toast.makeText(this, "寫入失敗", Toast.LENGTH_SHORT).show();
                            }
                        } else {
                            Toast.makeText(this, "你沒有操作SD卡權(quán)限", Toast.LENGTH_SHORT).show();
                        }
                        break;
                    case 2:// 讀取SD卡數(shù)據(jù)
                        if (isOperSd()) {
                            String str1 = readSdData();
                            textView.setText(str1);
                        } else {
                            Toast.makeText(this, "你沒有操作SD卡權(quán)限", Toast.LENGTH_SHORT).show();
                        }
                        break;
                }
                break;
        }
    }

    /**
     * 權(quán)限檢查方法
     */
    public boolean hasPermission(String... permissions) {
        for (String permission : permissions) {
            if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
                return false;
            }
        }
        return true;
    }

    /**
     * 權(quán)限請(qǐng)求方法
     */
    public void requestPermission(int code, String... permissions) {
        ActivityCompat.requestPermissions(this, permissions, code);
    }
}

問題4:通過上面的方法完善之后局扶,大部分的機(jī)型都可以使用,而一些特殊機(jī)型如HUAWEI Mate8(Android 6.0)依舊沒法進(jìn)行數(shù)據(jù)保存延欠,這又是為什么呢沈跨?首先可以說明的是這是一些非常特殊的情況,對(duì)于這些特殊情況狞玛,可能存在的問題已經(jīng)不是應(yīng)用層可以解決的涧窒,如果非要讓HUAWEI Mate8支持,可以通過以下方法讓HUAWEI Mate8恢復(fù)SD卡和U盤的讀取權(quán)限硬鞍。

  1. 首先要保證設(shè)備插入一張SD卡戴已。
  2. 進(jìn)入【設(shè)置->高級(jí)設(shè)置->內(nèi)存和存儲(chǔ)】然后改變【默認(rèn)存儲(chǔ)位置】為“SD卡”,之后系統(tǒng)會(huì)提示要重啟手機(jī)伐坏。
  3. 重啟完成后握联,按照2的方法再次將【默認(rèn)存儲(chǔ)位置】改回“內(nèi)部存儲(chǔ)”,再次重啟手機(jī)金闽。

GitHub地址
閱讀原文


微信公眾號(hào):書客創(chuàng)作
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末代芜,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子组橄,更是在濱河造成了極大的恐慌罚随,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,635評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件遵班,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡狭郑,警方通過查閱死者的電腦和手機(jī)翰萨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來殖告,“玉大人雳锋,你說我怎么就攤上這事$韫” “怎么了?”我有些...
    開封第一講書人閱讀 168,083評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵粤蝎,是天一觀的道長(zhǎng)嚼隘。 經(jīng)常有香客問我飞蛹,道長(zhǎng),這世上最難降的妖魔是什么灸眼? 我笑而不...
    開封第一講書人閱讀 59,640評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮霉囚,結(jié)果婚禮上匕积,老公的妹妹穿的比我還像新娘。我一直安慰自己闪唆,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評(píng)論 6 397
  • 文/花漫 我一把揭開白布票顾。 她就那樣靜靜地躺著,像睡著了一般豆同。 火紅的嫁衣襯著肌膚如雪含鳞。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,262評(píng)論 1 308
  • 那天精居,我揣著相機(jī)與錄音潜必,去河邊找鬼。 笑死佛吓,一個(gè)胖子當(dāng)著我的面吹牛垂攘,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播晒他,決...
    沈念sama閱讀 40,833評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼陨仅,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了灼伤?” 一聲冷哼從身側(cè)響起狐赡,我...
    開封第一講書人閱讀 39,736評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎鸟雏,沒想到半個(gè)月后览祖,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,280評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡惶室,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了悼泌。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片夹界。...
    茶點(diǎn)故事閱讀 40,503評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖鸠踪,靈堂內(nèi)的尸體忽然破棺而出复斥,到底是詐尸還是另有隱情,我是刑警寧澤目锭,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布痢虹,位于F島的核電站,受9級(jí)特大地震影響奖唯,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜坯墨,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,870評(píng)論 3 333
  • 文/蒙蒙 一瓢阴、第九天 我趴在偏房一處隱蔽的房頂上張望健无。 院中可真熱鬧,春花似錦叠穆、人聲如沸臼膏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至仔掸,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間卖氨,已是汗流浹背负懦。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留系吭,地道東北人残腌。 一個(gè)月前我還...
    沈念sama閱讀 48,909評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像蟆盹,于是被迫代替她去往敵國(guó)和親闺金。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評(píng)論 2 359