将4个字符序列有效地压缩为每个字符文件2位

时间:2016-11-12 02:40:37

标签: c bash file-io binary compression

我正在尝试压缩基因组序列。这些是字母“A”“C”“G”和“T”的字符串。在文本文件形式中,它们存储为字符。由于它们只有4个,因此可以在文件中表示为两位。

换言之:ACTG - > 00 01 10 11,而不是8位字符

此数据将写回一个文件,其中每个字节代表4个字符。在bash脚本或C程序中执行此操作的最有效方法是什么?

谢谢!

1 个答案:

答案 0 :(得分:2)

这是一个过滤器,它首先对最低有效位的序列进行编码:

#include <stdio.h>

int main(void) {
    unsigned i = 0;
    int c, d = 0;
    while ((c = getchar()) != EOF) {
        switch (c) {
          case 'A': d |= 0 << (2 * (i & 3)); break;
          case 'C': d |= 1 << (2 * (i & 3)); break;
          case 'T': d |= 2 << (2 * (i & 3)); break;
          case 'G': d |= 3 << (2 * (i & 3)); break;
          default: continue; // ignore all other characters
        }
        if ((++i & 3) == 0) {
            putchar(d);
            d = 0;
        }
    }
    if (i & 3) {
        putchar(d);
    }
    return 0;
}

这里首先是最重要的位(也就是像素顺序)

#include <stdio.h>

int main(void) {
    unsigned i = 0;
    int c, d = 0;
    while ((c = getchar()) != EOF) {
        switch (c) {
          case 'A': d = (d << 2) | 0; break;
          case 'C': d = (d << 2) | 1; break;
          case 'T': d = (d << 2) | 2; break;
          case 'G': d = (d << 2) | 3; break;
          default: continue; // ignore all other characters
        }
        if ((++i & 3) == 0) {
            putchar(d);
            d = 0;
        }
    }
    if (i & 3) {
        putchar(d << (2 * (3 - (i & 3))));
    }
    return 0;
}

注意:

  • 序列用A隐式填充,最多4个碱基。

  • 将二进制数据写入stdout可能会在stdout处于文本模式的系统上产生不正确的输出,其语义与二进制模式不同(例如Windows,与OS / X或Unix不同) )。