我试图制作DNA分析工具,但我在这里面临一个大问题。
我面临的问题是处理大数据。我已经使用了流和内存映射文件,但我不确定我是否朝着正确的方向前进。 我想要实现的是能够编写一个包含30亿个随机字母的文本文件,然后将该文本文件用于以后的目的。 目前,我有3000多个字母,但产生的数量要多,需要很长时间。你会如何解决这个问题?将全文文件存储到字符串中似乎对我来说过载。有什么想法吗?
private void WriteDNASequence(string dnaFile)
{
Dictionary<int, char> neucleotides = new Dictionary<int, char>();
neucleotides.Add(0, 'A');
neucleotides.Add(1, 'T');
neucleotides.Add(2, 'C');
neucleotides.Add(3, 'G');
int BasePairs = 3000;
using (StreamWriter sw = new StreamWriter(filepath + @"\" + dnaFile))
{
for (int i = 0; i < (BasePairs / 2); i++)
{
int neucleotide = RandomNumber(0, 4);
sw.Write(neucleotides[neucleotide]);
}
}
}
private string ReadDNASequence(string dnaFile)
{
_DNAData = "";
using (StreamReader file = new StreamReader(filepath + @"\" + dnaFile))
{
_DNAData = file.ReadToEnd();
}
return _DNAData;
}
//Function to get a random number
private static readonly Random random = new Random();
private static readonly object syncLock = new object();
public static int RandomNumber(int min, int max)
{
lock (syncLock)
{ // synchronize
return random.Next(min, max);
}
}
答案 0 :(得分:3)
当处理如此大量的数据时 - 每一点都很重要,你必须尽可能密集数据。
截至目前,每个核苷酸由一个char表示,并且您使用的编码中的一个char(默认为UTF-8
)占用1个字节(对于您使用的4个字符)。
但由于你只有4个不同的字符 - 每个字符只包含2位信息,所以我们可以将它们表示为:
00 - A
01 - T
10 - C
11 - G
这意味着我们可以在一个字节中打包4个核苷酸,使输出文件大小缩小4倍。
假设你有这样的地图:
static readonly Dictionary<char, byte> _neucleotides = new Dictionary<char, byte> {
{ 'A', 0},
{ 'T', 1},
{ 'C', 2},
{ 'G', 3}
};
static readonly Dictionary<int, char> _reverseNucleotides = new Dictionary<int, char> {
{0, 'A'},
{1, 'T'},
{2, 'C'},
{3, 'G'}
};
你可以打包4个核苷酸,就像这样一个字节:
string toPack = "ATCG";
byte packed = 0;
for (int i = 0; i < 4; i++) {
packed = (byte) (packed | _neucleotides[toPack[i]] << (i * 2));
}
然后像这样打开包装:
string unpacked = new string(new[] {
_reverseNucleotides[packed & 0b11],
_reverseNucleotides[(packed & 0b1100) >> 2],
_reverseNucleotides[(packed & 0b110000) >> 4],
_reverseNucleotides[(packed & 0b11000000) >> 6],
});
至于将字节写入文件,我认为这很容易。如果在这种情况下需要一些随机数据,请使用:
int chunkSize = 1024 * 1024; // 8 million pairs at once (since each byte is 4 nucleotides)
byte[] chunk = new byte[chunkSize];
random.NextBytes(chunk);
// fileStream is instance of `FileStream`, no need for `StreamWriter`
fileStream.Write(chunk, 0, chunk.Length);
有一些警告(比如文件中的最后一个字节可能不会存储4个核苷酸但不会更少),但我希望你能自己解决这个问题。
采用这种方法(以二进制打包,一次生成大块随机块,将大块写入文件) - 在我很老的(7年)HDD上生成30亿对花了8秒,输出大小为350MB。如有必要,您甚至可以一次性将所有350MB的内容读入内存。