文件传输基础(Java IO流)——文件操作

文件传输基础(Java IO流)——文件操作

编码

package com.zdy;

import java.io.UnsupportedEncodingException;

/**
 * Created by zdy on 2017/1/19.
 */
public class EncodeDemo {
    public static void main(String[] args) throws UnsupportedEncodingException {
        String s="慕课ABC";
        /*utf-8 中文 3个字节,英文 1个字节*/
        byte[] bytes1=s.getBytes("utf-8");
        for(byte b:bytes1){
            System.out.print(Integer.toHexString(b&0xff)+" ");
        }
        System.out.println();

        /*gbk 中文 2个字节,英文 1个字节*/
        byte[] bytes2=s.getBytes("gbk");
        for(byte b:bytes2){
            System.out.print(Integer.toHexString(b&0xff)+" ");
        }
        System.out.println();

        /*utf-16be 中文 2个字节,英文 2个字节*/
        byte[] bytes3=s.getBytes("utf-16be");
        for(byte b:bytes3){
            System.out.print(Integer.toHexString(b&0xff)+" ");
        }
        System.out.println();

        String str1=new String(bytes1,"utf-8");
        System.out.println(str1);

        String str2=new String(bytes2,"gbk");
        System.out.println(str2);

        String str3=new String(bytes3,"utf-16be");
        System.out.println(str3);

    }
}

File类

  • java.io.File类用于表示文件(目录)
  • File类只用于表示文件(目录)的信息(名称、大小等),不能用于文件内容的访问

提示:为了跨平台,目录分割符建议使用斜线/或者File.separator

语法:

//文件对象 mac,linux中注意权限问题
File file=new File("/Users/zdy/Workspace/test");
//是否存在,存在true,不存在false
file.exists()
//是否是目录,是目录true,不是目录或者目录不存在false
file.isDirectory()
//是否是文件,是文件true,不是目录或者文件不存在false
file.isFile()
//创建目录
file.mkdir()
//创建多级目录
file.mkdirs()
//创建文件
file.createNewFile()
//删除目录或文件
file.delete()

//打印文件路径,file.toString(),例如 /Users/zdy/Workspace/test/1.txt
System.out.println(file);
//绝对路径
file.getAbsolutePath();
//文件名或者路径名(仅最后一个节点)
file.getName()
//父目录 名
System.out.println(file.getParent());
System.out.println(file.getParentFile().getAbsolutePath());

【示例】

package com.zdy;

import java.io.File;
import java.io.IOException;

/**
 * Created by zdy on 2017/1/19.
 */
public class FileDemo {
    public static void main(String[] args) throws IOException {
        File file=new File("/Users/zdy/Workspace/test/1.txt");
        //File file2=new File(File.separator+"Users");
        /*是否存在*/
        System.out.println(file.exists());
        /*是否是目录*/
        System.out.println(file.isDirectory());
        /*是否是文件*/
        System.out.println(file.isFile());
        if (!file.exists()){
            file.createNewFile();
        }else{
            //file.delete();
        }
        System.out.println(file);
        System.out.println(file.getParentFile().getName());
    }
}

目录遍历实例

【FileUtils.java】

package com.zdy;

import java.io.File;

/**
 * Created by zdy on 2017/1/19.
 */
public class FileUtils {

    public static void listDirectory(File dir){
       if (!dir.exists()){
           throw new IllegalArgumentException("目录"+dir+"不存在.");
       }
       if (!dir.isDirectory()){
           throw new IllegalArgumentException(dir+"不是目录");
       }
       /*
       String[] filenames=dir.list();//返回字符串数组,只列出直接子文件或子目录
       for (String filename:filenames){
           System.out.println(dir+filename);
       }*/
       //遍历子目录,递归操作
        File[] files=dir.listFiles();//返回直接子目录文件的抽象
        if (files!=null&&files.length>0){
            for (File file:files){
                if (file.isDirectory()){
                    listDirectory(file);
                }else{
                    System.out.println(file);
                }
            }
        }
    }
}

【FileUtilTest.java】

package com.zdy;

import java.io.File;

/**
 * Created by zdy on 2017/1/19.
 */
public class FileUtilTest {
    public static void main(String[] args) {
        FileUtils.listDirectory(new File("/Users/zdy/Workspace"));
    }
}

RandomAccessFile

  • java提供的对文件内容的访问,既可以读文件,也可以写文件
  • 支持随机访问文件,可以访问文件的任意位置

