问题描述
我正在尝试将字符串(在内存中)与文件内容进行比较,以查看它们是否相同。关于动机的无聊细节在问题下方是否有人关心。
我的困惑是,当我对文件内容进行哈希处理时,得到的结果与对字符串进行哈希处理时的结果不同。
js
我想要做的只是 library(readr)
library(digest)
# write the string to the file
the_string <- "here is some stuff"
the_file <- "fake.txt"
readr::write_lines(the_string,the_file)
# both of these functions (predictably) give the same hash
tools::md5sum(the_file)
# "44b0350ee9f822d10f2f9ca7dbe54398"
digest(file = the_file)
# "44b0350ee9f822d10f2f9ca7dbe54398"
# Now read it back to a string and get something different
back_to_a_string <- readr::read_file(the_file)
# "here is some stuff\n"
digest(back_to_a_string)
# "03ed1c8a2b997277100399bef6f88939"
# add a newline because that's what write_lines did
orig_with_newline <- paste0(the_string,"\n")
# "here is some stuff\n"
digest(orig_with_newline)
# "03ed1c8a2b997277100399bef6f88939"
看看它们是否相同(它们是)但是返回 digest(orig_with_newline) == digest(file = the_file)
因为,如图所示,散列是不一样。
显然,我可以使用 FALSE
将文件读回字符串或将字符串写入临时文件,但这两种方法看起来都有些愚蠢和笨拙。我想这两个实际上都是很好的解决方案,我真的只是想了解为什么会发生这种情况,以便我可以更好地了解散列的工作原理。
关于动机的无聊细节
情况是我有一个函数可以将字符串写入文件,但是如果文件已经存在,那么除非用户明确传递read_file
,否则它将出错。但是,如果文件存在,我想检查即将写入文件的字符串是否实际上与文件中已有的相同。如果是这种情况,那么我将跳过错误(和写入)。可以在循环中调用此代码,如果用户不断看到此错误,即他们即将使用已在其中的相同内容覆盖文件,这将是令人讨厌的。
解决方法
简短回答:我认为您需要设置 serialize=FALSE
。假设文件不包含额外的换行符(见下文),
digest(the_string,serialize=FALSE) == digest(file=the_file) ## TRUE
(serialize
对命令的 file=
版本没有影响)
处理换行符
如果你读?write_lines
,它只会说
sep: 行分隔符 ... [关于不同操作系统的默认值的信息]
对我来说,这对于是否在最后一行之后添加分隔符似乎不明确。 (您不希望“逗号分隔列表”以逗号结束 ...)
另一方面,?base::writeLines
更明确一些,
sep:字符串。要写入连接的字符串 在每行文本之后。
如果您深入研究 source code of readr,您会发现它使用了
output << na << sep;
对于每一行代码,即它的行为方式与 writeLines
相同。
如果您真的只想将字符串写入文件而不添加任何废话,我建议cat()
:
identical(the_string,{ cat(the_string,file=the_file); readr::read_file(the_file) }) ## TRUE