JAVA基础---File、IO流

1.File

  • File类代表文件或者文件的类
  • 创建文件类的对象,在创建对象的过程中没有检测路径的信息是否存在,会把路径信息放在对象的身上。即若路径信息不存在,创建对象的语句编译和运行都不会报错。
File file=new File(路径);
  • 新建文件,新建文件为空文件,若路径信息的指定文件已经存在的话,返回值将会为false
boolean b=file.createNewFile();
  • 创建文件夹(多级)
 File f1=new File("E:\\IDEA\\workspace\\JAVASE2007\\Day18\\src\\cn\\tedu\\file\\a\\b\\c");
        //创建文件夹(多级)
 boolean b1=f1.mkdirs();
 System.out.println(b1);
  • 删除文件,无论文件是否有内容均可以删除,但是只能删除空文件夹,该方法操作需要慎重,删除文件无法还原。
boolean b2=file.delete();
  • 获取文件或是文件夹的名称,若为文件时,将会返回文件名+后缀名字/文件夹名字
File file=new File(路径信息);
//文件名+后缀名/文件夹名字
System.out.println(file.getName());
  • 返回当前所在文件夹
System.out.file(file.getParent());
  • 返回对象所在的路径信息
System.out/println(file.getPath());
  • 返回文件上次修时间----即从1970年1月1日0时0分0秒到现在的毫秒值
System.out.println(file.lastModified());
  • 设置文件上一次修改时间
file.setLastModified(233333333L);
  • 返回文件抽象路径表示的长度,如果file表示的是一个具体的文件,则返回的文件的字节大小,如果File表示一个目录,则返回值不能确定,如果目录或是文件不存在,则返回为0L.
System.out.println(file.length());
  • 返回文件夹下的所有文件,把当前文件夹下的所有信息当作File对象放入到数组中
File[] fs=file.listFiles();
  • 过滤文件,根据一定的过滤规则筛选出符合条件的文件,下面为不同的两种方法
        File f=new File("E://");
        //把E盘下含有数字的文件或者文件夹进行输出
        //把过滤之后的File类对象返回到数组中
        File[] fs=f.listFiles(new FileFilter() {
            //重写方法--过滤规则
            @Override
            public boolean accept(File pathname) {
                //正则语法----匹配字符串中含有数字
                return pathname.getName().matches(".*\\d.*");
            }
        });
        //遍历数组
        for(File f1:fs)
            System.out.println(f1);

        //
        File[] fss=file.listFiles(new FilenameFilter() {
            @Override
            public boolean accept(File dir, String name) {
                return name.matches(".*\\d.*");
            }
        });
  • 重命名文件的抽象路径名
        //创建代表文件类的对象
        File file=new File("E:\\IDEA\\workspace\\JAVASE2007\\Day18\\src\\cn\\tedu\\file\\123.txt");
        //重命名
        //底层是由剪切来实现的
        boolean b=file.renameTo(new File("E:\\IDEA\\workspace\\JAVASE2007\\Day18\\src\\cn\\tedu\\file\\a\\七夕.txt"));
        System.out.println(b);
  • 判断是否是文件夹
System.out.println(file.isDirectory());
  • 判断是否是文件
System.out.println(file.isFile());
  • 练习:删除文件夹下的所有文件内容(包括文件以及文件夹)
package cn.tedu.test;

import java.io.File;
import java.io.FileFilter;
import java.io.FilenameFilter;
import java.io.IOException;

public class TestDemo1 {
    public static void main(String[] args) throws IOException {
        File file=new File("E:\\IDEA\\workspace\\JAVASE2007\\Day18\\src\\cn\\tedu\\file\\a");
        //调用方法删除文件
        deleteFiles(file);
    }
    //定义删除文件方法
    public static void deleteFiles(File file){
        //判断是否是文件夹
        if(file.isDirectory()){
            //说明是文件夹,需要展开当前文件夹所有信息
            //获取当前文件夹所有信息
            //放入到数组中
            File [] fs=file.listFiles();
            //遍历当前数组
            for(File f:fs){
                //递归调用
                deleteFiles(f);
            }
        }
        //删除文件以及空文件夹
        file.delete();
    }
}
  • 统计工程里.java文件的个数以及.class文件个数
package cn.tedu.test;

import java.io.File;
import java.io.FileFilter;
import java.io.FilenameFilter;
import java.io.IOException;

