第6笔记 nodejs 文件系统-2

文件系统模块是一个封装了标准的 POSIX 文件 I/O 操作的集合。通过require('fs')使用这个模块。所有的方法都有同步和异步两种模式。

异步方法最后一个参数都是回调函数,这个回调的参数取决于方法,不过第一个参数一般都是异常。如果操作成功,那么第一个参数就是null或undefined。

当使用一个同步操作的时候,任意的异常都立即抛出,可以用 try/catch 来处理异常,使得程序正常运行。

这是异步操作的例子:

var fs = require('fs');

fs.unlink('/tmp/hello', function (err) {

if (err) throw err;

console.log('successfully deleted /tmp/hello');

});

这是同步操作的例子:

var fs = require('fs');

fs.unlinkSync('/tmp/hello');

console.log('successfully deleted /tmp/hello');

异步方法不能保证操作顺序,因此下面的例子很容易出错:

fs.rename('/tmp/hello', '/tmp/world', function (err) {

if (err) throw err;

console.log('renamed complete');

});

fs.stat('/tmp/world', function (err, stats) {

if (err) throw err;

console.log('stats: ' + JSON.stringify(stats));

});

可能先执行了fs.stat方法。正确的方法:

fs.rename('/tmp/hello', '/tmp/world', function (err) {

if (err) throw err;

fs.stat('/tmp/world', function (err, stats) {

if (err) throw err;

console.log('stats: ' + JSON.stringify(stats));

});

});

在繁忙的进程里,强烈建议使用异步方法。同步方法会阻塞整个进程,直到方法完成。

可能会用到相对路径,路径是相对process.cwd()来说的。

大部分 fs 函数会忽略回调参数,如果忽略,将会用默认函数抛出异常。如果想得到原调用点的堆栈信息,需要设置环境变量 NODE_DEBUG;

$ cat script.js

function bad() {

require('fs').readFile('/');

}

bad();

$ env NODE_DEBUG=fs node script.js

fs.js:66

throw err;

^

Error: EISDIR, read

at rethrow (fs.js:61:21)

at maybeCallback (fs.js:79:42)

at Object.fs.readFile (fs.js:153:18)

at bad (/path/to/script.js:2:17)

at Object. (/path/to/script.js:5:1)

fs.rename(oldPath, newPath, callback)

异步函数 rename(2)。回调函数只有一个参数:可能出现的异常。

fs.renameSync(oldPath, newPath)

同步函数 rename(2)。 返回undefined。

fs.ftruncate(fd, len, callback)

异步函数 ftruncate(2)。 回调函数只有一个参数:可能出现的异常。

fs.ftruncateSync(fd, len)

同步函数 ftruncate(2)。 返回undefined。

fs.truncate(path, len, callback)

异步函数 truncate(2)。 回调函数只有一个参数:可能出现的异常。 文件描述符也可以作为第一个参数,如果这种情况,调用fs.ftruncate()。

fs.truncateSync(path, len)

同步函数 truncate(2)。 返回undefined。

fs.chown(path, uid, gid, callback)

异步函数 chown(2)。 回调函数只有一个参数:可能出现的异常。

fs.chownSync(path, uid, gid)

同步函数 chown(2)。 返回undefined。

fs.fchown(fd, uid, gid, callback)

异步函数 fchown(2)。 回调函数只有一个参数:可能出现的异常。

fs.fchownSync(fd, uid, gid)

同步函数 fchown(2)。 返回undefined。

fs.lchown(path, uid, gid, callback)

异步函数 lchown(2)。 回调函数只有一个参数:可能出现的异常。

fs.lchownSync(path, uid, gid)

同步函数 lchown(2)。 返回undefined。

fs.chmod(path, mode, callback)

异步函数 chmod(2)。回调函数只有一个参数:可能出现的异常。

fs.chmodSync(path, mode)

同步函数 chmod(2)。 返回undefined。

fs.fchmod(fd, mode, callback)

