草庐IT

c++ - 具有重叠 I/O 的 FILE_FLAG_NO_BUFFERING - 字节读为零

coder 2024-06-13 原文

我在使用带有重叠 I/O 的标志 FILE_FLAG_NO_BUFFERING 时观察到一个奇怪的行为。 我调用了一系列 ReadFile() 函数调用,稍后使用 GetOverlappedResult() 查询它们的状态。

我所说的奇怪行为是,即使文件句柄良好并且 ReadFile() 调用返回时没有任何错误(预期的 ERROR_IO_PENDING 除外),从 GetOverlappedResult() 调用返回的“字节读取”值是某些文件为零,每次我运行代码时,它都是一组不同的文件。 如果我删除 FILE_FLAG_NO_BUFFERING,事情就会开始正常工作,并且没有字节读取值为零。

下面是我如何使用 FILE_FLAG_NO_BUFFERING 实现重叠 I/O 代码。

long overlappedIO(std::vector<std::string> &filePathNameVectorRef)
{    
    long totalBytesRead = 0;
    DWORD bytesRead = 0;
    DWORD bytesToRead = 0;
    std::map<HANDLE, OVERLAPPED> handleMap;
    HANDLE handle = INVALID_HANDLE_VALUE;
    DWORD accessMode = GENERIC_READ;
    DWORD shareMode = 0;
    DWORD createDisposition = OPEN_EXISTING;
    DWORD flags = FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING;

    DWORD fileSize;
    LARGE_INTEGER li;
    char * buffer;
    BOOL success = false;

    for(unsigned int i=0; i<filePathNameVectorRef.size(); i++)
    {
        const char* filePathName = filePathNameVectorRef[i].c_str();

        handle = CreateFile(filePathName, accessMode, shareMode, NULL, createDisposition, flags, NULL);

        if(handle == INVALID_HANDLE_VALUE){
            fprintf(stdout, "\n Error occured: %d", GetLastError());
            fprintf(stdout," getting handle: %s",filePathName);
            continue;
        }
        GetFileSizeEx(handle, &li);
        fileSize = (DWORD)li.QuadPart;

        bytesToRead = (fileSize/g_bytesPerPhysicalSector)*g_bytesPerPhysicalSector;
        buffer = static_cast<char *>(VirtualAlloc(0, bytesToRead, MEM_COMMIT, PAGE_READWRITE));

        OVERLAPPED overlapped;
        ZeroMemory(&overlapped, sizeof(overlapped));
        OVERLAPPED * lpOverlapped = &overlapped;

        success = ReadFile(handle, buffer, bytesToRead, &bytesRead, lpOverlapped);

        if(!success && GetLastError() != ERROR_IO_PENDING){ 
            fprintf(stdout, "\n Error occured: %d", GetLastError());
            fprintf(stdout, "\n reading file %s",filePathName);
            CloseHandle(handle);
            continue;
        }
        else
            handleMap[handle] = overlapped;
    }

    // Status check and bytes Read value
    for(std::map<HANDLE, OVERLAPPED>::iterator iter = handleMap.begin(); iter != handleMap.end(); iter++)
    {
        HANDLE handle = iter->first;        
        OVERLAPPED * overlappedPtr = &(iter->second);

        success = GetOverlappedResult(handle, overlappedPtr, &bytesRead, TRUE);
        if(success)
        {
                /* bytesRead value in some cases is unexpectedly zero */
                /* no file is of size zero or lesser than 512 bytes(physical volume sector size) */
            totalBytesRead += bytesRead;
            CloseHandle(handle);
        }
    }

    return totalBytesRead;
}

在没有 FILE_FLAG_NO_BUFFERING 的情况下,totalBytesRead 值为 57 MB。带有标志的情况下,totalBytesRead 值远低于 57 MB,并且每次运行代码时都会不断变化,范围从 2 MB 到 15 MB。

最佳答案

当文件大小小于 g_bytesPerPhysicalSector 时,您对 bytesToRead 的计算将产生 0 作为结果。因此,对于小文件,您请求 0 个字节。

