Android數(shù)據(jù)存儲(chǔ)方式

一荣病、使用SharedPreferences存儲(chǔ)數(shù)據(jù)

默認(rèn)存儲(chǔ)路徑:/data/data/<PackageName>/shared_prefs

SharedPreferences是一個(gè)較輕量級(jí)的存儲(chǔ)數(shù)據(jù)的方法码撰,適用范圍:保存少量的數(shù)據(jù),且這些數(shù)據(jù)的格式非常簡單:字符串型个盆、基本類型的值脖岛。

核心原理:保存基于XML文件存儲(chǔ)的key-value鍵值對(duì)數(shù)據(jù),通常用來存儲(chǔ)一些簡單的配置信息颊亮。通過DDMS的File Explorer面板柴梆,展開文件瀏覽樹,很明顯SharedPreferences數(shù)據(jù)總是存儲(chǔ)在/data/data/<package name>/shared_prefs目錄下。SharedPreferences對(duì)象本身只能獲取數(shù)據(jù)而不支持存儲(chǔ)和修改,存儲(chǔ)修改是通過SharedPreferences.edit()獲取的內(nèi)部接口Editor對(duì)象實(shí)現(xiàn)终惑。 SharedPreferences本身是一 個(gè)接口绍在,程序無法直接創(chuàng)建SharedPreferences實(shí)例,只能通過Context提供的getSharedPreferences(String name, int mode)方法來獲取SharedPreferences實(shí)例,
該方法中name表示要操作的xml文件名,第二個(gè)參數(shù)為設(shè)置讀寫模式偿渡,有以下三種選擇:

  • Context.MODE_PRIVATE: 指定該SharedPreferences數(shù)據(jù)只能被本應(yīng)用程序讀臼寄、寫。
  • Context.MODE_WORLD_READABLE: 指定該SharedPreferences數(shù)據(jù)能被其他應(yīng)用程序讀溜宽,但不能寫吉拳。
  • Context.MODE_WORLD_WRITEABLE: 指定該SharedPreferences數(shù)據(jù)能被其他應(yīng)用程序讀,寫适揉。

而編輯接口Editor有如下主要重要方法:

  • SharedPreferences.Editor clear():清空SharedPreferences里所有數(shù)據(jù)

  • ** SharedPreferences.Editor putXxx(String key , xxx value):** 向SharedPreferences存入指定key對(duì)應(yīng)的數(shù)據(jù)留攒,其中xxx 可以是boolean,float,int等各種基本類型據(jù)

  • ** SharedPreferences.Editor remove()**: 刪除SharedPreferences中指定key對(duì)應(yīng)的數(shù)據(jù)項(xiàng)

  • ** boolean commit()**: 當(dāng)Editor編輯完成后,使用該方法提交修改

讀寫其他應(yīng)用的SharedPreferences: 步驟如下

  1. 在創(chuàng)建SharedPreferences時(shí)嫉嘀,指定MODE_WORLD_READABLE模式炼邀,表明該SharedPreferences數(shù)據(jù)可以被其他程序讀取

  2. 創(chuàng)建其他應(yīng)用程序?qū)?yīng)的Context:

    Context pvCount = createPackageContext("com.tony.app",
    Context.CONTEXT_IGNORE_SECURITY);這里的com.tony.app就是其他程序的包名

  3. 使用其他程序的Context獲取對(duì)應(yīng)的SharedPreferences

    SharedPreferences read = pvCount.getSharedPreferences("lock",
    Context.MODE_WORLD_READABLE);

  4. 如果是寫入數(shù)據(jù),使用Editor接口即可剪侮,所有其他操作均和前面一致拭宁。

SharedPreferences對(duì)象與SQLite數(shù)據(jù)庫相比,免去了創(chuàng)建數(shù)據(jù)庫票彪,創(chuàng)建表红淡,寫SQL語句等諸多操作,相對(duì)而言更加方便降铸,簡潔在旱。但是SharedPreferences也有其自身缺陷,比如其職能存儲(chǔ)boolean推掸,int桶蝎,float,long和String五種簡單的數(shù)據(jù)類型谅畅,比如其無法進(jìn)行條件查詢等登渣。所以不論SharedPreferences的數(shù)據(jù)存儲(chǔ)操作是如何簡單,它也只能是存儲(chǔ)方式的一種補(bǔ)充毡泻,而無法完全替代如SQLite數(shù)據(jù)庫這樣的其他數(shù)據(jù)存儲(chǔ)方式胜茧。另外需要注意的一點(diǎn)是sharePreference在多進(jìn)程的情況下會(huì)失效。

