当前位置: 首页 > 面试题库 >

io.Copy()导致文件稀疏

祁宝
2023-03-14
问题内容

我想将文件从一个地方复制到另一个地方,问题是我处理了很多稀疏文件。

有什么(简单的)复制稀疏文件而不会在目标位置变得庞大的方法

我的基本代码

out, err := os.Create(bricks[0] + "/" + fileName)
in, err := os.Open(event.Name)
io.Copy(out, in)

问题答案:

一些背景理论

请注意,io.Copy()通过管道传输原始字节–一旦您认为将原始数据通过管道从io.Readerio.Writer提供Read([]byte)和的Write([]byte),就可以理解。这样,io.Copy()绝对可以处理提供字节的任何源以及使用它们的任何接收器。

另一方面,文件中漏洞的位置是“侧通道”信息,这些“侧通道”信息是“经典”系统调用,例如read(2)对用户隐藏。
io.Copy()不能以任何方式传达这种辅助信道信息。

IOW,最初,文件稀疏是一种仅在用户背后有效存储数据的想法。

因此,不,io.Copy()它本身无法处理稀疏文件。

该怎么办

您需要更深入一点,并使用该syscall软件包和一些手动修改来实现所有这些功能

要使用孔,应为syscall
使用SEEK_HOLESEEK_DATA特殊值lseek(2),尽管这在形式上是非标准的,但所有
主要
平台均支持。

不幸的是,库存syscall包(从Go
1.8.1开始)和目录golang.org/x/sys树中都不存在对那些“因此”位置的支持。

但是不要担心,有两个简单的步骤:

  1. 首先,将库存syscall.Seek()实际映射到lseek(2) 相关平台上。

  2. 接下来,你需要找出正确的值SEEK_HOLE,并 SEEK_DATA为需要支持的平台。

请注意,它们可以 自由地 在不同平台之间有所不同!

说,在我的Linux系统上,我可以做简单

    $ grep -E 'SEEK_(HOLE|DATA)' </usr/include/unistd.h 
#  define SEEK_DATA     3       /* Seek to next data.  */
#  define SEEK_HOLE     4       /* Seek to next hole.  */

…找出这些符号的值。

现在,假设您在包中创建了一个特定于Linux的文件,其中包含以下内容

// +build linux

const (
    SEEK_DATA = 3
    SEEK_HOLE = 4
)

然后将这些值与一起使用syscall.Seek()

syscall.Seek()可以使用值Fd()方法从打开的文件中获取传递给朋友的文件描述符os.File

读取时使用的模式是检测包含数据的区域,并从中读取数据-
请参阅此示例。

请注意,这涉及读取稀疏文件。但是如果您实际上想稀疏地 转移 它们-也就是说,保留它们的这种特性-
情况就更加复杂了:它似乎更不便于携带,因此需要进行一些研究和实验。

在Linux上,您似乎可以尝试使用fallocate(2)with
FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE尝试在要写入的文件末尾打个孔;如果该操作合法失败(带有syscall.EOPNOTSUPP),则只需将要清零的洞覆盖的零块塞入目标文件中即可-
希望操作系统能够做正确的事情并将其自身转换为一个洞。

请注意,作为一个概念,某些文件系统根本不支持漏洞。一个示例是FAT系列中的文件系统。我要带您的是,根据您的情况,无法创建稀疏文件实际上可能是目标文件系统的属性。

您可能会发现Go感兴趣的问题#13548“ archive /
tar:添加对编写包含稀疏文件的tar的支持”。

另一个注意事项:您可能还考虑检查要复制源文件的目标目录是否与源文件位于同一文件系统中,如果成立,请使用syscall.Rename()(在POSIX系统上)或os.Rename()仅在不同目录中移动文件没有实际复制其数据。



 类似资料:
  • 问题内容: 我使用io.Copy()复制文件,大约700Mb,但这会导致内存不足 错误信息如下: 我为buf分配了足够的内存,这导致bodyWriter.CreateFormFile()中的内存不足 问题答案: 这是因为您正在“复制”到,这是内存中的缓冲区,从而迫使Go尝试分配与整个文件一样大的内存块。 根据您的使用情况,您似乎正在尝试通过HTTP流式传输文件?在这种情况下,请勿将传递给,而是直接

  • 问题内容: 我得到了一个1TB的稀疏文件,在Linux上实际上存储了32MB数据。 是否可以“有效地”制作一个软件包来存储稀疏文件?该软件包应解压缩为另一台计算机上的1TB稀疏文件。理想情况下,“软件包”应为32MB左右。 注意:可能的解决方案是使用“ tar”:https : //wiki.archlinux.org/index.php/Sparse_file#Archiving_with_.6

  • 我正在用Jersey 2.0开发表单提交服务。表单包括几个文本字段和一个文件字段。我需要提取文件、文件名、文件媒体类型和文件内容类型,并将它们保存在对象存储中。 pom。xml 表格提交请求 JVM堆大小 上载约50MB的文件时,会在名为FileBackedOutputStream7949386530699987086的目录下创建两个MD5和相似的临时文件。tmp和MIME823422976685

  • 我正在开发一个android应用程序,我试图将谷歌驱动器集成到我的应用程序中。该程序是允许同步,所以它在SD卡上创建一个文件,然后这个文件被上传到谷歌驱动器上。我成功地进行了身份验证,但是当我使用函数上传时,我得到一个NullPointerException,并且我看不到值在哪里是null,因为当我遍历所有内容时,似乎没有任何内容是null。 下面是我用来执行上传的代码。 以下是我如何获得驱动器服

  • 这是密码 我希望一个包含2个元素的数组第一个是空字符串,第二个是“\test”,因为它在javascript中工作得非常好 但不是预期的输出,而是我如何获得完整的:( 不知道我做错了什么。。。

  • 在Java中,我与JGit合作,在远程存储库中执行一些操作。但是,当我依次在版本之间执行稀疏签出时: 它保留最后一个签出文件并添加新的签出文件。只有当目录中的文件名不相同时才会发生这种情况。以这种方式使用checkout命令时,如何避免这种情况? 我考虑过删除正在签出的文件夹中的文件(本例中是脚本),但我不知道当“下载”的文件具有相同的名称时,是否会带来冲突。