是否可以从C中的文件开头删除N个字节?

时间:2012-12-02 19:22:34

标签: c file

是否可以从C?

中的文件开头删除N个字节

N仅为30个字节。

我无法复制文件,因为它们非常大(有时甚至是100 GB)

2 个答案:

答案 0 :(得分:2)

在Linux上,您可以创建指向另一个文件中的偏移量的环回设备。来自unix.stackexchange的Here is such an example

#!/bin/bash
for ((i=0;i<10000;i++)); do
    printf "%7d\n" $i
done >/var/tmp/file
losetup -v -f -o 512 --sizelimit 512 /var/tmp/file
losetup -a
head -2 /var/tmp/file
echo ...
tail -2 /var/tmp/file
echo ===
head -2 /dev/loop0
echo ...
tail -2 /dev/loop0 
printf "I was here" > /dev/loop0
grep here /var/tmp/file
losetup -d /dev/loop0

输出:

loop device: /dev/loop0
/dev/loop0: [0808]:136392 (/var/tmp/file), offset 512, size 512
      0
      1
...
   9998
   9999
===
     64
     65
...
    126
    127
I was here   65

答案 1 :(得分:1)

你不能从文件的开头删除30个字节,但没有什么能阻止你覆盖文件(至少在大多数Unix文件系统上)。这相当于所需时间的副本,但它不会占用您的可用磁盘空间。

这是一个可能有用的小功能,虽然我没有彻底测试。

一个警告:曾经是off_t是32位有符号整数的情况,因此pread,pwrite和ftruncate不能用于大于2GB的文件。在Linux上,情况已不再如此。但是,可能需要使用pread64,pwrite64和ftruncate64。在您确认它确实在您的操作系统上运行之前,请不要在您关心的非常大的文件上尝试此操作。

int fshift(int fd, off_t to, off_t from) {
  if (from <= to) {
    fprintf(stderr, "%s\n", "Unimplemented: fshift can only shift left");
    errno = ERANGE;
    return -1;
  }
  char buffer[BUFFER_SIZE];
  for (;;) {
    ssize_t n_read = pread(fd, buffer, BUFFER_SIZE, from);
    if (n_read < 0) {
      int tmp = errno;
      perror("fshift: could not read file");
      errno = tmp;
      return -1;
    }
    from += n_read;
    if (n_read == 0) {
      int rc = ftruncate(fd, to);
      if (rc < 0) {
        int tmp = errno;
        perror("fshift: could not truncate file");
        errno = tmp;
      }
      return rc;
    }
    for (char* p = buffer, *lim = &buffer[n_read]; p < lim;) {
      ssize_t n_write = pwrite(fd, p, lim - p, to);
      if (n_write < 0) {
        int tmp = errno;
        perror("fshift: could not write file");
        errno = tmp;
        return -1;
      }
      p += n_write;
      to += n_write;
    }
  }
}