public class TestDemo1 {
    //表示java文件的个数
    private static int countJava=0;
    //表示class文件的个数
    private static int countClass=0;
    public static void main(String[] args) throws IOException {
        File file = new File("E:\\IDEA\\workspace\\JAVASE2007");
        //统计方法统计文件数
        countFiles(file);
        //输出java文件的个数
        System.out.println("java文件个数:"+countJava);
        System.out.println("class文件个数:"+countClass);
    }
    //定义方法来统计文件数
    public static void countFiles(File file){
        //判断文件是否是文件夹
        if(file.isDirectory()){
            //说明是文件夹
            //获取文件夹里的信息
            File [] fs=file.listFiles();
            //遍历数组
            for(File f:fs){
                countFiles(f);
            }
        }
        //统计java文件个数
        if(file.getName().endsWith(".java")){
            countJava++;
        }
        //统计class文件的个数
        if(file.getName().endsWith(".class")){
            countClass++;
        }
    }
}

2.IO流

1)概念:本质上是一套数据传输的机制
2)图例:若将A文件写入到B文件中将会涉及到数据传输机制,即涉及到IO流。


image.png

3)三要素:将内存看作是参照物

  • 根据传输的方向
     输入流:往内存来传输数据
     输出流:从内存往外传输数据
  • 根据传输的方式
     字符流:传输字符形式的数据
     字节流:传输字节形式的数据
  • 根据数据存放/获取的位置
     硬盘、内存、网络、外设设备

4)四大基本流(下面的四个类均为抽象类)

  • 字符输入流:Reader
  • 字符输出流:Writer
  • 字节输入流:InputStream
  • 字节输出流:OutputStream

5)硬盘

  • 字符流
    A、给硬盘上.txt文件写入数据-----文件字符输出流--FileWriter
package cn.tedu.test;

import java.io.*;

public class TestDemo1 {
    public static void main(String[] args) throws IOException {
        //创建文件字符输出流对象
        //创建对象的过程中会检测路径信息是否存在
        //若存在会创建新的空文件进行覆盖
        //当未指定append的值时,append的值将会默认为false
        //当append为true时,不会会覆盖文件的原有内容,若为false,将会覆盖原有内容
        FileWriter fw=new FileWriter("Test\\src\\file\\a.txt",true);
        //写入数据
        //写入int数据
        fw.write(1);
        //写入char数组数据
        char c[]={'a','b','c'};
        fw.write(c,1,2);
        //写入String数据
        fw.write("你好");

    }
}

但是,当我们这样的写程序的时候会发现,文件中并未存在我们写入的内容,原因是什么呢?接下来,我们看一下FileWriter的大致写入过程。


数据写入过程.png

 由上图可知,我们上述程序未写入的原因就是缓冲区并未存放满,那么缓冲区的容量大概是多少?又如何将未存放满的数据存放到文件中。
 由资料查找可知,缓冲区的容量为8kb,而当我们需要将数据从缓冲区中拿取出来时可以采用flush()函数来冲刷缓冲区。完整程序代码如下:

package cn.tedu.test;

import java.io.*;

public class TestDemo1 {
    public static void main(String[] args) throws IOException {
        //创建文件字符输出流对象
        //创建对象的过程中会检测路径信息是否存在
        //若存在会创建新的空文件进行覆盖
        //当未指定append的值时,append的值将会默认为false
        //当append为true时,不会会覆盖文件的原有内容,若为false,将会覆盖原有内容
        FileWriter fw=new FileWriter("Test\\src\\file\\a.txt",true);
        //写入数据
        //写入int数据
        fw.write(1);
        //写入char数组数据
        char c[]={'a','b','c'};
        fw.write(c,1,2);
        //写入String数据
        fw.write("你好");

        //底层为了提高和保证数据传输效率,会提供缓冲区来传输数据并且要求缓冲区
        //存满了才会进行数据传输。若此时数据没有充满缓冲区且并未冲刷缓冲区
        //数据将会滞留在缓冲区并且丢失
        //冲刷缓冲区
        fw.flush();

        //关流
        //含有自动冲刷的过程
        fw.close();
        
        //将流对象置为null,等待系统进行回收
        fw=null;
    }
}

B、从硬盘上的.txt文件读取数据-----文件输入流---FileReader

package cn.tedu.test;

import java.io.*;

public class TestDemo1 {
    public static void main(String[] args) throws IOException {
        //创建文件输入流对象
        FileReader fr=new FileReader("Test\\src\\file\\a.txt");
        //返回单个字符的编码值
        /*System.out.println(fr.read());
        System.out.println(fr.read());
        //当读取完毕之后将会返回-1
        System.out.println(fr.read());*/

        //采用循环来实现上述过程
        int i=-1;
        while((i=fr.read())!=-1){
            System.out.println(i);
        }
        //关流
        fr.close();
    }
}

 在上述过程中,我们采用了read()方法读取单个字符的编码值,但是很明显单个字符进行读取的时候数据传输效率并不是很高,但是在底层我们也没有像字符输出流一样拥有缓冲区,那么我们该怎样提高数据传输效率?答案就是自建缓冲区,代码实例如下:

public static void main(String[] args) throws IOException {
        //创建文件输入流对象
        FileReader fr=new FileReader("Test\\src\\file\\a.txt");
        //自建缓冲区
        //创建新数组,存放我们要读取的数据就
        char cs[]=new char[5];
        //把读取到的数据存放到数组中
        while(fr.read(cs)!=-1){
            System.out.println(cs);
        }
        //关流
        fr.close();
    }

接下来我们查看一下文档内容是否和输出内容一致。


结果对比.png

 很明显,结果不相同,那么原因又是什么呢?我们来看一下该段程序的大致执行过程。


执行过程.png

 由图可知,我们想要解决这个问题,必须对输出的数据进行截取,只能截取文件内容输出完毕,即文件内容输出完毕,数据同样也输出相同长度。代码见如下:
package cn.tedu.test;

import java.io.*;

public class TestDemo1 {
    public static void main(String[] args) throws IOException {
        //创建文件输入流对象
        FileReader fr=new FileReader("Test\\src\\file\\a.txt");
        //自建缓冲区
        //创建新数组,存放我们要读取的数据就
        char cs[]=new char[5];
        int len=-1;
        //把读取到的数据存放到数组中
        //方法返回值就是读取字符的个数,返回-1读取完毕
        while((len=fr.read(cs))!=-1){
            //输出数组内容
            System.out.println(new String(cs,0,len));
        }
        //关流
        fr.close();
    }
}
  • 字节流(常见)
    A、给硬盘上.txt文件写入数据(txt文件较为特殊,可以把字节转字符,也可以把字符转为字节)---文件字节输出流----FileOutputStream
package cn.tedu.test;

import java.io.*;

public class TestDemo1 {
    public static void main(String[] args) throws IOException {
        //创建文件字节输出流对象
        //底层不存在缓冲区
        FileOutputStream fos=new FileOutputStream("Test\\src\\file\\a.txt");
        //写出数据
        fos.write("你好".getBytes());
        //关流
        fos.close();
    }
}

B、从硬盘上.txt文件读取数据----文件字节输入流--FileInputStream

package cn.tedu.test;

import java.io.*;

public class TestDemo1 {
    public static void main(String[] args) throws IOException {
        //创建文件字节输入流对象
        FileInputStream fis=new FileInputStream("Test\\src\\file\\a.txt");
        //返回一个字节对应的编码值
        /*文件存放内容为:你好
        编码方式为utf-8
        故对应字节为6个,所以应该读取六次读取完毕
         */
        /*System.out.println(fis.read());
        System.out.println(fis.read());
        System.out.println(fis.read());
        System.out.println(fis.read());
        System.out.println(fis.read());
        System.out.println(fis.read());
        //读取完毕返回-1
        System.out.println(fis.read());*/

        //采用自建缓冲区的方式来读取数据
        byte [] bs=new byte[15];
        int len=-1;
        //返回的是读取到的字节数,遇到-1读取完毕
        while((len=fis.read(bs))!=-1){
            //输出可能出现?的原因是:相应的字节数可能无法组成一个汉字
            System.out.println(new String(bs,0,len));
        }
        //关流
        fis.close();
    }
}

6)IO流中异常捕获
 我们都知道处理异常的方式有两种,一是抛出,而是捕获,那IO中的异常又是如何捕获的?

package cn.tedu.test;

import java.io.*;

public class TestDemo1 {
    public static void main(String[] args){
        //由于在创建IO流对象时可能会抛出异常,所以IO流对象对象的初始化过程需要放在
        //try块里,但是不论流对象是否真正的初始化成功,我们都需要把流对象
        //置为null以及关流,故该对象需要再finally中使用,所以我们将IO流对象
        //的创建过程分为初始化和声明两个过程。

        //1.声明流对象,并且赋值为null
        FileWriter fw=null;
        try{
            //流对象进行初始化
            fw=new FileWriter("Test\\src\\file\\a.txt");
            //写入数据
            fw.write("你好");
            //虽然我们关流时会进行自动冲刷缓冲区,但是同样的关流也同样有可能会发生异常
            //所以我们需要添加手动冲刷的过程,两者一起发生错误的几率还是很小的
            //4.手动冲刷
            fw.flush();
        }catch (IOException e){

        }finally {
            //2.判断流对象是否成功初始化
            if(fw!=null)
            //成功初始化
            //关流
            try {
                fw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }finally{
                //3.无论关流成功与否都要把流对象置为null
                fw=null;
            }
        }
    }
}