二仇味、SQLite數(shù)據(jù)庫存儲(chǔ)數(shù)據(jù)

默認(rèn)存儲(chǔ)路徑:/data/data/<PackageName>/databases

SQLite是輕量級(jí)嵌入式數(shù)據(jù)庫引擎呻顽,它支持 SQL 語言,并且只利用很少的內(nèi)存就有很好的性能〉つ現(xiàn)在的主流移動(dòng)設(shè)備像Android廊遍、iPhone等都使用SQLite作為復(fù)雜數(shù)據(jù)的存儲(chǔ)引擎,在我們?yōu)橐苿?dòng)設(shè)備開發(fā)應(yīng)用程序時(shí)贩挣,也許就要使用到SQLite來存儲(chǔ)我們大量的數(shù)據(jù)喉前。

SQLiteDatabase類為我們提供了很多種方法没酣,上面的代碼中基本上囊括了大部分的數(shù)據(jù)庫操作;對(duì)于添加卵迂、更新和刪除來說裕便,我們都可以使用

1 db.executeSQL(String sql);
2 db.executeSQL(String sql, Object[] bindArgs);//sql語句中使用占位符,然后第二個(gè)參數(shù)是實(shí)際的參數(shù)集

 @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
          
        //打開或創(chuàng)建test.db數(shù)據(jù)庫  
        SQLiteDatabase db = openOrCreateDatabase("test.db", Context.MODE_PRIVATE, null);  
        db.execSQL("DROP TABLE IF EXISTS person");  
        //創(chuàng)建person表  
        db.execSQL("CREATE TABLE person (_id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR, age SMALLINT)");  
        Person person = new Person();  
        person.name = "john";  
        person.age = 30;  
        //插入數(shù)據(jù)  
        db.execSQL("INSERT INTO person VALUES (NULL, ?, ?)", new Object[]{person.name, person.age});  
          
        person.name = "david";  
        person.age = 33;  
        //ContentValues以鍵值對(duì)的形式存放數(shù)據(jù)  
        ContentValues cv = new ContentValues();  
        cv.put("name", person.name);  
        cv.put("age", person.age);  
        //插入ContentValues中的數(shù)據(jù)  
        db.insert("person", null, cv);  
          
        cv = new ContentValues();  
        cv.put("age", 35);  
        //更新數(shù)據(jù)  
        db.update("person", cv, "name = ?", new String[]{"john"});  
          
        Cursor c = db.rawQuery("SELECT * FROM person WHERE age >= ?", new String[]{"33"});  
        while (c.moveToNext()) {  
            int _id = c.getInt(c.getColumnIndex("_id"));  
            String name = c.getString(c.getColumnIndex("name"));  
            int age = c.getInt(c.getColumnIndex("age"));  
            Log.i("db", "_id=>" + _id + ", name=>" + name + ", age=>" + age);  
        }  
        c.close();  
          
        //刪除數(shù)據(jù)  
        db.delete("person", "age < ?", new String[]{"35"});  
          
        //關(guān)閉當(dāng)前數(shù)據(jù)庫  
        db.close();  
          
        //刪除test.db數(shù)據(jù)庫  
//      deleteDatabase("test.db");  
    }  

在執(zhí)行完上面的代碼后狭握,系統(tǒng)就會(huì)在/data/data/[PACKAGE_NAME]/databases目錄下生成一個(gè)“test.db”的數(shù)據(jù)庫文件闪金。

上面的代碼中基本上囊括了大部分的數(shù)據(jù)庫操作疯溺;對(duì)于添加论颅、更新和刪除來說,我們都可以使用

db.executeSQL(String sql);  
db.executeSQL(String sql, Object[] bindArgs);//sql語句中使用占位符囱嫩,然后第二個(gè)參數(shù)是實(shí)際的參數(shù)集  

來執(zhí)行sql語句恃疯,
除了統(tǒng)一的形式之外,他們還有各自的操作方法:

db.insert(String table, String nullColumnHack, ContentValues values);  
db.update(String table, Contentvalues values, String whereClause, String whereArgs);  
db.delete(String table, String whereClause, String whereArgs);  

