Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/259.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为分析目的写入和读取大文件_C#_File_Memory_Stream_Dna Sequence - Fatal编程技术网

C# 为分析目的写入和读取大文件

C# 为分析目的写入和读取大文件,c#,file,memory,stream,dna-sequence,C#,File,Memory,Stream,Dna Sequence,我想做一个DNA分析工具,但我在这里面临一个大问题 下面是应用程序的屏幕截图 我面临的问题是处理大数据。我使用了流和内存映射文件,但我不确定我的方向是否正确。 我试图实现的是能够编写一个包含30亿个随机字母的文本文件,然后将该文本文件用于以后的用途。 目前我有3000封信,但产生更多的信需要时间。你将如何处理这个问题?将全文文件存储到字符串中对我来说似乎是过载。有什么想法吗 private void WriteDNASequence(string dnaFile) {

我想做一个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);
        }
    }
private void WriteDNASequence(字符串dnaFile)
{
字典neucleotides=新字典();
添加(0,'A');
添加(1,'T');
添加(2,'C');
添加(3,'G');
int碱基对=3000;
使用(StreamWriter sw=新StreamWriter(文件路径+@“\”+dnaFile))
{
对于(int i=0;i<(碱基对/2);i++)
{
int neucletide=随机数(0,4);
sw.Write(neucleotides[neucleotide]);
}
}
}
私有字符串ReadDNASequence(字符串dnaFile)
{
_DNAData=“”;
使用(StreamReader文件=新的StreamReader(文件路径+@“\”+dnaFile))
{
_DNAData=file.ReadToEnd();
}
返回数据;
}
//函数获取一个随机数
私有静态只读随机=新随机();
私有静态只读对象syncLock=新对象();
公共静态整数随机数(整数最小值,整数最大值)
{
锁定(同步锁定)
{//同步
返回random.Next(最小值、最大值);
}
}

在处理如此大量的数据时,每一点都很重要,您必须尽可能密集地打包数据

到目前为止,每个核苷酸由一个字符表示,您使用的编码中的一个字符(默认情况下是
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'}
};
至于将字节写入文件,我认为这很容易。如果在这种情况下需要一些随机数据,请使用:

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年)硬盘上生成30亿对需要8秒钟,输出大小为350MB。如果有必要,您甚至可以一次将所有350MB的数据读取到内存中。

将数据块生成,然后将数据块写入文件。在一个字符串中生成500000个字母应该没有问题(请使用StringBuilder),然后将其刷新到文件中。冲洗,重复20次。写文本应该是最简单的事情(但你设法使它变得非常复杂)。我可以看到读取(全部)有问题,但这里没有提出这个问题。如果您有一个进程按顺序写入,然后有一个进程按顺序读取文件,则不需要内存映射文件。想做就做您可能需要缓冲数据,每次读取或写入一个字节非常耗时。如果只有普通的ANSI字符,您可能还希望使用ANSI每个字符一个字节的文件。甚至可以把它们装进更小的东西里,如果每个字节没有256个可能的值。请使用SQL Server之类的数据库,该数据库旨在处理大量数据。顺便说一句,从多个线程写入同一个视图访问器可能不安全。使用所有可能位的随机字节打包以及由此产生的下一个字节的使用非常好。在我的测试中,产生0-3之间的随机整数以获得单个字节所需的时间比实际将它们写入磁盘所需的时间要长。我投票赞成一个非常有创造性的解决方案。在我的机器上运行这个大约需要4.5秒。嘿,回答太好了!有一个问题,你能展示一下你是如何使用chunkSize生成30亿对的吗?@Eli我现在没有时间来写代码,但应该很简单。据我所知,30亿对是15亿个字符。每4个字符为1个字节。所以把它除以4。然后按上述方式生成随机字节,分块,并写入文件(同样如上所述),直到写入指定数量的字节(最后一个块当然可能小于块大小)。
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);