关于c++ - 具有重叠 I/O 的 FILE_FLAG_NO_BUFFERING - 字节读为零,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17780227/

有关c++ - 具有重叠 I/O 的 FILE_FLAG_NO_BUFFERING - 字节读为零的更多相关文章

  1. ruby - 具有身份验证的私有(private) Ruby Gem 服务器 - 2

    我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..

  2. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  3. ruby-on-rails - rails : save file from URL and save it to Amazon S3 - 2

    从给定URL下载文件并立即将其上传到AmazonS3的更直接的方法是什么(+将有关文件的一些信息保存到数据库中,例如名称、大小等)?现在,我既不使用Paperclip,也不使用Carrierwave。谢谢 最佳答案 简单明了:require'open-uri'require's3'amazon=S3::Service.new(access_key_id:'KEY',secret_access_key:'KEY')bucket=amazon.buckets.find('image_storage')url='http://www.ex

  4. ruby - 无法让 RSpec 工作—— 'require' : cannot load such file - 2

    我花了三天的时间用头撞墙,试图弄清楚为什么简单的“rake”不能通过我的规范文件。如果您遇到这种情况:任何文件夹路径中都不要有空格!。严重地。事实上,从现在开始,您命名的任何内容都没有空格。这是我的控制台输出:(在/Users/*****/Desktop/LearningRuby/learn_ruby)$rake/Users/*******/Desktop/LearningRuby/learn_ruby/00_hello/hello_spec.rb:116:in`require':cannotloadsuchfile--hello(LoadError) 最佳

  5. ruby CSV : How can I read a tab-delimited file? - 2

    CSV.open(name,"r").eachdo|row|putsrowend我得到以下错误:CSV::MalformedCSVErrorUnquotedfieldsdonotallow\ror\n文件名是一个.txt制表符分隔文件。我是专门做的。我有一个.csv文件,我转到excel,并将文件保存为.txt制表符分隔的文件。所以它是制表符分隔的。CSV.open不应该能够读取制表符分隔的文件吗? 最佳答案 尝试像这样指定字段分隔符:CSV.open("name","r",{:col_sep=>"\t"}).eachdo|row|

  6. 使用 ACL 调用 upload_file 时出现 Ruby S3 "Access Denied"错误 - 2

    我正在尝试编写一个将文件上传到AWS并公开该文件的Ruby脚本。我做了以下事情:s3=Aws::S3::Resource.new(credentials:Aws::Credentials.new(KEY,SECRET),region:'us-west-2')obj=s3.bucket('stg-db').object('key')obj.upload_file(filename)这似乎工作正常,除了该文件不是公开可用的,而且我无法获得它的公共(public)URL。但是当我登录到S3时,我可以正常查看我的文件。为了使其公开可用,我将最后一行更改为obj.upload_file(file

  7. ruby-on-rails - Rails 3.1 中具有相同形式的多个模型? - 2

    我正在使用Rails3.1并在一个论坛上工作。我有一个名为Topic的模型,每个模型都有许多Post。当用户创建新主题时,他们也应该创建第一个Post。但是,我不确定如何以相同的形式执行此操作。这是我的代码:classTopic:destroyaccepts_nested_attributes_for:postsvalidates_presence_of:titleendclassPost...但这似乎不起作用。有什么想法吗?谢谢! 最佳答案 @Pablo的回答似乎有你需要的一切。但更具体地说...首先改变你View中的这一行对此#

  8. Ruby - 如何将消息长度表示为 2 个二进制字节 - 2

    我正在使用Ruby,我正在与一个网络端点通信,该端点在发送消息本身之前需要格式化“header”。header中的第一个字段必须是消息长度,它被定义为网络字节顺序中的2二进制字节消息长度。比如我的消息长度是1024。如何将1024表示为二进制双字节? 最佳答案 Ruby(以及Perl和Python等)中字节整理的标准工具是pack和unpack。ruby的packisinArray.您的长度应该是两个字节长,并且按网络字节顺序排列,这听起来像是n格式说明符的工作:n|Integer|16-bitunsigned,network(bi

  9. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  10. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

随机推荐