以上三個(gè)方法的第一個(gè)參數(shù)都是表示要操作的表名墨闲;insert中的第二個(gè)參數(shù)表示如果插入的數(shù)據(jù)每一列都為空的話今妄,需要指定此行中某一列的名稱,系統(tǒng)將此列設(shè)置為NULL鸳碧,不至于出現(xiàn)錯(cuò)誤盾鳞;insert中的第三個(gè)參數(shù)是ContentValues類型的變量,是鍵值對(duì)組成的Map瞻离,key代表列名腾仅,value代表該列要插入的值;update的第二個(gè)參數(shù)也很類似套利,只不過它是更新該字段key為最新的value值推励,第三個(gè)參數(shù)whereClause表示W(wǎng)HERE表達(dá)式,比如“age > ? and age < ?”等肉迫,最后的whereArgs參數(shù)是占位符的實(shí)際參數(shù)值验辞;delete方法的參數(shù)也是一樣。

下面喊衫,我們就以一個(gè)實(shí)例來講解具體的用法跌造,我們新建一個(gè)名為db的項(xiàng)目,其中DBHelper繼承了SQLiteOpenHelper族购,作為維護(hù)和管理數(shù)據(jù)庫的基類壳贪,DBManager是建立在DBHelper之上,封裝了常用的業(yè)務(wù)方法联四,Person是我們的person表對(duì)應(yīng)的JavaBean撑碴,MainActivity就是我們顯示的界面。

public class DBHelper extends SQLiteOpenHelper {  
  
    private static final String DATABASE_NAME = "test.db";  
    private static final int DATABASE_VERSION = 1;  
      
    public DBHelper(Context context) {  
        //CursorFactory設(shè)置為null,使用默認(rèn)值  
        super(context, DATABASE_NAME, null, DATABASE_VERSION);  
    }  
  
    //數(shù)據(jù)庫第一次被創(chuàng)建時(shí)onCreate會(huì)被調(diào)用  
    @Override  
    public void onCreate(SQLiteDatabase db) {  
        db.execSQL("CREATE TABLE IF NOT EXISTS person" +  
                "(_id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR, age INTEGER, info TEXT)");  
    }  
  
    //如果DATABASE_VERSION值被改為2,系統(tǒng)發(fā)現(xiàn)現(xiàn)有數(shù)據(jù)庫版本不同,即會(huì)調(diào)用onUpgrade  
    @Override  
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {  
        db.execSQL("ALTER TABLE person ADD COLUMN other STRING");  
    }  
}  

數(shù)據(jù)庫第一次創(chuàng)建時(shí)onCreate方法會(huì)被調(diào)用朝墩,我們可以執(zhí)行創(chuàng)建表的語句醉拓,當(dāng)系統(tǒng)發(fā)現(xiàn)版本變化之后伟姐,會(huì)調(diào)用onUpgrade方法,我們可以執(zhí)行修改表結(jié)構(gòu)等語句亿卤。
為了方便我們面向?qū)ο蟮氖褂脭?shù)據(jù)愤兵,我們建一個(gè)Person類,對(duì)應(yīng)person表中的字段排吴,如下:

public class Person {  
    public int _id;  
    public String name;  
    public int age;  
    public String info;  
      
    public Person() {  
    }  
      
    public Person(String name, int age, String info) {  
        this.name = name;  
        this.age = age;  
        this.info = info;  
    }  
}  

然后秆乳,我們需要一個(gè)DBManager,來封裝我們所有的業(yè)務(wù)方法钻哩,代碼如下:

public class DBManager {  
    private DBHelper helper;  
    private SQLiteDatabase db;  
      
    public DBManager(Context context) {  
        helper = new DBHelper(context);  
        //因?yàn)間etWritableDatabase內(nèi)部調(diào)用了mContext.openOrCreateDatabase(mName, 0, mFactory);  
        //所以要確保context已初始化,我們可以把實(shí)例化DBManager的步驟放在Activity的onCreate里  
        db = helper.getWritableDatabase();  
    }  
      
    /** 
     * add persons 
     * @param persons 
     */  
    public void add(List<Person> persons) {  
        db.beginTransaction();  //開始事務(wù)  
        try {  
            for (Person person : persons) {  
                db.execSQL("INSERT INTO person VALUES(null, ?, ?, ?)", new Object[]{person.name, person.age, person.info});  
            }  
            db.setTransactionSuccessful();  //設(shè)置事務(wù)成功完成  
        } finally {  
            db.endTransaction();    //結(jié)束事務(wù)  
        }  
    }  
      
    /** 
     * update person's age 
     * @param person 
     */  
    public void updateAge(Person person) {  
        ContentValues cv = new ContentValues();  
        cv.put("age", person.age);  
        db.update("person", cv, "name = ?", new String[]{person.name});  
    }  
      
    /** 
     * delete old person 
     * @param person 
     */  
    public void deleteOldPerson(Person person) {  
        db.delete("person", "age >= ?", new String[]{String.valueOf(person.age)});  
    }  
      
