关于Android文件的那些事

前言

在了解Android文件相关知识前,先来了解下Android文件相关常用的API

Log.i("相关API调用", "=======Environment调用=======\n"
                + "getRootDirectory = " + Environment.getRootDirectory().getPath() + "\n"
                + "getDownloadCacheDirectory = " + Environment.getDownloadCacheDirectory().getPath() + "\n"
                + "getDataDirectory = " + Environment.getDataDirectory().getPath() + "\n"
                + "getExternalStorageDirectory = " + Environment.getExternalStorageDirectory().getPath() + "\n"
                + "getExternalStoragePublicDirectory = " + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS).getPath() + "\n"
                + "getExternalStoragePublicDirectory = " + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_ALARMS).getPath() + "\n"
                + "getExternalStoragePublicDirectory = " + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).getPath() + "\n"
                + "getExternalStoragePublicDirectory = " + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES).getPath() + "\n"
                + "getExternalStoragePublicDirectory = " + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC).getPath() + "\n"
                + "getExternalStoragePublicDirectory = " + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath() + "\n"
                + "getExternalStoragePublicDirectory = " + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_NOTIFICATIONS).getPath() + "\n"
                + "getExternalStoragePublicDirectory = " + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getPath() + "\n"
                + "getExternalStoragePublicDirectory = " + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PODCASTS).getPath() + "\n"
                + "getExternalStoragePublicDirectory = " + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_RINGTONES).getPath() + "\n"
                + "=======Environment调用结束=======\n \n"
                + "=======Context调用出的目录=======\n"
                + "getCacheDir = " + getCacheDir().getPath() + "\n"
                + "getDataDir = " + getDataDir().getPath() + "\n"//Android7.0
                + "getFilesDir = " + getFilesDir().getPath() + "\n"
                + "getExternalMediaDirs = " + Arrays.toString(getExternalMediaDirs()) + "\n"
                + "getExternalCacheDir = " + getExternalCacheDir() + "\n"
                + "getExternalCacheDirs = " + Arrays.toString(getExternalCacheDirs()) + "\n"
                + "getExternalFilesDir = " + getExternalFilesDir(null) + "\n"
                + "getExternalFilesDirs = " + Arrays.toString(getExternalFilesDirs(null)) + "\n"
                + "getExternalFilesDir = " + getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS).getPath() + "\n"
                + "getExternalFilesDir = " + getExternalFilesDir(Environment.DIRECTORY_ALARMS).getPath() + "\n"
                + "getExternalFilesDir = " + getExternalFilesDir(Environment.DIRECTORY_DCIM).getPath() + "\n"
                + "getExternalFilesDir = " + getExternalFilesDir(Environment.DIRECTORY_MOVIES).getPath() + "\n"
                + "getExternalFilesDir = " + getExternalFilesDir(Environment.DIRECTORY_MUSIC).getPath() + "\n"
                + "getExternalFilesDir = " + getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).getPath() + "\n"
                + "getExternalFilesDir = " + getExternalFilesDir(Environment.DIRECTORY_NOTIFICATIONS).getPath() + "\n"
                + "getExternalFilesDir = " + getExternalFilesDir(Environment.DIRECTORY_PICTURES).getPath() + "\n"
                + "getExternalFilesDir = " + getExternalFilesDir(Environment.DIRECTORY_PODCASTS).getPath() + "\n"
                + "getExternalFilesDir = " + getExternalFilesDir(Environment.DIRECTORY_RINGTONES).getPath() + "\n"
                + "=======Context调用出的目录结束=======\n");

输出如下:

I/相关API调用: =======Environment调用=======
    getRootDirectory = /system
    getDownloadCacheDirectory = /data/cache
    getDataDirectory = /data
    getExternalStorageDirectory = /storage/emulated/0
    getExternalStoragePublicDirectory = /storage/emulated/0/Documents
    getExternalStoragePublicDirectory = /storage/emulated/0/Alarms
    getExternalStoragePublicDirectory = /storage/emulated/0/DCIM
    getExternalStoragePublicDirectory = /storage/emulated/0/Movies
    getExternalStoragePublicDirectory = /storage/emulated/0/Music
    getExternalStoragePublicDirectory = /storage/emulated/0/Download
    getExternalStoragePublicDirectory = /storage/emulated/0/Notifications
    getExternalStoragePublicDirectory = /storage/emulated/0/Pictures
    getExternalStoragePublicDirectory = /storage/emulated/0/Podcasts
    getExternalStoragePublicDirectory = /storage/emulated/0/Ringtones
    =======Environment调用结束=======
     
    =======Context调用出的目录=======
    getCacheDir = /data/user/0/com.xxx.xxxxx/cache
    getDataDir = /data/user/0/com.xxx.xxxxx
    getFilesDir = /data/user/0/com.xxx.xxxxx/files
    getExternalMediaDirs = [/storage/emulated/0/Android/media/com.xxx.xxxxx]
    getExternalCacheDir = /storage/emulated/0/Android/data/com.xxx.xxxxx/cache
    getExternalCacheDirs = [/storage/emulated/0/Android/data/com.xxx.xxxxx/cache]
    getExternalFilesDir = /storage/emulated/0/Android/data/com.xxx.xxxxx/files
    getExternalFilesDirs = [/storage/emulated/0/Android/data/com.xxx.xxxxx/files]
    getExternalFilesDir = /storage/emulated/0/Android/data/com.xxx.xxxxx/files/Documents
    getExternalFilesDir = /storage/emulated/0/Android/data/com.xxx.xxxxx/files/Alarms
    getExternalFilesDir = /storage/emulated/0/Android/data/com.xxx.xxxxx/files/DCIM
    getExternalFilesDir = /storage/emulated/0/Android/data/com.xxx.xxxxx/files/Movies
    getExternalFilesDir = /storage/emulated/0/Android/data/com.xxx.xxxxx/files/Music
    getExternalFilesDir = /storage/emulated/0/Android/data/com.xxx.xxxxx/files/Download
    getExternalFilesDir = /storage/emulated/0/Android/data/com.xxx.xxxxx/files/Notifications
    getExternalFilesDir = /storage/emulated/0/Android/data/com.xxx.xxxxx/files/Pictures
    getExternalFilesDir = /storage/emulated/0/Android/data/com.xxx.xxxxx/files/Podcasts
    getExternalFilesDir = /storage/emulated/0/Android/data/com.xxx.xxxxx/files/Ringtones
    =======Context调用出的目录结束=======

1、获取文件夹、文件和Uri

1.1、Android7.0前

在Android6.0之前和Android6.0之后,只是获取文件需要增加一个读取权限的区别而已

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

而获取文件目录都是如下

Environment.getExternalStorageDirectory().getPath()+"子目录";
//或者
Environment.getExternalStoragePublicDirectory(String type).getPath()+"子目录";

//若想要取以上文件夹中的其他文件夹或者文件,则在后面拼接即可,如下
String testFileTest = Environment.getExternalStoragePublicDirectory(String type).getPath()+File.separator+"test(.文件后缀)";

获取文件Uri
Uri uri = Uri.fromFile(file);

1.2、Android7.0后

Android7.0和Android7.0之后,获取文件目录的方式跟Android7.0之前没什么区别
只不过要在Manifest.xml文件中增加FileProvider配置,否则取不到File,并且不能再直接通过File方式获取文件输入输出流对文件进行读写和其他操作

<!--FileProvider-->
<provider
        android:name="androidx.core.content.FileProvider"
        android:authorities="com.test.provider.xxxxxx"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/public_file_path" />
</provider>

上面android:authorities="com.test.provider.xxxxxx"的内容为com.test.provider.xxxxxx,一般情况下,android:authorities的值为包名+其他,这个值关系到后面如何获取文件的Uri

//获取外部存储空间目录及其子文件夹目录下的文件夹和文件的Uri,即通过Environment.getXXXDir获取到的目录和文件获取Uri的方式
Uri uri = FileProvider.getUriForFile(this, getPackageName(), file);
//如果android:authorities的值不止有包名,则获取方式为
Uri uri = FileProvider.getUriForFile(this, getPackageName()+"其他", file);

//而Context调出的目录,例如getExternalCacheDir()目录下用这种方式取得Uri
Uri uri = Uri.fromFile(file);