语法

//打开文件。两种模式,读写`rw`只读`r`
RandomAccessFile randomAccessFile=new RandomAccessFile(file,"rw");

//写,写一个字节(8位),同时指针指向下一个位置,准备再次写入
randomAccessFile.write();
//写入字符‘A’
randomAccessFile.write('A');
//写入数字1
int i=1;
randomAccessFile.writeInt(i);
//写入 ”张“
String s="张";
byte[] b=s.getBytes();
randomAccessFile.write(b);

//读,读一个字节,或者读到一个字节数组
randomAccessFile.read();
randomAccessFile.read(buf);

//获取指针的位置
randomAccessFile.getFilePointer()
//指针移到某处,比如头部
randomAccessFile.seek(0)

//文件的字节数(long型,可强转为int)
randomAccessFile.length()

//关闭文件
randomAccessFile.close()

【示例】

package com.zdy;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Arrays;

/**
 * Created by zdy on 2017/1/20.
 */
public class RafDemo {
    public static void main(String[] args) throws IOException {
        File demo=new File("/Users/zdy/Workspace/test/demo.dat");
        if (demo.exists()){
            demo.delete();
        }
        if (!demo.exists()){
            demo.createNewFile();
        }
        RandomAccessFile randomAccessFile=new RandomAccessFile(demo,"rw");
        System.out.println(randomAccessFile.getFilePointer());
        randomAccessFile.write('A');
        //randomAccessFile.read();
        int i=1;
        randomAccessFile.write(i>>>24);
        randomAccessFile.write(i>>>16);
        randomAccessFile.write(i>>>8);
        randomAccessFile.write(i);
        randomAccessFile.writeInt(i);
        String s="张";
        byte[] b=s.getBytes();
        randomAccessFile.write(b);
        System.out.println(randomAccessFile.length());
        randomAccessFile.seek(0);
        byte[] buf=new byte[(int)randomAccessFile.length()];
        randomAccessFile.read(buf);
        System.out.println(Arrays.toString(buf));
        String s1=new String(buf);
        System.out.println(s1);
        //以十六进制形式打印
        for (byte b1:buf) {
            System.out.print(Integer.toHexString(b1&0xff)+" ");
        }
        randomAccessFile.close();
    }
}

IO流

字节流/字符流 ;输入流/输出流

字节流

InputStream OutputStream

  • InputStream抽象了应用程序读取数据的方式
  • OutputStream抽象了应用程序写入数据的方式

EOF(-1)

输入流

//读取一个字节无符号填充到int低八位。-1是EOF
int b=in.read()
//读取数据填充到字节数组buf
in.read(byte[] buf)
//读取数据到字节数组buf,从buf的start位置开始存放size长度的数据
in.read(byte[] buf,int start,int size)

输出流

//写出一个byte到流,b的第八位
out.write(int b)
//将buf字节数组写入到流
out.write(byte[] buf)
//字节数组buf从start位置开始写szie长度的字节到流
out.write(byte[],int start,int size)

FileInputStream

具体实现了在文件上读取数据

示例:

【IOUtil.java】

package com.zdy;

import java.io.FileInputStream;
import java.io.IOException;

/**
 * Created by zdy on 2017/1/20.
 */
public class IOUtil {
    /*读取制定文件内容,按照16进制输出到控制台*/
    public static void printHex(String fileName) throws IOException {
        FileInputStream fileInputStream=new FileInputStream(fileName);
        int b;
        int i=1;
        while ((b= fileInputStream.read())!=-1){
            if (b<=0xf){
                //单位数前面补零
                System.out.print("0");
            }
            System.out.print(Integer.toHexString(b)+" ");
            if (i++%10==0){
                System.out.println();
            }
        }
        fileInputStream.close();
    }
    public static void printHexByByteArray(String fileName) throws IOException {
        FileInputStream fileInputStream=new FileInputStream(fileName);
        byte[] buf=new byte[20*1024];
        int bytes=0;
        int j=1;
        while  ((bytes=fileInputStream.read(buf,0,buf.length))!=-1) {
            for (int i=0;i<bytes;i++){
                if((buf[i]&0xff) <=0xf){
                    System.out.print("0");
                }
                System.out.print(Integer.toHexString(buf[i]&0xff)+" ");
                if (j++%10==0){
                    System.out.println();
                }
            }
        }
        fileInputStream.close();
    }
}