    /** 
     * query all persons, return list 
     * @return List<Person> 
     */  
    public List<Person> query() {  
        ArrayList<Person> persons = new ArrayList<Person>();  
        Cursor c = queryTheCursor();  
        while (c.moveToNext()) {  
            Person person = new Person();  
            person._id = c.getInt(c.getColumnIndex("_id"));  
            person.name = c.getString(c.getColumnIndex("name"));  
            person.age = c.getInt(c.getColumnIndex("age"));  
            person.info = c.getString(c.getColumnIndex("info"));  
            persons.add(person);  
        }  
        c.close();  
        return persons;  
    }  
      
    /** 
     * query all persons, return cursor 
     * @return  Cursor 
     */  
    public Cursor queryTheCursor() {  
        Cursor c = db.rawQuery("SELECT * FROM person", null);  
        return c;  
    }  
      
    /** 
     * close database 
     */  
    public void closeDB() {  
        db.close();  
    }  
}  

我們?cè)贒BManager構(gòu)造方法中實(shí)例化DBHelper并獲取一個(gè)SQLiteDatabase對(duì)象屹堰,作為整個(gè)應(yīng)用的數(shù)據(jù)庫實(shí)例;在添加多個(gè)Person信息時(shí)街氢,我們采用了事務(wù)處理扯键,確保數(shù)據(jù)完整性;最后我們提供了一個(gè)closeDB方法珊肃,釋放數(shù)據(jù)庫資源荣刑,這一個(gè)步驟在我們整個(gè)應(yīng)用關(guān)閉時(shí)執(zhí)行,這個(gè)環(huán)節(jié)容易被忘記

其他具體詳見 相關(guān)博客: http://blog.csdn.net/liuhe688/article/details/6715983/

現(xiàn)在Android在SQLite數(shù)據(jù)存儲(chǔ)方面出現(xiàn)了很多的ORM框架:ORMLite伦乔、greendao厉亏、ormndroid、androrm烈和、ActiveAndroid爱只,用于實(shí)現(xiàn)面向?qū)ο缶幊陶Z言里不同類型系統(tǒng)的數(shù)據(jù)之間的轉(zhuǎn)換。從效果上說斥杜,它其實(shí)是創(chuàng)建了一個(gè)可在編程語言里使用的“虛擬對(duì)象數(shù)據(jù)庫”虱颗。這些都極大的提高了我們的開發(fā)數(shù)據(jù)庫的效率,也值得我們深入學(xué)習(xí)蔗喂。

三忘渔、文件存儲(chǔ)數(shù)據(jù)

默認(rèn)存儲(chǔ)路徑:/data/data/<PackageName>/files

核心原理: Context提供了兩個(gè)方法來打開數(shù)據(jù)文件里的文件IO流 FileInputStream openFileInput(String name); FileOutputStream(String name , int mode),這兩個(gè)方法第一個(gè)參數(shù) 用于指定文件名,第二個(gè)參數(shù)指定打開文件的模式缰儿。具體有以下值可選:

         MODE_PRIVATE:為默認(rèn)操作模式畦粮,代表該文件是私有數(shù)據(jù),只能被應(yīng)用本身訪問乖阵,在該模式下宣赔,寫入的內(nèi)容會(huì)覆蓋原文件的內(nèi)容,如果想把新寫入的內(nèi)容追加到原文件中。可   以使用Context.MODE_APPEND

         MODE_APPEND:模式會(huì)檢查文件是否存在粘勒,存在就往文件追加內(nèi)容,否則就創(chuàng)建新文件钩蚊。

         MODE_WORLD_READABLE:表示當(dāng)前文件可以被其他應(yīng)用讀裙鼻獭;

         MODE_WORLD_WRITEABLE:表示當(dāng)前文件可以被其他應(yīng)用寫入砰逻。

除此之外鸣驱,Context還提供了如下幾個(gè)重要的方法:

         getDir(String name , int mode):在應(yīng)用程序的數(shù)據(jù)文件夾下獲取或者創(chuàng)建name對(duì)應(yīng)的子目錄

         File getFilesDir():獲取該應(yīng)用程序的數(shù)據(jù)文件夾得絕對(duì)路徑

         String[] fileList():返回該應(yīng)用數(shù)據(jù)文件夾的全部文件    

