好的,我制作了一个C#winform应用程序,它是一个File_Splitter_Joiner。 你只需给它一个文件,然后将它拆分为你指定的一些部分。 拆分是在一个单独的线程中完成的。 一切都工作得很好,直到我切成1Gig文件! 在任务管理器中,我看到我的程序开始消耗1G内存,而我的计算机几乎死了! 不仅如此,当切片完成时,消耗没有改变! (不知道这是否意味着垃圾收集器无法正常工作,虽然我很确定我丢失了所有关于持有大数据块的内容的引用,所以它应该工作) 这是Splitter构造函数(只是为了给你一个更好的想法):
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程序(不是我写的)只是为了看如果它有同样的问题,我加载文件,程序消耗约5Mig的ram,当我开始拆分时,它使用了大约10Migs !! 现在这是一个非常大的差异..可能该应用程序是在C / C ++ ..
总结一下,谁糟透了?是我的代码,如果是这样,我该如何解决?或者说性能是C#?
非常感谢SOOO,因为你能把我联系起来:)
答案 0 :(得分:2)
以下两行将为您解释:
int fileSize = (int)FileToSplitInfo.Length; // a FileInfo object
...
byte[] fileBytes = new byte[fileSize];
Int32.MaxValue
时,您的代码将失败。不必要,只需使用long fileSize = FileToSplitInfo.Length;
PieceSize
个字节。您甚至不需要知道fileSize,只需
byte[] pieceBuffer = new byte[PieceSize];
while (true)
{
int nBytes = br.Read(pieceBuffer, 0, pieceBuffer.Length);
if (nBytes == 0)
break;
// write this piece, the length is nBytes
}
答案 1 :(得分:1)
可以做出更好的不同方面:
如果您正在处理大文件,为什么首先在中写入所有并将写入另一个文件?只需在从另一个文件读取时写入新文件。
在任何情况下都使用using
来保证对流的处理:是否存在例外情况。
如果您开始使用非常大的文件,例如1GB甚至更多,我建议您查看Memory Mapped Files。因此,您可以通过提高性能成本来获得令人难以置信的内存消耗优势。