我想将一个字符编码为 2 位,即:
'A' to 00
'C' to 01
'G' to 10
'T' to 11
现在,例如给定一个内容为 ACGT
的文件其大小为 4 字节。
我想读取该文件并将其相应位写入 .bin 文件,该文件的大小最终仅为 8 位(1 字节)。
即:
输入文本文件内容:ACGT
输出二进制文件内容:00011011
通过这样做,我会将尺寸减小到原始尺寸的 1/4 倍。
用C语言可以实现吗?
最佳答案
以下代码演示了您需要执行的操作。它根据您的规范进行编码/解码,但仅在内存中而不是在文件中。该代码需要适合对文件进行编码/解码。
编码字节格式:
前 4 个字节(或根据平台为 8 个字节)包含大端(或根据平台为小端格式)编码字符数(“ACGTA”为 5 个字符)。之后的字节包含根据您的规范编码的字符。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void encode(const char *input, unsigned char *output)
{
size_t size = strlen(input);
memcpy(output, &size, sizeof (size_t));
output += sizeof(size_t);
size_t outputindex = 0;
for (size_t i = 0; i < size; )
{
unsigned char byte = 0;
for (int j = 0; j < 4 && i < size; j++)
{
unsigned char value;
switch (input[i++])
{
case 'A':
value = 0;
break;
case 'C':
value = 1;
break;
case 'G':
value = 2;
break;
case 'T':
value = 3;
break;
default:
printf("Input error, invalid char '%c' encountered\n", input[i - 1]);
exit(1);
}
byte |= (value << ((3 - j) * 2));
}
end:
output[outputindex++] = byte;
}
}
void decode(const unsigned char *input, char *output)
{
size_t size;
memcpy(&size, input, sizeof(size_t));
input += sizeof(size_t);
size_t inputindex = 0;
size_t i;
for (i = 0; i < size;)
{
unsigned char ch = input[inputindex++];
for (int j = 0; j < 4; j++)
{
unsigned char b = (ch >> ((3 - j) * 2)) & 0x3;
output[i++] = "ACGT"[b];
if (i >= size)
break;
}
}
output[i] = 0;
}
void printhexencoded(unsigned char *input)
{
size_t size;
memcpy(&size, input, sizeof(size_t));
size = (size + 3) / 4;
input += sizeof(size_t);
for (size_t i = 0; i < size; i++)
{
printf("%02x", input[i]);
}
}
int main(void)
{
const char testdata[] = "ACGTCGTAACGATACTGCTAA";
printf("Encoding %s\n", testdata);
unsigned char encodedbytes[100];
encode(testdata, encodedbytes);
printf("Encoded bytes in hexadecimal: ");
printhexencoded(encodedbytes);
printf("\n");
char decodedbytes[100];
decode(encodedbytes, decodedbytes);
printf("Decoded bytes %s\n", decodedbytes);
if (strcmp(testdata, decodedbytes) != 0)
printf("Test failed.");
else
printf("Test succeeded.");
}
免责声明:此代码几乎没有经过测试,并且根本没有进行任何边界检查。假设输入只包含[ACGT]
集合中的字符,如果遇到任何其他字符,则程序退出。
关于我们可以用 C 将位写入 .bin 文件吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54804107/