异步函数 fchmod(2)。 回调函数只有一个参数:可能出现的异常。

fs.fchmodSync(fd, mode)

同步函数 fchmod(2)。 返回undefined。

fs.lchmod(path, mode, callback)

异步函数 lchmod(2)。 回调函数只有一个参数:可能出现的异常。

仅在 Mac OS X 可用。

fs.lchmodSync(path, mode)

同步函数 lchmod(2)。 返回undefined。

fs.stat(path, callback)

异步函数 stat(2)。 回调函数有两个参数: (err, stats) ,其中stats是一个fs.Stats对象。 详情请参考 fs.Stats。

fs.lstat(path, callback)

异步函数 lstat(2)。 回调函数有两个参数: (err, stats) ,其中stats是一个fs.Stats对象。lstat()与stat()基本相同, 区别在于,如果path是链接,读取的是链接本身,而不是它所链接到的文件。

fs.fstat(fd, callback)

异步函数 fstat(2)。 回调函数有两个参数: (err, stats) ,其中stats是一个fs.Stats对象。

fs.statSync(path)

同步函数 stat(2)。 返回fs.Stats实例。

fs.lstatSync(path)

同步函数 lstat(2)。 返回fs.Stats实例。

fs.fstatSync(fd)

同步函数 fstat(2)。 返回fs.Stats实例。

fs.link(srcpath, dstpath, callback)

异步函数 link(2)。 回调函数只有一个参数:可能出现的异常。

fs.linkSync(srcpath, dstpath)

同步函数 link(2)。 返回undefined。

fs.symlink(srcpath, dstpath[, type], callback)

异步函数 symlink(2)。 回调函数只有一个参数:可能出现的异常。

type可能是'dir','file', 或'junction'(默认'file') ,仅在 Windows(不考虑其他系统)有效。注意, Windows junction 要求目的地址需要绝对的。当使用'junction'的时候,destination参数将会自动转换为绝对路径。

fs.symlinkSync(srcpath, dstpath[, type])

同步函数 symlink(2)。 返回undefined。

fs.readlink(path, callback)

异步函数 readlink(2)。 回调函数有2个参数(err, linkString).

fs.readlinkSync(path)

同步函数 readlink(2)。 返回符号链接的字符串值。

fs.realpath(path[, cache], callback)

异步函数 realpath(2)。 回调函数有2个参数(err,resolvedPath)。可以使用process.cwd来解决相对路径问题。

例如:

var cache = {'/etc':'/private/etc'};

fs.realpath('/etc/passwd', cache, function (err, resolvedPath) {

if (err) throw err;

console.log(resolvedPath);

});

fs.realpathSync(path[, cache])

同步函数 realpath(2)。 返回解析出的路径。

fs.unlink(path, callback)

异步函数 unlink(2)。 回调函数只有一个参数:可能出现的异常.

fs.unlinkSync(path)

同步函数 unlink(2)。 返回undefined。

fs.rmdir(path, callback)

异步函数 rmdir(2)。 回调函数只有一个参数:可能出现的异常.

fs.rmdirSync(path)

同步函数 rmdir(2)。 返回undefined。

fs.mkdir(path[, mode], callback)

异步函数 mkdir(2)。 回调函数只有一个参数:可能出现的异常.mode默认s to0777.

fs.mkdirSync(path[, mode])

同步函数 mkdir(2)。 返回undefined。

fs.readdir(path, callback)