寫入文件:

    public void save(){
      String data = "save something here";
      FileOutputStream out = null;
      ButteredWriter writer = null;
      try{
            out = openFileOutput("data",Context.MODE_PRIVATE);
            writer = new ButteredWriter(new OutputSreamWriter(out));
            writer.write(data);
      }catch(IOException e){
            e.printStackTrace();
      }finally{
            try{
                  if(writer!=null){
                        writer.close();
                  }
            }catch(IOException e){
                  e.printStackTrace();
       }
}

讀取文件數(shù)據(jù):

public String load(){
      FileInputStream in = null;
      ButteredReader reader = null;
      StringBuilder builder = new StringBuilder();
      try{
            in = openFileInput("data");
            reader = new ButteredReader(new InputStreamReader(in));
            String line= "";
            while((line = reader.readline()) != null){
                   builder.append();
            }
      }catch(IOException e){
            e.printStackTrace();
      }finally{
            if(reader != null){
                    try{
                          reader.close();
                    }catch(IOException e){
                          e.printStackTrace();
                    }
             }
      }
}

讀寫sdcard上的文件

其中讀寫步驟按如下進(jìn)行:

1、調(diào)用Environment的getExternalStorageState()方法判斷手機(jī)上是否插了sd卡,且應(yīng)用程序具有讀寫SD卡的權(quán)限蝠咆,如下代碼將返回true

Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)

2踊东、調(diào)用Environment.getExternalStorageDirectory()方法來獲取外部存儲(chǔ)器,也就是SD卡的目錄,或者使用"/mnt/sdcard/"目錄

3刚操、使用IO流操作SD卡上的文件

注意點(diǎn):手機(jī)應(yīng)該已插入SD卡闸翅,對(duì)于模擬器而言,可通過mksdcard命令來創(chuàng)建虛擬存儲(chǔ)卡

必須在AndroidManifest.xml上配置讀寫SD卡的權(quán)限

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

四赡茸、ContentProvider存儲(chǔ)數(shù)據(jù)

ContentProvider主要用于不同的程序之間實(shí)現(xiàn)數(shù)據(jù)共享的功能缎脾。詳見Android四大組件介紹的內(nèi)容

五、網(wǎng)絡(luò)存儲(chǔ)

這個(gè)很好理解占卧,就是將數(shù)據(jù)上傳到服務(wù)器,在需要的時(shí)候再將它通過網(wǎng)絡(luò)讀取下來即可联喘。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末华蜒,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子豁遭,更是在濱河造成了極大的恐慌叭喜,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,839評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蓖谢,死亡現(xiàn)場(chǎng)離奇詭異捂蕴,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)闪幽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門啥辨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人盯腌,你說我怎么就攤上這事溉知。” “怎么了腕够?”我有些...
    開封第一講書人閱讀 153,116評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵级乍,是天一觀的道長。 經(jīng)常有香客問我帚湘,道長玫荣,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,371評(píng)論 1 279
  • 正文 為了忘掉前任大诸,我火速辦了婚禮捅厂,結(jié)果婚禮上材诽,老公的妹妹穿的比我還像新娘。我一直安慰自己恒傻,他們只是感情好脸侥,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評(píng)論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著盈厘,像睡著了一般睁枕。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上沸手,一...
    開封第一講書人閱讀 49,111評(píng)論 1 285
  • 那天外遇,我揣著相機(jī)與錄音,去河邊找鬼契吉。 笑死跳仿,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的捐晶。 我是一名探鬼主播菲语,決...
    沈念sama閱讀 38,416評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼惑灵!你這毒婦竟也來了山上?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,053評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤英支,失蹤者是張志新(化名)和其女友劉穎佩憾,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體干花,經(jīng)...
    沈念sama閱讀 43,558評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡妄帘,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了池凄。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片抡驼。...
    茶點(diǎn)故事閱讀 38,117評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖修赞,靈堂內(nèi)的尸體忽然破棺而出婶恼,到底是詐尸還是另有隱情,我是刑警寧澤柏副,帶...
    沈念sama閱讀 33,756評(píng)論 4 324
  • 正文 年R本政府宣布勾邦,位于F島的核電站,受9級(jí)特大地震影響割择,放射性物質(zhì)發(fā)生泄漏眷篇。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評(píng)論 3 307
  • 文/蒙蒙 一荔泳、第九天 我趴在偏房一處隱蔽的房頂上張望蕉饼。 院中可真熱鬧虐杯,春花似錦、人聲如沸昧港。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽创肥。三九已至达舒,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間叹侄,已是汗流浹背巩搏。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評(píng)論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留趾代,地道東北人贯底。 一個(gè)月前我還...
    沈念sama閱讀 45,578評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像撒强,于是被迫代替她去往敵國和親禽捆。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容