【IOUtilTest.java】

package com.zdy;

import java.io.IOException;

/**
 * Created by zdy on 2017/1/20.
 */
public class IOUtilTest {
    public static void main(String[] args) {
        try {
            IOUtil.printHex("/Users/zdy/Workspace/test/demo.dat");
            System.out.println();
            IOUtil.printHexByByteArray("/Users/zdy/Workspace/test/demo.dat");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

【输出示例】

41 00 00 00 01 00 00 00 01 e5 
bc a0 
41 00 00 00 01 00 00 00 01 e5 
bc a0

FileOutputStream

【FIleOutputStreamDemo:写文件demo】

package com.zdy;

import java.io.FileOutputStream;
import java.io.IOException;

/**
 * Created by zdy on 2017/1/20.
 */
public class FIleOutputStreamDemo {
    public static void main(String[] args) throws IOException {
        //存在文件,删除后重新创建;不存在,创建文件
        FileOutputStream fileOutputStream=new FileOutputStream("/Users/zdy/Workspace/test/out.dat",true);
        fileOutputStream.write('A');
        fileOutputStream.write('B');
        int a=10;
        fileOutputStream.write(a>>>24);
        fileOutputStream.write(a>>>16);
        fileOutputStream.write(a>>>8);
        fileOutputStream.write(a);
        byte[] bytes="张丹阳".getBytes();
        fileOutputStream.write(bytes);
        fileOutputStream.close();
        IOUtil.printHex("/Users/zdy/Workspace/test/out.dat");
    }
}

复制文件示例

【IOUtil.java】

public class IOUtil {
    /* 批量字节拷贝,效率最高*/
    public static void copyFile(File srcFile,File destFile) throws IOException {
        if (!srcFile.exists()){
            throw new IllegalArgumentException("源文件"+srcFile+"不存在");
        }
        if (!srcFile.isFile()){
            throw new IllegalArgumentException(srcFile+"不是文件");
        }
        FileInputStream fileInputStream=new FileInputStream(srcFile);
        FileOutputStream fileOutputStream=new FileOutputStream(destFile);
        byte[] buf=new byte[20*1024];
        int b;
        while  ((b=fileInputStream.read(buf,0,buf.length))!=-1){
            fileOutputStream.write(buf,0,b);
            fileOutputStream.flush();
        }
        fileInputStream.close();
        fileOutputStream.close();
    }
}

【IOUtilTest.java】

package com.zdy;

import java.io.File;
import java.io.IOException;

/**
 * Created by zdy on 2017/1/20.
 */
public class IOUtilTest {
    public static void main(String[] args) {
        try {
            IOUtil.copyFile(new File("/Users/zdy/Workspace/test/demo.dat"),new File("/Users/zdy/Workspace/test/copydemo.dat"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

DataInputStream/DataOutputStream

对流功能的扩展,可以更加方便的读取int,long,字符等类型数据。

【DataInputStreamDemo.java】

package com.zdy;

import java.io.*;

/**
 * Created by zdy on 2017/1/20.
 */
public class DataInputStreamDemo {
    public static void main(String[] args) throws IOException {
        DataInputStream dataInputStream=new DataInputStream(new FileInputStream("/Users/zdy/Workspace/test/dos.txt"));
        System.out.println(dataInputStream.readInt());
        System.out.println(dataInputStream.readInt());
        System.out.println(dataInputStream.readFloat());
        System.out.println(dataInputStream.readLong());
        System.out.println(dataInputStream.readUTF());//utf-8
        System.out.println(dataInputStream.readChar());//utf-16be
        dataInputStream.close();
    }
}

【DataOutputStreamDemo.java】

package com.zdy;

import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * Created by zdy on 2017/1/20.
 */
public class DataOutputStreamDemo {
    public static void main(String[] args) throws IOException {
        DataOutputStream dataOutputStream=new DataOutputStream(new FileOutputStream("/Users/zdy/Workspace/test/dos.txt"));
        dataOutputStream.writeInt(10);
        dataOutputStream.writeInt(-10);
        dataOutputStream.writeFloat(10.5f);
        dataOutputStream.writeLong(1000L);
        dataOutputStream.writeUTF("张丹阳");//utf-8
        dataOutputStream.writeChar('A');//utf-16be
        dataOutputStream.close();
    }
}

BufferedInputStream/BufferedOutputStream

这两个流类为IO提供了带缓冲区的操作,一般打开文件进行写入或读取操作时,都会加上缓冲,这种流模式提高了IO的性能,

【IOUtil.java】

public class IOUtil {
    /*通过缓冲区拷贝*/
    public static void copyFileByBuffer(File srcFile,File destFile) throws IOException {
        if (!srcFile.exists()){
            throw new IllegalArgumentException("源文件"+srcFile+"不存在");
        }
        if (!srcFile.isFile()){
            throw new IllegalArgumentException(srcFile+"不是文件");
        }
        BufferedInputStream bufferedInputStream=new BufferedInputStream(new FileInputStream(srcFile));
        BufferedOutputStream bufferedOutputStream=new BufferedOutputStream(new FileOutputStream(destFile));
        int c;
        while  ((c=bufferedInputStream.read())!=-1){
            bufferedOutputStream.write(c);
            bufferedOutputStream.flush();//刷新缓冲区
        }
        bufferedInputStream.close();
        bufferedOutputStream.close();
    }
}

【IOUtilTest.java】

package com.zdy;

import java.io.File;
import java.io.IOException;

/**
 * Created by zdy on 2017/1/20.
 */
public class IOUtilTest {
    public static void main(String[] args) {
        try {
            IOUtil.copyFileByBuffer(new File("/Users/zdy/Workspace/test/demo.dat"),new File("/Users/zdy/Workspace/test/demo.txt"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

字符流

认识文本和文本文件

  • java的文本char是16位无符号整数,是字符的unicode编码(双字节编码)
  • 文件是byte的数据序列
  • 文本文件是char序列按照某种编程方案(utf-8,utf-16be,gbk)序列华为byte的存储

字符流

  • 字符的处理,一次处理一个字符
  • 字符的底层依然是基本的字节序列

用来操作文本文件。

字符流的基本实现

  • InputStreamReader 完成byte流解析为char流,按照编码解析
  • OutputStreamWriter 提供char流到byte流,按照编码处理

【示例:InputStreamReaderAndOutputStreamReaderDemo.java】

package com.zdy;

import java.io.*;

/**
 * Created by zdy on 2017/1/22.
 */
public class InputStreamReaderAndOutputStreamReaderDemo {
    public static void main(String[] args) throws IOException {
        FileInputStream fileInputStream=new FileInputStream("/Users/zdy/Workspace/test/test.txt");
        FileOutputStream fileOutputStream=new FileOutputStream("/Users/zdy/Workspace/test/test2.txt");
        InputStreamReader inputStreamReader=new InputStreamReader(fileInputStream,"utf-8");
        OutputStreamWriter outputStreamWriter=new OutputStreamWriter(fileOutputStream,"utf-8");
        /*int c;
        while((c=inputStreamReader.read())!=-1){
            System.out.println((char) c);
        }*/
        char[] buffer=new char[8*1024];
        int c;
        while  ((c=inputStreamReader.read(buffer,0,buffer.length))!=-1){
            String s=new String(buffer,0,c);
            System.out.println(s);
            outputStreamWriter.write(buffer,0,c);
        }
        inputStreamReader.close();
        outputStreamWriter.close();
        fileInputStream.close();
        fileOutputStream.close();
    }
}
  • FileReader
  • FileWriter

【示例:FileReaderAndFileWriterDemo.java】

package com.zdy;

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

/**
 * Created by zdy on 2017/1/22.
 */
public class FileReaderAndFileWriterDemo {
    public static void main(String[] args) throws IOException {
        FileReader fileReader=new FileReader("/Users/zdy/Workspace/test/test.txt");
        FileWriter fileWriter=new FileWriter("/Users/zdy/Workspace/test/test2.txt",true);
        char []buffer=new char[1024*8];
        int c;
        while  ((c=fileReader.read(buffer,0,buffer.length))!=-1){
            fileWriter.write(buffer,0,c);
        }
        fileWriter.flush();
        fileReader.close();
        fileWriter.close();
    }
}

字符流的过滤器

  • BufferedReader ,readLine一次读一行
  • BuffererWriter/PrintWriter 写一行

【示例:BufferedReaderAndBufferedWriterAndPrintWriterDemo.java】

package com.zdy;

import java.io.*;

/**
 * Created by zdy on 2017/1/22.
 */
public class BufferedReaderAndBufferedWriterAndPrintWriterDemo {
    public static void main(String[] args) throws IOException{
        BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(new FileInputStream("/Users/zdy/Workspace/test/test.txt")));
        BufferedWriter bufferedWriter=new BufferedWriter(new OutputStreamWriter(new FileOutputStream("/Users/zdy/Workspace/test/test2.txt")));
        PrintWriter printWriter=new PrintWriter("/Users/zdy/Workspace/test/test3.txt");
        String line;
        while  ((line=bufferedReader.readLine())!=null){
            System.out.println(line);
            bufferedWriter.write(line);
            //单独写换行
            bufferedWriter.newLine();

            printWriter.println(line);
        }
        bufferedWriter.flush();
        printWriter.flush();
        bufferedReader.close();
        bufferedWriter.close();
        printWriter.close();
    }
}

对象序列化/反序列化

  • 对象序列化,就是将Object转换成byte序列,反之叫对象的反序列化

  • 序列化流(ObjectOutputStream)---writeObject;反序列化流(ObjectInputStream)---readObject

  • 序列化接口(Serializable):对象必须实现序列化接口,才能进行序列化,否则将出现异常。这个接口,没有任何方法,知识一个标准。

  • Java序列化就是把对象转换成字节序列,而Java反序列化就是把字节序列还原成Java对象。

  • 采用Java序列化与反序列化技术,一是可以实现数据的持久化,在MVC模式中很是有用;二是可以对象数据的远程通信。

【Student.java】

package com.zdy;

import java.io.Serializable;

/**
 - Created by zdy on 2017/1/22.
 */
public class Student implements Serializable{
    private String no;
    private String name;
    private int age;

    public Student() {
    }

    public Student(String no, String name, int age) {
        this.no = no;
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "no='" + no + '\'' +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public String getNo() {
        return no;
    }

    public void setNo(String no) {
        this.no = no;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

【ObjectSerializableDemo.java】

package com.zdy;

import java.io.*;

/**
 * Created by zdy on 2017/1/22.
 */
public class ObjectSerializableDemo {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        String file="/Users/zdy/Workspace/test/obj.dat";
        /*对象的序列化*/
        ObjectOutputStream objectOutputStream=new ObjectOutputStream(new FileOutputStream(file));
        Student student=new Student("10001","张三",22);
        objectOutputStream.writeObject(student);
        objectOutputStream.flush();
        objectOutputStream.close();
        /*对象的反序列化*/
        ObjectInputStream objectInputStream=new ObjectInputStream(new FileInputStream(file));
        Student stu=(Student)objectInputStream.readObject();
        System.out.println(stu.toString());
        objectInputStream.close();
    }
}

【打印结果】

Student{no='10001', name='张三', age=22}

transient,不进行序列化

修改 Student.javaprivate int age;private transient int age;

【打印结果】

Student{no='10001', name='张三', age=0}

单独序列化

在某些情况下可以提高性能

private transient int age;的基础上,向Student.java添加下面方法:

private void writeObject(java.io.ObjectOutputStream s)
        throws java.io.IOException{
    s.defaultWriteObject();
    s.writeInt(age);
}
private void readObject(java.io.ObjectInputStream s)
        throws java.io.IOException, ClassNotFoundException {
    s.defaultReadObject();
    this.age=s.readInt();
}

【打印结果】

Student{no='10001', name='张三', age=22}

序列化中子类和父类

一个类实现了序列化接口,那么其子类都可以进行序列化。

对子类对象进行反序列化时,如果其父类没有实现序列化接口,那么其父类的构造函数会被显式调用。

[一条慕课网视频评论]在创建子类对象的时候,同时就需要创建其所有直接以及间接父类对象(没父亲自然就没儿子),所以,如果最早的父类实现了Serializable接口,那么将二级子类序列化写入文件的时候,实际上是对父类,一级子类,二级子类三个对象都进行了序列化并写入文件,所以,再将文件中内容反序列化到一个新创建的二级子类对象的时候(实际上就是将文件中的内容反序列化给这个新对象),自然就不需要调用那些父类的构造函数,因为文件里面已经都有了,干嘛还要再构造一次

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,924评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,902评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,716评论 0 239
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,783评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,166评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,510评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,784评论 2 311
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,476评论 0 196
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,196评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,459评论 2 243
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,978评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,321评论 2 252
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,964评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,046评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,803评论 0 193
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,530评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,420评论 2 265

推荐阅读更多精彩内容