异步函数 readdir(3)。 读取文件夹的内容。回调有2个参数(err, files)files 是文件夹里除了名字为,'.'和'..'`之外的所有文件名。

fs.readdirSync(path)

同步函数 readdir(3)。 返回除了文件名为'.'和'..'之外的所有文件.

fs.close(fd, callback)

异步函数 close(2)。 回调函数只有一个参数:可能出现的异常.

fs.closeSync(fd)

同步函数 close(2)。 返回undefined。

fs.open(path, flags[, mode], callback)

异步函数 file open. 参见 open(2)。flags是:

'r'- 以只读模式打开.如果文件不存在,抛出异常。

'r+'-以读写模式打开.如果文件不存在,抛出异常。

'rs'- 同步的,以只读模式打开. 指令绕过操作系统直接使用本地文件系统缓存。 这个功能主要用来打开 NFS 挂载的文件,因为它能让你跳过可能过时的本地缓存。如果对 I/O 性能很在乎,就不要使用这个标志位。

这里不是调用fs.open()变成同步阻塞请求,如果你想要这样,可以调用fs.openSync()。

'rs+'- 同步模式下以读写方式打开文件。注意事项参见'rs'.

'w'- 以只写模式打开。文件会被创建 (如果文件不存在) 或者覆盖 (如果存在)。

'wx'- 和'w'类似,如果文件存储操作失败

'w+'- 以可读写方式打开。文件会被创建 (如果文件不存在) 或者覆盖 (如果存在)

'wx+'- 和'w+'类似,如果文件存储操作失败。

'a'- 以附加的形式打开。如果文件不存在则创建一个。

'ax'- 和'a'类似,如果文件存储操作失败。

'a+'- 以只读和附加的形式打开文件.若文件不存在,则会建立该文件

'ax+'- 和'a+'类似,如果文件存储操作失败.

如果文件存在,参数mode设置文件模式 (permission 和 sticky bits)。 默认是0666, 可读写.

回调有2个参数(err, fd).

排除标记'x'(对应 open(2)的O_EXCL标记) 保证path是新创建的。在 POSIX 系统里,即使文件不存在,也会被认定为文件存在。 排除标记不能确定在网络文件系统中是否有效。

Linux系统里,无法对以追加模式打开的文件进行指定位置写。系统核心忽略了位置参数,每次把数据写到文件的最后。

fs.openSync(path, flags[, mode])

fs.open()的同步版本. 返回整数形式的文件描述符。.

fs.utimes(path, atime, mtime, callback)

改变指定路径文件的时间戳。

fs.utimesSync(path, atime, mtime)

fs.utimes()的同步版本. 返回undefined。

fs.futimes(fd, atime, mtime, callback)

改变传入的文件描述符指向文件的时间戳。

fs.futimesSync(fd, atime, mtime)

fs.futimes()的同步版本. 返回undefined。

fs.fsync(fd, callback)

异步函数 fsync(2)。 回调函数只有一个参数:可能出现的异常.

fs.fsyncSync(fd)

同步 fsync(2)。 返回undefined。

fs.write(fd, buffer, offset, length[, position], callback)

将buffer写到fd指定的文件里。

参数offset和length确定写哪个部分的缓存。

参数position是要写入的文件位置。如果typeof position !== 'number',将会在当前位置写入。参见 pwrite(2)。

回调函数有三个参数(err, written, buffer),written指定buffer的多少字节用来写。

注意,如果fs.write的回调还没执行,就多次调用fs.write,这样很不安全。因此,推荐使用fs.createWriteStream。

Linux系统里,无法对以追加模式打开的文件进行指定位置写。系统核心忽略了位置参数,每次把数据写到文件的最后。

fs.write(fd, data[, position[, encoding]], callback)

将buffer写到fd指定的文件里。如果data不是 buffer,那么它就会被强制转换为字符串。

参数position是要写入的文件位置。如果typeof position !== 'number',将会在当前位置写入。参见 pwrite(2)。

参数encoding:字符串的编码方式.

回调函数有三个参数(err, written, buffer),written指定buffer的多少字节用来写。注意写入的字节(bytes)和字符(string characters)不同。参见Buffer.byteLength

和写入buffer不同,必须写入整个字符串,不能截取字符串。这是因为返回的字节的位移跟字符串的位移是不一样的。

注意,如果fs.write的回调还没执行,就多次调用fs.write,这样很不安全。因此,推荐使用fs.createWriteStream

Linux系统里,无法对以追加模式打开的文件进行指定位置写。系统核心忽略了位置参数,每次把数据写到文件的最后。

fs.writeSync(fd, buffer, offset, length[, position])

fs.writeSync(fd, data[, position[, encoding]])

fs.write()的同步版本. 返回要写的bytes数.

fs.read(fd, buffer, offset, length, position, callback)

读取fd指定文件的数据。

buffer是缓冲区,数据将会写入到这里.

offset写入的偏移量

length需要读的文件长度

position读取的文件起始位置,如果是position是null, 将会从当前位置读。

回调函数有3个参数,(err, bytesRead, buffer).

fs.readSync(fd, buffer, offset, length, position)

fs.read的同步版本. 返回bytesRead的数量.

fs.readFile(filename[, options], callback)

filename{String}

options{Object}

encoding{String | Null} 默认 =null

flag{String} 默认 ='r'

callback{Function}

异步读取整个文件的内容。例如:

fs.readFile('/etc/passwd', function (err, data) {

if (err) throw err;

console.log(data);

});

回调函数有2个参数(err, data), 参数data是文件的内容。 如果没有指定参数encoding, 返回原生 buffer

fs.readFileSync(filename[, options])

fs.readFile的同步版本. 返回整个文件的内容.

如果没有指定参数encoding, 返回buffer。

fs.writeFile(filename, data[, options], callback)

filename{String}

data{String | Buffer}

options{Object}

encoding{String | Null} 默认 ='utf8'

mode{Number} 默认 =438(aka0666in Octal)

flag{String} 默认 ='w'

callback{Function}

异步写文件,如果文件已经存在则替换。data可以是缓存或者字符串。

如果参数data是 buffer,会忽略参数encoding。默认值是'utf8'。

列如:

fs.writeFile('message.txt', 'Hello Node', function (err) {

if (err) throw err;

console.log('It\'s saved!');

});

fs.writeFileSync(filename, data[, options])

fs.writeFile的同步版本. 返回undefined。

fs.appendFile(filename, data[, options], callback)

filename{String}

data{String | Buffer}

options{Object}

encoding{String | Null} 默认 ='utf8'

mode{Number} 默认 =438(aka0666in Octal)

flag{String} 默认 ='a'

callback{Function}

异步的给文件添加数据,如果文件不存在,就创建一个。data可以是缓存或者字符串。

例如:

fs.appendFile('message.txt', 'data to append', function (err) {

if (err) throw err;

console.log('The "data to append" was appended to file!');

});

fs.appendFileSync(filename, data[, options])

fs.appendFile的同步版本. 返回undefined。

fs.watchFile(filename[, options], listener)

稳定性: 2 - 不稳定。  尽可能的用 fs.watch 来替换。

监视filename文件的变化。每当文件被访问的时候都会调用listener。

第二个参数可选。如果有,它必须包含两个 boolean 参数(persistent和interval)的对象。persistent指定文件被监视时进程是否继续运行。interval指定了查询文件的间隔,以毫秒为单位。缺省值为{ persistent: true, interval: 5007 }。

listener 有两个参数,第一个为文件现在的状态,第二个为文件的前一个状态:

fs.watchFile('message.text', function (curr, prev) {

console.log('the current mtime is: ' + curr.mtime);

console.log('the previous mtime was: ' + prev.mtime);

});

listener中的文件状态对象类型为 fs.Stat。

如果想修改文件时被通知,而不是访问的时候就通知,可以比较curr.mtime和prev.mtime。

fs.unwatchFile(filename[, listener])

稳定性: 2 - 不稳定. 尽可能的用 fs.watch 来替换。

停止监视filename文件的变化。如果指定了listener,那只会移除这个listener。否则,移除所有的 listener,并会停止监视filename。

调用fs.unwatchFile()停止监视一个没被监视的文件,不会触发错误,而会发生一个no-op。

fs.watch(filename[, options][, listener])

稳定性: 2 - 不稳定.

观察filename指定的文件或文件夹的改变。返回对象是fs.FSWatcher

第二个参数可选。如果有,它必须是包含两个 boolean 参数(persistent和recursive)的对象。persistent指定文件被监视时进程是否继续运行。recursive表明是监视所有的子文件夹还是当前文件夹,这个参数只有监视对象是文件夹时才有效,而且仅在支持的系统里有效(参见下面注意事项)。

默认值{ persistent: true, recursive: false }.

回调函数有2个参数(event, filename)。event是rename或change。filename是触发事件的文件名。

注意事项

fs.watchAPI 不是 100% 的跨平台兼容,可能在某些情况下不可用。

recursive参数仅在 OS X 上可用。仅FSEvents支持这个类型文件的监视,所以未来也不太可能有新的平台加入。

可用性

这些特性依赖于底层系统提供文件系统变动的通知。

Linux 系统,使用inotify.

BSD 系统,使用kqueue.

OS X,文件使用kqueue,文件夹使用FSEvents.

SunOS 系统(包括 Solaris 和 SmartOS),使用event ports.

Windows 系统, 依赖与ReadDirectoryChangesW.

如果底层系统函数不可用,那么fs.watch就无法工作。例如,监视网络文件系统(NFS, SMB, 等)经常不能用。你仍然可以用fs.watchFile查询,但是会比较慢,且不可靠。

文件名参数

回调函数中提供文件名参数,不是每个平台都能用(Linux 和 Windows 就不行)。即使在可用的平台,也不能保证都能提供。所以不要假设回调函数中filename参数有效,要在代码里添加一些为空的逻辑判断。

fs.watch('somedir', function (event, filename) {

console.log('event is: ' + event);

if (filename) {

console.log('filename provided: ' + filename);

} else {

console.log('filename not provided');

}

});

fs.exists(path, callback)

判断文件是否存在,回调函数参数是 bool 值。例如:

fs.exists('/etc/passwd', function (exists) {

util.debug(exists ? "it's there" : "no passwd!");

});

fs.exists()是老版本的函数,因此在代码里不要用。

另外,打开文件前判断是否存在有漏洞,在fs.exists()和fs.open()调用中间,另外一个进程有可能已经移除了文件。最好用fs.open()来打开文件,根据回调函数来判断是否有错误。

fs.exists()未来会被移除。

fs.existsSync(path)

fs.exists()的同步版本. 如果文件存在返回true, 否则返回false。

fs.existsSync()未来会被移除。

fs.access(path[, mode], callback)

测试由参数path指向的文件的用户权限。可选参数mode为整数,它表示需要检查的权限。下面列出了所有值。mode可以是单个值,或者可以通过或运算,掩码运算实现多个权限检查。

fs.F_OK- 文件是对于进程可见,可以用来检查文件是否存在。参数mode的默认值。

fs.R_OK- 文件对于进程是否可读。

fs.W_OK- 文件对于进程是否可写。

fs.X_OK- 文件对于进程是否可执行。(Windows系统不可用,执行效果等同fs.F_OK)

第三个参数是回调函数。如果检查失败,回调函数的参数就是响应的错误。下面的例子检查文件/etc/passwd是否能被当前的进程读写。

fs.access('/etc/passwd', fs.R_OK | fs.W_OK, function(err) {

util.debug(err ? 'no access!' : 'can read/write');

});

fs.accessSync(path[, mode])

fs.access的同步版本. 如果发生错误抛出异常,否则不做任何事情。

类: fs.Stats

fs.stat(),fs.lstat()和fs.fstat()以及同步版本的返回对象。

stats.isFile()

stats.isDirectory()

stats.isBlockDevice()

stats.isCharacterDevice()

stats.isSymbolicLink()(only valid withfs.lstat())

stats.isFIFO()

stats.isSocket()

对普通文件使用util.inspect(stats),返回的字符串和下面类似:

{ dev: 2114,

ino: 48064969,

mode: 33188,

nlink: 1,

uid: 85,

gid: 100,

rdev: 0,

size: 527,

blksize: 4096,

blocks: 8,

atime: Mon, 10 Oct 2011 23:24:11 GMT,

mtime: Mon, 10 Oct 2011 23:24:11 GMT,

ctime: Mon, 10 Oct 2011 23:24:11 GMT,

birthtime: Mon, 10 Oct 2011 23:24:11 GMT }

atime,mtime,birthtime, 和ctime都是Date的实例,需要使用合适的方法来比较这些值。通常使用getTime()来获取时间戳(毫秒,从1 January 1970 00:00:00 UTC开始算),这个整数基本能满足任何比较条件。也有一些其他方法来显示额外信息。更多参见MDN JavaScript Reference

Stat Time Values

状态对象(stat object)有以下语义:

atime访问时间 - 文件的最后访问时间.mknod(2),utimes(2), 和read(2)等系统调用可以改变.

mtime修改时间 - 文件的最后修改时间.mknod(2),utimes(2), 和write(2)等系统调用可以改变.

ctime改变时间 - 文件状态(inode)的最后修改时间.chmod(2),chown(2),link(2),mknod(2),rename(2),unlink(2),utimes(2),read(2), 和write(2)等系统调用可以改变.

birthtime"Birth Time" - 文件创建时间,文件创建时生成。 在一些不提供文件 birthtime 的文件系统中, 这个字段会使用 ctime 或 1970-01-01T00:00Z (ie, unix epoch timestamp 0)来填充。 在 Darwin 和其他 FreeBSD 系统变体中, 也将 atime 显式地设置成比它现在的 birthtime 更早的一个时间值,这个过程使用了 utimes(2) 系统调用。

在 Node v0.12 版本之前, Windows 系统里 ctime 有 birthtime 值. 注意在v.0.12版本中, ctime 不再是"creation time", 而且在Unix系统中,他一直都不是。

fs.createReadStream(path[, options])

返回可读流对象 (见Readable Stream)。

options默认值如下:

{ flags: 'r',

encoding: null,

fd: null,

mode: 0666,

autoClose: true

}

参数options提供start和end位置来读取文件的特定范围内容,而不是整个文件。start和end都在文件范围里,并从 0 开始,encoding是'utf8','ascii', 或'base64'。

如果给了fd值,ReadStream将会忽略path参数,而使用文件描述,这样不会触发任何open事件。

如果autoClose为 false,即使发生错误文件也不会关闭,需要你来负责关闭,避免文件描述符泄露。如果autoClose是 true(默认值),遇到error或end,文件描述符将会自动关闭。

例如,从100个字节的文件里,读取最少10个字节:

fs.createReadStream('sample.txt', {start: 90, end: 99});

Class: fs.ReadStream

ReadStream是Readable Stream

Event: 'open'

fd{Integer} ReadStream 所使用的文件描述符。

当创建文件的ReadStream时触发。

fs.createWriteStream(path[, options])

返回一个新的写对象 (参见Writable Stream)。

options是一个对象,默认值:

{ flags: 'w',

encoding: null,

fd: null,

mode: 0666 }

options 也可以包含一个 start 选项,在指定文件中写入数据开始位置。 修改而不替换文件需要 flags 的模式指定为 r+ 而不是默值的 w.

和之前的ReadStream类似,如果fd不为空,WriteStream将会忽略path参数,转而使用文件描述,这样不会触发任何open事件。

类: fs.WriteStream

WriteStream是Writable Stream

Event: 'open'

fd{Integer} WriteStream 所用的文件描述符

打开 WriteStream file 时触发。

file.bytesWritten

目前写入的字节数,不含等待写入的数据。

Class: fs.FSWatcher

fs.watch()返回的对象就是这个类.

watcher.close()

停止观察fs.FSWatcher对象中的更改。

Event: 'change'

event{String} fs 改变的类型

filename{String} 改变的文件名 (if relevant/available)

当监听的文件或文件夹改变的时候触发,参见fs.watch

Event: 'error'

error{Error object}

错误发生时触发。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念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

推荐阅读更多精彩内容