Visual C ++读取整个文件

时间:2013-08-23 21:25:09

标签: c++ visual-c++ binary ifstream winsock2

有几天我一直试图将整个PNG读成一个字符串,所以我可以通过winsock2将它上传到服务器,它似乎在几个字符或某种断行后停止读取文件,是否有任何特殊原因和解决方法。

我尝试了很多解决方案,这现在开始让我疯狂。我正在使用的当前代码如下

std::ifstream in ("some.png", ios::in|ios::binary|ios::ate );
std::string contents;
if (in)
{           
    in.seekg(0, in.end);
    contents.resize(in.tellg());
    in.seekg(0, in.beg);
    in.read(&contents[0], contents.size());
    in.close();
    length = contents.size();        
}

我不知道问题可能是什么,因为我对c ++相对较新,我已经通过google拖了几天而没有可行的解决方案。

请帮忙

更新代码发布到服务器

    WSADATA wsa;

        if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
    return;


    SOCKET fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

            if (fd < 0)     
                throw;

            SOCKADDR_IN service;

    service.sin_family    = AF_INET;
    service.sin_port      = htons(80);
    LPHOSTENT host        = gethostbyname("127.0.0.1");

            if (!host)          
                throw;

            service.sin_addr = *((LPIN_ADDR)*host->h_addr_list);

            if (connect(fd, (SOCKADDR *)&service, sizeof(service)) < 0)     
                throw;

    int length ;

    std::ifstream in (CCFileUtils::fullPathFromRelativePath("back.png"), ios::in|ios::binary|ios::ate );
    std::string contents;

            if (in){

            in.seekg(0, in.end);
        contents.resize(in.tellg());
        in.seekg(0, in.beg);
        in.read(&contents[0], contents.size());
        in.close();
        length = contents.size();
    }else

        std::string str =
        "POST /index.php HTTP/1.1\r\n"
        "Host: metapps.co.uk\r\n"
        "Accept: */*\r\n";

        char buffer1 [50];  
        str.append(  "Content-Length: 121\r\n" );
        str.append(  "\r\n" );

        str.append(  "Content-Disposition: form-data; name=\"tmp\";filename=\"photo.png\"\r\n" );
        str.append(  "Content-Type: image/dds\r\n" );
        sprintf (buffer1, "Content-Length: %d\r\n", length);
        str.append( buffer1 );
        str.append( contents    );
        str.append(  "\r\n\x01A\r\n" );

        // send str ...
        send(fd, str.c_str() , strlen( str.c_str() ) +1 , 0);
        char ret[1024];

        recv(fd,ret,strlen(ret),0);

        closesocket(fd);
        WSACleanup();
}

更新2

它与Null终结符字符串和追加方法

有关

如果我这样做

str.append( "he\0llo"   );

服务器只会显示“他”

如果我这样做

str.append( "hello" );

我得到你好,希望这个信息可以带来解决方案

4 个答案:

答案 0 :(得分:3)

    send(fd, str.c_str() , strlen( str.c_str() ) +1 , 0);
        char ret[1024];

strlen( str.c_str() ) +1将告诉您输出中第一个0字节的位置,而不是字符串的长度。最好通过str.size()来获取字符串的长度。


此外,正如WhosCraig mentioned一样,您正在调用strlen(ret),其中ret未初始化。相反,使用

  std::array<char, 1024> ret;
  recv(fd,ret,ret.size(),0);

或者可能更具活力的东西。

答案 1 :(得分:1)

单向 [1]

std::ifstream in("some.png", ios::binary);
std::vector<unsigned char> contents(std::istreambuf_iterator<char>(in), {});

另一个

std::ostringstream oss;
oss << in.rdbuf();
std::string contents = iss.str();

正如其他人所指出的那样,通常没有必要在内存中同时拥有全部内容。它导致可伸缩性问题。如果可能的话,尽量避免使用它。


[1] 如果您的编译器受到标准挑战,请将其分解:

std::istreambuf_iterator<char> f(in), l;
std::vector<unsigned char> contents(f, l);

答案 2 :(得分:0)

您正在使用&contents[0]来获取字符串使用的内部缓冲区的地址。据我所知,在你调用.c_str()之前,不保证这个缓冲区是偶然的,甚至是正确的大小,所以你只是无法传递地址。

对原始二进制数据使用std::vector<char>std::array<char, n>。它们总是保证有顺序缓冲区。

哦,顺便说一句,没有必要将整个文件读入一个大缓冲区。只需逐段阅读即可。

答案 3 :(得分:0)

我解决了!

我发送的标题内容长度是固定长度121

       str.append(  "Content-Length: 121\r\n" );

因此服务器因此将消息体截断为这个长度,我不知道服务器如此认真地使用了这个值,如果它太大也会抛出500错误。

为邮件正文发送正确的长度修复它。

我还将标题与邮件正文分开并使用了

std::vector<char> 

根据@youdontneedtothankme存储邮件正文

感谢所有的回复和评论,帮助我在经历了长达一周的挫折之后找到问题的根源,我的生活现在可以继续了哈哈:)

Stackoverflow FTW!