OK、C# の winform アプリを作成しました。これは File_Splitter_Joiner です。ファイルを渡すだけで、指定した数の断片に分割されます。分割は別のスレッドで行われます。1Gig ファイルをスライスするまで、すべてがうまく機能していました。タスク マネージャーで、私のプログラムが 1 ギガバイトのメモリを消費し始め、コンピューターが死にかけているのを見ました! それだけでなく、スライスが終わったとき、消費は変わりませんでした!(これがガベージコレクタが機能していないことを意味するかどうかはわかりませんが、ビッグデータチャンプを保持していたものへのすべての参照を失ったことはかなり確信しているので、機能するはずです)考え):
public FileSplitter(string FileToSplitPath, string PiecesFolder, int NumberOfPieces, int PieceSize, SplittingMethod Method)
{
FileToSplitInfo = new FileInfo(FileToSplitPath);
this.FileToSplitPath = FileToSplitPath;
this.PiecesFolder = PiecesFolder;
this.NumberOfPieces = NumberOfPieces;
this.PieceSize = PieceSize;
this.Method = Method;
SplitterThread = new Thread(Split);
}
そして、実際の分割を行った方法は次のとおりです: (私はまだ初心者なので、これから説明することは可能な限り最良の方法で行われない可能性があります。私はここで学んでいます)
private void Split()
{
int remainingSize = 0;
int remainingPos = -1;
bool isNumberOfPiecesEqualInSize = true;
int fileSize = (int)FileToSplitInfo.Length; // FileToSplitInfo is a FileInfo object
if (fileSize % PieceSize != 0)
{
remainingSize = fileSize % PieceSize;
remainingPos = fileSize - remainingSize;
isNumberOfPiecesEqualInSize = false;
}
byte[] fileBytes = new byte[fileSize];
var _fs = File.Open(FileToSplitPath, FileMode.Open);
BinaryReader br = new BinaryReader(_fs);
br.Read(fileBytes, 0, fileSize);
br.Close();
_fs.Close();
for (int i = 0, index = 0; i < NumberOfPieces; i++, index += PieceSize)
{
var fs = File.Create(PiecesFolder + "\\" + Path.GetFileName(FileToSplitPath) + "." + (i+1).ToString());
var bw = new BinaryWriter(fs);
bw.Write(fileBytes, index, PieceSize);
if(i == NumberOfPieces-1 && !isNumberOfPiecesEqualInSize && Method == SplittingMethod.NumberOfPieces)
bw.Write(fileBytes, remainingPos, remainingSize);
bw.Close();
fs.Close();
}
MessageBox.Show("File has been splitted successfully!");
SplitterThread.Abort();
}
ここで、BinaryReader を介してファイルのバイトを読み取る代わりに、最初にFile.ReadAllBytes
メソッドを介してファイルを読み取っていました。小さなファイル サイズでは問題なく動作していましたが、私たちの大物を扱ったときに「SystemOutOfMemory」例外が発生しました。 BinaryReader を介してバイトを読み取ったときに、なぜその例外が発生しなかったのか。
(それは中間の質問でした)
それで、主な質問は、メモリをそれほど消費しない方法で大きなファイルをロードするにはどうすればよいかということです(ギグと言えば)?つまり、プログラムがそのメモリをすべて消費しないようにするにはどうすればよいでしょうか? 分割が完了した後、使用済みメモリを解放するにはどうすればよいですか? (実際に使った
bw.Dispose; fs.Dispose;
それ以外の
bw.Close(); fs.Close();
それは同じでした。Q が意味をなさない可能性があることはわかっています。何かをロードすると、他の場所ではなくメモリに保存されますが、そのように尋ねた理由は、別の Splitting_Joining プログラム (私が作成したものではありません) を使用したためです。同じ問題が発生した場合、ファイルをロードすると、プログラムは約5MigsのRAMを消費し、分割を開始すると約10Migsを使用しました!! これは非常に大きな違いです..おそらくそのアプリはC / C ++でした..
要約すると、誰が悪いのですか?それは私のコードですか?もしそうなら、どうすれば修正できますか? それともパフォーマンスに関してはC#ですか?
あなたが私をつなぐことができるものをすべてありがとうございます:)