//得到uri之后才可以根据Uri得到输入输出流对文件进行操作
InputStream inputStream = context.getContentResolver().openInputStream(uri);
OutputStream outputStream = context.getContentResolver().openOutputStream(uri);

到这里为止,根据以上的所得Android7.0前和Android7.0及之后,在获取外部存储空间Uri时的兼容代码可以如下

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    Uri uri = FileProvider.getUriForFile(this, getPackageName()+"其他", file);
} else {
    Uri uri = Uri.fromFile(file);           
}

而Context调出的目录,例如getExternalCacheDir()目录下文件的Uri获取方式则不变

1.3、Android Q后

Android Q 在外部存储设备中为每个应用提供了一个“隔离存储沙盒”(例如 /sdcard)。任何其他应用都无法直接访问您应用的沙盒文件。自己本应用访问自己保存在沙盒中的文件属于私有,所以访问不需要任何权限。如果需要访问系统媒体文件,需要申请新的媒体权限:READ_MEDIA_IMAGES,READ_MEDIA_VIDEO,READ_MEDIA_AUDIO
对于Android Q来说,沙盒还算是刚开始,所以官方的限制也没那么严格,可以通过在<application>中配置android:requestLegacyExternalStorage="true",那么同样能访问系统的相关媒体文件
对于沙盒存储,文件存放都要存放到对应的位置,如一张图片要放到
getExternalFilesDir(Environment.DIRECTORY_PICTURES)当中,若getExternalFilesDir(Environment.DIRECTORY_PICTURES)为空,则放到
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)当中,这样能将对应类型的文件放到对应的文件目录下,不至于乱放

理解:沙盒存储,就是将对应的文件类型,放到对应的目录或者Android/data/对应的包名文件当中去

1.3.1、获取Uri

对于Android Q来说,设置了android:requestLegacyExternalStorage="true"依然可以跟之前一样,存放文件并没有一定要求完全沙盒存储
Android Q以下或者Android Q设置了android:requestLegacyExternalStorage="true",依然可以在Environment.getExternalStorageDirectory().getPath();目录下存放文件和操作文件

//Uri获取
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    Uri uri = FileProvider.getUriForFile(this, getPackageName()+"其他", file);
} else {
    Uri uri = Uri.fromFile(file);           
}

若无设置android:requestLegacyExternalStorage或者大于Android Q来说,则必须按照完全沙盒存储

//文件存储和操作目录必须放于该公共目录下
Environment.getExternalStoragePublicDirectory(String type).getPath();
//或者私有存储
getExternalFilesDir(String type).getPath()

//Uri获取
Uri uri = Uri.fromFile(file);        

2、创建文件夹

2.1、创建文件夹和其子目录

if(!file.exists()){
    file.mkdirs();
}

2.2、创建单一文件夹

if(!file.exists()){
    file.mkdir();
}

3、获取文件输入输出流

3.1、根据Uri获取输入输出流

InputStream inputStream = context.getContentResolver().openInputStream(uri);
OutputStream outputStream = context.getContentResolver().openOutputStream(uri);

3.2、根据File获取输入输出流

根据File获取输入输出流是有前提的,那就是文件路径必须对
这个前提看似很简单,但是根据以上说的版本差异,经常会出现兼容未做好而导致通过File获取输入输出流或者对文件进行操作时,提示:FileNotFoundException: open failed: EPERM (Operation not permitted)
所以必须根据版本差异,是使用非沙盒存储还是沙盒存储,这点是必须要注意的

File file = new File(path);
//path一定,一定,一定要根据是否沙盒确定好存放路径,并且申请相关权限
InputStream inputStream = new FileInputStream(file);
OutputStream outputStream = new FileOutputStream(file);

4、FileProvider配置

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <!--1、对应内部内存卡根目录:Context.getFileDir()/com.xxx.xxx-->
    <files-path
        name="int_root"
        path="com.xxx.xxx/" />
    <!--2、对应应用默认缓存根目录:Context.getCacheDir()/com.xxx.xxx-->
    <cache-path
        name="app_cache"
        path="com.xxx.xxx/" />
    <!--3、对应外部内存卡根目录:Environment.getExternalStorageDirectory()/com.xxx.xxx-->
    <external-path
        name="ext_root"
        path="com.xxx.xxx/" />
    <!--4、对应外部内存卡根目录下的APP公共目录:Context.getExternalFileDir(String)/com.xxx.xxx-->
    <external-files-path
        name="ext_pub"
        path="com.xxx.xxx/" />
    <!--5、对应外部内存卡根目录下的APP缓存目录:Context.getExternalCacheDir()/com.xxx.xxx-->
    <external-cache-path
        name="ext_cache"
        path="com.xxx.xxx/" />