7)缓冲流(给IO流提供缓冲区)
 在之前,当我们一次性传输多个数据时,我们会采用自建缓冲区的方式,但是选取一个合适的缓冲区长度将会是一个问题,这时Java提供给我们一个缓冲流,用来给IO流提供缓冲区。

  • BufferedReader---给字符输入流提供缓冲区
    readLine()读取一行数据
package cn.tedu.test;

import java.io.*;

public class TestDemo1 {
    public static void main(String[] args) throws IOException {
        //创建缓冲流对象
        //BufferedReader和FileReader都是Reader的子类---同类
        //br对象具有FileReader的所有功能,但是还在此基础上增加了别的功能
        //所以,若将FileReader看作本类对象,BufferedReader作为同类对象
        //同类对象给本类对象增强(完善)功能---称为装饰者设计模式
        BufferedReader br=new BufferedReader(new FileReader
                ("Test\\src\\file\\a.txt"));
        //读取数据
        //读取一行数据
        /*
        文件中内容:你好
        helloworld
        总共分为两行
         */
        /*System.out.println(br.readLine());
        System.out.println(br.readLine());
        //当内容读取完毕之后将会返回null
        System.out.println(br.readLine());*/

        //使用循环实现上述功能
        String str="";
        while((str=br.readLine())!=null){
            System.out.println(str);
        }
        //关流
        br.close();
    }
}
  • BufferedWriter--给字符输出流提供缓冲区(虽然字符输出流自带缓冲区,但是BufferedWriter能够提供更大的缓冲区)
    newLine():换行
package cn.tedu.test;

import java.io.*;

public class TestDemo1 {
    public static void main(String[] args) throws IOException {
        //创建缓冲流对象
        BufferedWriter bw=new BufferedWriter(new FileWriter(
                "Test\\src\\file\\a.txt",true
        ));
        //写出数据
        bw.write("你好");
        //换行
        bw.newLine();
        bw.write("加油");
        //关流
        bw.close();
    }
}

8)转换流
 在数据传输的过程中,我们有时候会遇到这样的情况:比如我们需要得到字符流的数据,但是现在我们所拥有的只有字节流对象,或是我们可能会遇到需要字节流但是只有字符里的情况。那么,在这种情况下,我们就需要将字节流和字符流进行相互转换,这时我们会用到我们的转换流。

  • OutputStreamWriter----字符流转成字节流
package cn.tedu.test;

import java.io.*;

public class TestDemo1 {
    public static void main(String[] args) throws IOException {
        //创建转换流对象
        //转换对象是由文件字节输出流对象构建
        //底层真正进行传输数据的是文件字节输出流对象
        //接受准备数据时需要用的是字符形式数据,底层真正往外写出数据的是字节流形式
        //所以OutputStreamWriter转换流是将字符流转换成字节流
        OutputStreamWriter ow=new OutputStreamWriter(new FileOutputStream(
                "Test\\src\\file\\a.txt"
        ));
        //写出数据
        //当我们需要写出数据时,我们需要提前准备字符形式的数据
        ow.write("你好");
        //g关流
        ow.close();
    }
}
  • InputStreamReader----字节流转成字符流
package cn.tedu.test;

import java.io.*;

public class TestDemo1 {
    public static void main(String[] args) throws IOException {
        //创建转换流对象
        //转换流对象是由文件自建输入流对象来提供的
        //底层真正读取数据的是文件字节输入流
        //先根据文件字节输入流来读取数据,再根据字符流来展示数据
        //所以InputStreamReader是将字节流数据转换成为字符流
        InputStreamReader isr=new InputStreamReader(new FileInputStream(
                "Test\\src\\file\\a.txt"
        ));
        //读取数据
        char [] cs=new char[10];//自建缓冲区
        int len=-1;
        //展示数据为字符形式数据
        //展示的数据由字符流来提供
        while((len=isr.read(cs))!=-1){
            System.out.println(new String(cs,0,len));
        }
        //关流
        isr.close();
    }
}

9)系统流
 我们首先来看下面的代码:

package cn.tedu.test;

import java.io.*;
import java.util.Scanner;

