MemoryStream替代大数据量

时间:2013-07-29 10:38:30

标签: c# .net stream memorystream

如果数据很大且进程为32位,那么在使用.Net MemoryStream时出现内存不足异常的问题。

我相信System.IO.Packaging API会随着数据量的增加而从内存静默切换到文件支持的存储,从表面上看,似乎可以实现一个MemoryStream的子类。完全相同的事情。

有谁知道这样的实现?我很确定框架本身没有任何内容。

4 个答案:

答案 0 :(得分:8)

程序员努力避免使用文件。在Windows中,内存和文件之间的差异非常小。用于MemoryStream的任何内存实际上都需要一个文件。存储由页面文件c:\ pagefile.sys支持。反之亦然,您使用的任何文件都由内存支持。文件数据由文件系统缓存缓存在RAM中。因此,如果机器有足够的RAM,那么如果使用FileStream,实际上只能从/向内存读写。并获得你期望使用内存的性能。它完全免费,您不必编写任何代码来启用此功能,也不必管理它。

如果机器没有足够的RAM,那么它会以同样的方式恶化。当您使用MemoryStream时,页面文件开始被废弃,您将被磁盘放慢速度。当您使用文件时,数据将不适合文件系统缓存,您将被磁盘放慢速度。

你当然会得到使用文件的好处,你不会再耗尽内存了。改为使用FileStream。

答案 1 :(得分:1)

预计这将使用MemoryStream发生,因此您应该实现自己的逻辑或使用一些外部类。这是一篇解释MemoryStream和大数据问题的帖子,帖子提供了MemoryStream A replacement for MemoryStream

的替代方法

答案 2 :(得分:1)

我们在团队中遇到了类似的障碍。一些评论者建议开发人员在使用文件时需要更加安全。如果可以直接使用文件系统,则可以这样做,但这并不总是一种选择。

如果像我们需要的那样,希望在应用程序周围传递从文件读取的数据,则不能传递FileStream对象,因为它可以在读取数据之前被处理掉。我们最初使用MemoryStreams来使我们轻松传递数据,但是遇到了同样的问题。

我们使用了几种不同的解决方法来缓解该问题。

我们使用的选项包括:

  • 实施包装器类以将数据存储在多个(由于数组仍限于#include <SDL2/SDL.h> #include <SDL2/SDL_image.h> void save_texture(const char* file_name, SDL_Renderer* renderer, SDL_Texture* texture); SDL_Texture* clipTexture(SDL_Rect rect, SDL_Renderer* renderer, SDL_Texture* source); int main(int argc, const char * argv[]) { SDL_Init(SDL_INIT_VIDEO); IMG_Init(IMG_INIT_PNG); SDL_Surface* surface = IMG_Load("test.png"); SDL_Renderer* renderer = SDL_CreateSoftwareRenderer(surface); SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, surface); SDL_Rect frame_rect = { 189, 243,115, 50 }; SDL_Texture* tex_clip = clipTexture( frame_rect, renderer, texture ); save_texture("test1.png", renderer, tex_clip); SDL_FreeSurface(surface); return 0; } // return a new texture that is a part of the original texture. SDL_Texture* clipTexture(SDL_Rect rect, SDL_Renderer* renderer, SDL_Texture* source) { SDL_Texture* result = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, rect.w, rect.h); SDL_SetRenderTarget(renderer, result); SDL_SetTextureBlendMode(source, SDL_BLENDMODE_NONE); SDL_RenderCopy(renderer, source, &rect, NULL); return result; } // save png to disk void save_texture(const char* file_name, SDL_Renderer* renderer, SDL_Texture* texture) { int width, height; SDL_QueryTexture(texture, NULL, NULL, &width, &height); Uint32 rmask, gmask, bmask, amask; #if SDL_BYTEORDER == SDL_BIG_ENDIAN rmask = 0xff000000; gmask = 0x00ff0000; bmask = 0x0000ff00; amask = 0x000000ff; #else rmask = 0x000000ff; gmask = 0x0000ff00; bmask = 0x00ff0000; amask = 0xff000000; #endif SDL_Surface* surface = SDL_CreateRGBSurface(0, width, height, 32, rmask, gmask, bmask, amask); SDL_RenderReadPixels(renderer, NULL, surface->format->format, surface->pixels, surface->pitch); IMG_SavePNG(surface, file_name); SDL_FreeSurface(surface); } 个条目)byte []对象中,并公开使您几乎可以将它们视为Stream的方法。我们仍然不惜一切代价避免这种情况。
  • 使用某种“令牌”来传递对数据位置的引用,然后等待“及时”在应用程序中加载数据。

答案 3 :(得分:-1)

我建议查看这个项目。

http://www.codeproject.com/Articles/348590/A-replacement-for-MemoryStream

我认为内存流的问题来自这样一个事实:在它下面所有它们仍然是单个字节[]的花哨包装器,因此仍受.net要求所有对象即使在64位也必须小于2gb的要求程式。上面的实现将byte []分成几个不同的byte [] s。