2012-03-12 35 views
0

我正在嘗試製作加密算法。 我可以讀取一個文件並將其轉換爲無任何問題的字節,並將字節保存在一個byteArray中。基於可用物理內存的數組大小

問題是我目前正在創建數組的大小是這樣的:

byte[] FileArray =new byte[10000000]; 
FileStream TheFileStream = new FileStream(FilePath.Text, FileMode.Open); 
BinaryReader TheFileBinary = new BinaryReader(TheFileStream); 

for (int i = 0; i < TheFileStream.Length; i++) { 
    FileArray = TheFileBinary.ReadBytes(10000000); 
    // I call a function here 
    if (TheFileStream.Position == TheFileStream.Length) 
     break; 
} 

不過,我不希望被固定數組的大小,因爲如果我讓它1000000(作爲一個例子),其他內存小的機器可能會遇到問題。 我需要爲每臺機器找到一個內存大小的空閒大小,我如何根據空閒的未分配內存空間動態設置數組大小,以便我可以將它放在byteArray中?

我注意到數組越大,讀取的速度越快,所以我不想讓它太小。 我真的很感激幫助。

+9

'想使加密algorithm'這可能是一個錯誤。安全加密是_hard_。 – SLaks 2012-03-12 18:54:11

+2

你要求的〜10MB是一個相當小的數額。你爲什麼在這裏擔心記憶問題?你遇到問題了嗎?你預計未來某些10MB的設備會遇到什麼問題? – dlev 2012-03-12 18:55:41

+2

(可以說)_better_方法是製作你自己的Stream。 – 2012-03-12 18:59:21

回答

0

如果你真的很擔心空間,那麼使用一個簡單的List,一次讀入數據流塊(比如1024),然後在列表中調用AddRange方法。完成後,請在列表中調用ToArray,現在您的字節數組大小適當。

List<byte> byteArr = new List<byte>(); 
byte[] buffer = new byte[1024]; 
int bytesRead = 0; 
using(FileStream TheFileStream = new FileStream(FilePath.Text, FileMode.Open)) 
{ 
    while((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0) 
     byteArr.AddRange(buffer); 
} 
buffer = byteArr.ToArray(); 
// call your method here. 

編輯:它仍然更好地閱讀它在大塊文件的塊。當然,你可以隨意使用緩衝區大小,但是1024通常是一個很好的起點。讀取整個文件最終會使內存變爲雙倍,因爲您還必須處理內部讀取緩衝區是流的大小(在您自己的緩衝區之上)。將讀取分成塊只需要FileStream.Length + <buffer size>內存,而不是FileStream.Length * 2。只是要記住...

byte[] buffer = null; 
using(FileStream TheFileStream = new FileStream(FilePath.Text, FileMode.Open)) 
{ 
    buffer = new byte[TheFileStream.Length]; 
    int offset = 0; 
    while((bytesRead = stream.Read(buffer, offset, 1024)) > 0) 
     offset += bytesRead; 
    // Or just TheFileStream.Read(buffer, 0, buffer.Length) if it's small enough. 
} 
+0

您正在以塊讀取文件,但最終會以'byteArray'和'buffer'存儲整個文件的副本。作者擔心內存使用情況,並且一次只想要一塊文件在內存中。 – BACON 2012-03-12 19:37:38

0

FileStream跟蹤文件中有多少字節。只需使用Length屬性。

FileStream TheFileStream = new FileStream(FilePath.Text, FileMode.Open); 
BinaryReader TheFileBinary = new BinaryReader(TheFileStream); 
byte[] FileArray = TheFileBinary.ReadBytes(TheFileStream.Length); 

好重讀的問題,並finnaly發現這是一個問題,「我怎麼能知道自由的未分配的內存空間,所以我可以把它放在字節組」它的一部分。無論如何,我建議你看看this question along with its highest rated comment

+0

作者正在嘗試以最佳大小的塊讀取和處理該文件,而這會一次將整個文件讀入一個數組。另外,FileStream.Length屬性拼寫錯誤。 – BACON 2012-03-12 19:20:34

0

您可以使用WMI檢索Win32_OperatingSystem class的實例和基本內存計算關閉FreePhysicalMemoryTotalVisibleMemorySize屬性:

static ulong GetAvailableMemoryKilobytes() 
{ 
    const string memoryPropertyName = "FreePhysicalMemory"; 

    using (ManagementObject operatingSystem = new ManagementObject("[email protected]")) 
     return (ulong) operatingSystem[memoryPropertyName]; 
} 

static ulong GetTotalMemoryKilobytes() 
{ 
    const string memoryPropertyName = "TotalVisibleMemorySize"; 

    using (ManagementObject operatingSystem = new ManagementObject("[email protected]")) 
     return (ulong) operatingSystem[memoryPropertyName]; 
} 

那麼這兩種方法的結果傳遞給方法像這樣規模的您讀取緩衝區的大小到本地機器的內存:

static int GetBufferSize(ulong memoryKilobytes) 
{ 
    const int bufferStepSize = 256;  // 256 kilobytes of buffer... 
    const int memoryStepSize = 128 * 1024;// ...for every 128 megabytes of memory... 
    const int minBufferSize = 512;  // ...no less than 512 kilobytes... 
    const int maxBufferSize = 10 * 1024; // ...no more than 10 megabytes 
    int bufferSize = bufferStepSize * ((int) memoryKilobytes/memoryStepSize); 

    bufferSize = Math.Max(bufferSize, minBufferSize); 
    bufferSize = Math.Min(bufferSize, maxBufferSize); 

    return bufferSize; 
} 

顯然,增加256 KB的緩衝區大小每128 MB的RAM似乎有點傻,但這些數字都只是例子如果你真的想這麼做,你如何擴展你的緩衝區大小。除非你一次讀取很多很多的文件,否則擔心一個幾百KB或幾MB的緩衝區可能比它的價值更麻煩。你可能比基準測試更好,看看哪種大小的緩衝區能夠提供最佳性能(可能不需要像你想象的那麼大)並使用它。

現在,你可以簡單地更新你的代碼是這樣的:

ulong memoryKilobytes = 
    GetAvailableMemoryKilobytes(); 
    // ...or GetTotalMemoryKilobytes(); 
int bufferSize = GetBufferSize(memoryKilobytes); 

using (FileStream TheFileStream = new FileStream(FilePath.Text, FileMode.Open)) 
{ 
    byte[] FileArray = new byte[bufferSize]; 
    int readCount; 

    while ((readCount = TheFileBinary.Read(FileArray, 0, bufferSize)) > 0) 
    { 
     // Call a method here, passing FileArray as a parameter 
    } 
} 
相關問題