public class TestDemo1 {
    public static void main(String[] args) throws IOException {
        //输出正确结果
        //out---字节输出流对象
        System.out.println(1);
        //输出错误结果
        //err---字节输出流对象
        System.err.println(1);
        //in---字节输入流对象
        Scanner sc=new Scanner(System.in);
        int num=sc.nextInt();
        System.out.println(num);
    }
}

 由上面程序可知,out、err、in都是字节流。那么由之前的操作我们可以得知,流对象是可以关闭的,那么我们能否对其进行关闭呢?

package cn.tedu.test;

import java.io.*;
import java.util.Scanner;

public class TestDemo1 {
    public static void main(String[] args) throws IOException {
        Scanner sc=new Scanner(System.in);
        int num=sc.nextInt();
        System.out.println(num);
        //关流
        sc.close();
        Scanner sc1=new Scanner(System.in);
        int num1=sc1.nextInt();
        System.out.println(num1);
    }
}

 结果如下:

image.png

 有结果来看,很明显是不可以的,而发生这种情况的原因就是,在底层代码中in是静态流对象,如果关闭了,其他地方无法使用。所以,我们需要注意的是:系统流都是静态的流对象,使用完毕之后不能关流(且系统流不会占用太多内存)
10)打印流
 在上一块代码中,我们可以看到out以及err都是PrintStream的对象,PrintStream称为打印流,是字节输出流。

package cn.tedu.test;

import java.io.*;
import java.util.Scanner;

public class TestDemo1 {
    public static void main(String[] args) throws IOException {
        //创建打印流对象
        PrintStream pw=new PrintStream( "Test\\src\\file\\a.txt");
        //写出数据
        pw.print("123");
        pw.println();
        pw.print(123);
        //关流
        pw.close();
    }
}

 我们的print以及println方法都是定义在打印流中的,我们之前之所以能够将数据打印到控制台中,是因为在System中指定了路径信息为打印台,所以同样的,我们也可以采用一样的方式将信息打印到我们的文件中。
12)序列化与反序列化
 在我们的日常生活中,我们面对数据传输时我们往往是需要将大量的数据信息进行传输,更具Java一切皆对象的思想,我们可以将数据封装对象来进行传输或是接收,这样过的过程我们称之为序列化与反序列化

  • 序列化:把对象以及相关信息转成字节数组
    反序列化:把字节数组转成相应的对象
  • 注意:
    1.类实现了Serializable接口产生的对象才能被序列化
    2.如果属性被static/transient来修饰不能被序列化过去,方法不会被序列化过去
    3.serialVersionUID(序列化版本号):在序列化之前会根据类里的属性和方法来计算出一个版本号,随着对象一起序列化过去。在反序列化之前会再次根据类里的属性和方法来计算出一个版本号,根据前后两个版本号进行对比,如果对比结果一致可以进行正常的反序列化,如果对比结果不一致则反序列化失败。(解决方法----提供版本号)
    4.集合对象和映射对象都不能直接进行序列化,只能依次遍历元素对象一一进行序列化。(其存放内容的属性均被static修饰,无法被序列化过去)
  • 实例代码
    序列化:
package cn.tedu.test;

import java.io.*;
import java.util.ArrayList;
import java.util.Scanner;

public class TestDemo1 {
    public static void main(String[] args) throws IOException {
        //创建对象
        ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream(
                "Test\\src\\file\\person.data"
        ));
        //提供对象
        Person p=new Person("爱丽丝",12);
        //把对象转换成字节数组进行序列化
        oos.writeObject(p);
        //关流
    }
}
//定义代表人的类
class Person implements Serializable{
    //java自动提供的序列化版本号
    private static final long serialVersionUID = -109039264791201202L;
    //提供版本号--java就不再计算版本号
    //private static final long serialVersionUID=1555555555L;
    //属性
    private String name;
    private int age;
    //属性会被序列化过去
    //静态属性不会被序列化过去
    //强制属性不会被序列化过去
    transient double weight;

    //静态属性
    private static String classroom;
    //方法不会被序列化过去
    
    //定义有参构造
    public Person(String name,int age){
        this.name=name;
        this.age=age;
    }
    //提供get方法
    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
    //重写toString

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

反序列化

package cn.tedu.test;

import java.io.*;
import java.util.ArrayList;
import java.util.Scanner;

public class TestDemo1 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //创建对象
        ObjectInputStream o=new ObjectInputStream(new FileInputStream(
                "Test\\src\\file\\person.data"
        ));
        //读取相应的字节数组转换成对应的对象---反序列化
        Person p=(Person)o.readObject();
        //关流
        o.close();
        //输出
        System.out.println(p);
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343