</paths>

5、copy文件

    /**
     * 复制文件
     * @param context 上下文对象
     * @param sourceUri 被复制文件的Uri
     * @param savePath 粘贴路径
     * @return 返回File
     */
    public static File copyFile(Context context, Uri sourceUri, String savePath) {
        InputStream inputStream = null;
        OutputStream fos = null;
        try {
            inputStream = context.getContentResolver().openInputStream(sourceUri);
            String path = sourceUri.getPath();
            if (path == null) {
                return null;
            }
            int i = path.lastIndexOf("/") + 1;
            String substring = path.substring(i);
            File directory = new File(savePath);
            if (!directory.exists()) {
                directory.mkdirs();
            }
            File file = new File(savePath, substring);
            if (file.exists()) {
                if (inputStream != null) {
                    inputStream.close();
                }
                return file;
            }
            fos = new FileOutputStream(file);
//            long sum = 0;
            byte[] buf = new byte[2048];
            int len;
            while (inputStream != null && (len = inputStream.read(buf)) != -1) {
                fos.write(buf, 0, len);
//                sum += len;
            }
            fos.flush();
            return file;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

使用

File file;
Uri uri;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
    //想放到公共目录,理论上可被复制的文件也可被访问,故而大多情况下复制到沙盒公共目录下是多余的
    file = FileUtils.copyFile(this, uri,
            Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS).getPath()
                    + File.separator + Env.DIR_PUBLIC);
    //或者放到私有目录沙盒
    file = FileUtils.copyFile(this, uri,
            getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS).getPath()
                    + File.separator + Env.DIR_PUBLIC);

    uri = Uri.fromFile(file);
} else {
    file = FileUtils.copyFile(this, uri,Environment.getExternalStorageDirectory().getPath()+ File.separator + Env.DIR_PUBLIC);

    uri = FileProvider.getUriForFile(this, getPackageName() + "其他", file);
}

6、根据路径路径以合适的程序打开文件

//建立一个文件类型与文件后缀名的匹配表
    private static final String[][] MIME_MapTable = {
            //{后缀名, MIME类型}
            {".3gp", "video/3gpp"},
            {".apk", "application/vnd.android.package-archive"},
            {".asf", "video/x-ms-asf"},
            {".avi", "video/x-msvideo"},
            {".bin", "application/octet-stream"},
            {".bmp", "image/bmp"},
            {".c", "text/plain"},
            {".class", "application/octet-stream"},
            {".conf", "text/plain"},
            {".cpp", "text/plain"},
            {".doc", "application/msword"},
            {".docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"},
            {".xls", "application/vnd.ms-excel"},
            {".xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"},
            {".exe", "application/octet-stream"},
            {".gif", "image/gif"},
            {".gtar", "application/x-gtar"},
            {".gz", "application/x-gzip"},
            {".h", "text/plain"},
            {".htm", "text/html"},
            {".html", "text/html"},
            {".jar", "application/java-archive"},
            {".java", "text/plain"},
            {".jpeg", "image/jpeg"},
            {".jpg", "image/jpeg"},
            {".js", "application/x-javascript"},
            {".log", "text/plain"},
            {".m3u", "audio/x-mpegurl"},
            {".m4a", "audio/mp4a-latm"},
            {".m4b", "audio/mp4a-latm"},
            {".m4p", "audio/mp4a-latm"},
            {".m4u", "video/vnd.mpegurl"},
            {".m4v", "video/x-m4v"},
            {".mov", "video/quicktime"},
            {".mp2", "audio/x-mpeg"},
            {".mp3", "audio/x-mpeg"},
            {".mp4", "video/mp4"},
            {".mpc", "application/vnd.mpohun.certificate"},
            {".mpe", "video/mpeg"},
            {".mpeg", "video/mpeg"},
            {".mpg", "video/mpeg"},
            {".mpg4", "video/mp4"},
            {".mpga", "audio/mpeg"},
            {".msg", "application/vnd.ms-outlook"},
            {".ogg", "audio/ogg"},
            {".pdf", "application/pdf"},
            {".png", "image/png"},
            {".pps", "application/vnd.ms-powerpoint"},
            {".ppt", "application/vnd.ms-powerpoint"},
            {".pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation"},
            {".prop", "text/plain"},
            {".rc", "text/plain"},
            {".rmvb", "audio/x-pn-realaudio"},
            {".rtf", "application/rtf"},
            {".sh", "text/plain"},
            {".tar", "application/x-tar"},
            {".tgz", "application/x-compressed"},
            {".txt", "text/plain"},
            {".wav", "audio/x-wav"},
            {".wma", "audio/x-ms-wma"},
            {".wmv", "audio/x-ms-wmv"},
            {".wps", "application/vnd.ms-works"},
            {".xml", "text/plain"},
            {".z", "application/x-compress"},
            {".zip", "application/x-zip-compressed"},
            {"", "*/*"}
    };

