2016-07-19 24 views
0

私はオンラインで見ていましたが、私はいくつかのものを見つけることができました。c# - 大きなファイルを複数のファイルに分割

INSERT INTO `cola`(`url`, `page`, `c_id`) VALUES 
(`{0}`, `{1}`, 0), 
(`{0}`, `{1}`, 0), 
(`{0}`, `{1}`, 0), ... 300 times 
(`{0}`, `{1}`, 0); 
INSERT INTO... 

は{0}と{1}の値です:

私はこのようになりますSQLファイルを持っています。 私はphpMyAdminに最大50MiBしかアップロードできないので、このファイルを分割する必要があります。 私は物事をオンラインで見つけましたが、行を終了せずにファイルを50MiBで正確に分割しました。

は、だから私は何をしたいです: スプリット48個のにファイル - 49MiBファイル、および

INSERT INTO `cola`(`url`, `page`, `c_id`) VALUES 

で始まる最後の行が( {0} , {1} , 0);と次のファイルになりましょうどのようなI現在:

StreamReader GET = new StreamReader(@"C:\Users\Matthew\Documents\sql.sql"); 

     string line; 
     int fileId = 0; 
     int lineId = 0; 
     long fileLenght = 0; 

     while ((line = GET.ReadLine()) != null) 
     { 
      lineId++; 

      using (StreamWriter sw = File.AppendText(@"C:\Users\Matthew\Desktop\ye\" + fileId.ToString() + ".sql")) sw.WriteLine(line); 

      if (lineId == 50000) 
      { 
       FileInfo f = new FileInfo(@"C:\Users\Matthew\Desktop\ye\" + fileId.ToString() + ".sql"); 
       fileLenght = f.Length; 
       Console.Title = fileLenght.ToString(); 
       lineId = 0; 
      } 

      if (fileLenght > 50000000 && line.EndsWith(");")) 
      { 
       fileLenght = 0; 
       fileId++; 
       using (FileStream fs = File.Create(@"C:\Users\Matthew\Desktop\ye\" + fileId.ToString() + ".sql")) fs.Close(); 
       Console.WriteLine("Created: " + fileId.ToString()); 
      } 

     } 

     GET.Close(); 
     Console.WriteLine("Core - SQL is done."); 

これは機能しますが、非常に遅いです。どんなアイデアでもそれを速くすることができますか?

分割しているファイルは4GBです。

+1

なぜファイルをINSERT文で分割しないのですか?これはワンオフ作品ですか? – Yahya

+0

@ Yahya各INSERT文で分割すると、あまりにも多くのファイルが取得されます。私は約48/49 MiBのファイルが欲しい。 – wtm

+0

これは、C# – Paparazzi

答えて

1

私は数年前に同様のプロジェクトを行っていました。私がそれを処理する方法は、Xサイズ(あなたの場合は49MB)のチャンクを取り込み、最後のキーの先頭に逆方向(String.LastIndexOfを使用)をスキャンすることでした( "Insert Into"になります)。 String.LastIndexOf結果の左側は、ファイルに保存され、その文字列の残りは次のXY(49メガバイト - 剰余列のサイズ)の前に付加されている私がロードされていることバイト

0

擬似コード来る:

open main file 
n=1 
open chunk[n] 
while not !eof main file 
{ 
    read line from main file 
    if chunk stream . position+size of line < chunksize 
    write line to chunk 
    else 
    { 
    close chunk 
    n+1 
    open new chunk 
    write line to new chunk 
    } 
} 
close chunk 
close main file 

今、あなたはチャンクで、全体のラインであなたのファイルを持っている。このような

0

何かが動作するはずです。あなたはヘクタールあれば遊んでする必要があるかもしれませんスクリプトに文を挿入するだけではありません。

var filename = "outfile.sql"; 
var spliton = "INSERT INTO"; 
var expectedEnd = ";"; 

var outcount = 0; 
var filecounter = 0; 
var outfileformatter = Path.GetFileNameWithoutExtension(filename) + "_{0}" + 
         Path.GetExtension(filename); 

string outfile = null; 
StreamWriter writer = null; 
var blocksize = 32 * 1024; 
var block = new char[blocksize]; 
// by using StreamReader you won't have to load the entire file into memory 
using (var reader = new StreamReader(filename)) 
{ 
    while (!reader.EndOfStream) 
    { 
     // read in sections of the file at a time since you can't hold the entire thing in memory. 
     var outsize = reader.ReadBlock(block, 0, blocksize); 
     var content = new string(block, 0, outsize); 

     // split the data by your seperator. 
     var chunks = content.Split(new[] { spliton }, StringSplitOptions.RemoveEmptyEntries) 
          .Select(c => spliton + c); 

     // loop over the chunks of data 
     foreach (var chunk in chunks) 
     { 
       //once the threshold is tripped close the writer and open the next 
       if (outcount > 48 * 1024 * 1024 || outfile == null) //48MB - 
       { 
        if (expectedEnd != null && !chunk.TrimEnd().TrimEnd('\n', '\r').EndsWith(expectedEnd)) 
        { 
         //Console.WriteLine("+++extend"); 
        } 
        else 
        { 
         filecounter++; 
         outcount = 0; 
         if (writer != null) 
          writer.Close(); 
         Console.WriteLine(outfile); 
         outfile = string.Format(outfileformatter, filecounter); 
         writer = new StreamWriter(outfile); 
        } 
       } 
      //output the data 
      writer.Write(chunk); 
      //record how much data you wrote to the file. 
      outcount += Encoding.UTF8.GetBytes(chunk).Length; 
      //if the file is only ascii you could cheat and just say 'chunk.Length'. 
     } 

    } 
} 
if (writer != null) 
    writer.Close(); 

...これはSQLを解析しません。あなたが文を挿入するだけでなく、48MBよりも長いinsert文を使っているなら、この分割コードに問題があるかもしれません。しかし、ファイルに書き込まれている最後のステートメントがセミコロン;で終わっていることを常に確認するか、必要に応じて解析/分割ロジックを変更することができます。

関連する問題