/**
     * 根据路径打开文件
     *
     * @param context 上下文
     * @param path    文件路径
     */
    public static void openFileByPath(Context context, String path) {
        try {
            Intent intent = new Intent();
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            //设置intent的Action属性
            intent.setAction(Intent.ACTION_VIEW);
            File file = new File(path);
            //获取文件file的MIME类型
            String type = getMIMEType(file);
            //设置intent的data和Type属性。android 7.0以上crash,改用provider
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                Uri fileUri = FileProvider.getUriForFile(context, context.getPackageName() + ".provider", file);//android 7.0以上
                intent.setDataAndType(fileUri, type);
                grantUriPermission(context, fileUri, intent);
            } else {
                intent.setDataAndType(/*uri*/Uri.fromFile(file), type);
            }
            //跳转
            context.startActivity(intent);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static String getMIMEType(File file) {

        String type = "*/*";
        String fName = file.getName();
        //获取后缀名前的分隔符"."在fName中的位置。
        int dotIndex = fName.lastIndexOf(".");
        if (dotIndex < 0) {
            return type;
        }
        /* 获取文件的后缀名 */
        String end = fName.substring(dotIndex).toLowerCase();
        if (end.equals("")) return type;
        //在MIME和文件类型的匹配表中找到对应的MIME类型。
        for (int i = 0; i < MIME_MapTable.length; i++) { //MIME_MapTable??在这里你一定有疑问,这个MIME_MapTable是什么?
            if (end.equals(MIME_MapTable[i][0]))
                type = MIME_MapTable[i][1];
        }
        return type;
    }

    private static void grantUriPermission(Context context, Uri fileUri, Intent intent) {
        List<ResolveInfo> resInfoList = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
        for (ResolveInfo resolveInfo : resInfoList) {
            String packageName = resolveInfo.activityInfo.packageName;
            context.grantUriPermission(packageName, fileUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
        }
    }

7、根据Uri得到文件路径

    /**
     * 根据公共存储目录文件Uri得到文件路径
     * @param context 上下文对象
     * @param uri 需要查找文件的Uri
     * @return 返回路径
     */
    public static String getPath(final Context context, final Uri uri) {
        // DocumentProvider
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && DocumentsContract.isDocumentUri(context, uri)) {
            // ExternalStorageProvider
            if (isExternalStorageDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

                if ("primary".equalsIgnoreCase(type)) {
                    return Environment.getExternalStorageDirectory() + "/" + split[1];
                }
            }
            // DownloadsProvider
            else if (isDownloadsDocument(uri)) {

                final String id = DocumentsContract.getDocumentId(uri);
                final Uri contentUri = ContentUris.withAppendedId(
                        Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));

                return getDataColumn(context, contentUri, null, null);
            }
            // MediaProvider
            else if (isMediaDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

                Uri contentUri = null;
                if ("image".equals(type)) {
                    contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                } else if ("video".equals(type)) {
                    contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                } else if ("audio".equals(type)) {
                    contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                }

                final String selection = "_id=?";
                final String[] selectionArgs = new String[]{split[1]};

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

推荐阅读更多精彩内容