Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/138.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
visualc&x2B+;2010-转换10 GB字节数组的最快方法? 问题: >在Visual C++中,用10进制字节数组转换为标准字符串的最快方法是什么?_C++_Arrays_File_Byte_Stdstring - Fatal编程技术网

visualc&x2B+;2010-转换10 GB字节数组的最快方法? 问题: >在Visual C++中,用10进制字节数组转换为标准字符串的最快方法是什么?

visualc&x2B+;2010-转换10 GB字节数组的最快方法? 问题: >在Visual C++中,用10进制字节数组转换为标准字符串的最快方法是什么?,c++,arrays,file,byte,stdstring,C++,Arrays,File,Byte,Stdstring,我在做什么:我使用std::fread(…)将一个非常大的文件读入一个大的缓冲区,然后将其格式化为十六进制格式,然后将其转换为std::string。我希望我有道理 我目前正在使用这段代码(不是我写的…),速度很慢 std::string ByteToHexFormatStdStr( __in ::BYTE *ByteArray, __in int ArraySize, __in bool AddSpace ) { ::BYTE Byte = NULL; const char H

我在做什么:我使用std::fread(…)将一个非常大的文件读入一个大的缓冲区,然后将其格式化为十六进制格式,然后将其转换为std::string。我希望我有道理

我目前正在使用这段代码(不是我写的…),速度很慢

std::string ByteToHexFormatStdStr( __in ::BYTE *ByteArray, __in int ArraySize, __in bool AddSpace )
{
    ::BYTE Byte = NULL;
    const char HexCharacters[ 16 ] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
    std::string Return = "";

    for( ::UINT Index = 0; Index < ArraySize; ++ Index )
    {
        Byte = ( ::BYTE )( ByteArray[ Index ] & 0xF0 );
        Byte = ( ::BYTE )( Byte >> 4 );
        Byte = ( ::BYTE )( Byte & 0x0F );
        Return += HexCharacters[ ( int )Byte ];
        Byte = ( ::BYTE )( ByteArray[ Index ] & 0x0F );
        Return += HexCharacters[ ( int )Byte ];

        if( AddSpace ) Return += ' ';
    }

    return ( Return );
}
std::string ByteToHexFormatStdStr(uu in::BYTE*ByteArray,u in int ArraySize,u in bool AddSpace)
{
::BYTE=NULL;
const char HexCharacters[16]={0',1',2',3',4',5',6',7',8',9',A',B',C',D',E',F'};
std::string Return=“”;
对于(::UINT Index=0;Index>4);
字节=(::字节)(字节&0x0F);
返回+=十六进制字符[(int)字节];
字节=(::字节)(字节数组[索引]&0x0F);
返回+=十六进制字符[(int)字节];
if(AddSpace)返回+='';
}
返回(返回);
}

这里的问题不太可能出现在将数据转换为十六进制的例程中

几乎可以肯定的是,你只是使用了太多的内存。输入的每个字节变成两个十六进制字节。如果在它们之间添加空格,则每个输入都有三个字节的输出

如果您从10G的输入开始,这意味着您将产生20G或30G的输出。由于您正在以增量方式扩展目标字符串,因此很有可能它会调整其缓冲区大小,并在数据达到完整的30G字节之前多次复制数据。在调整大小/复制操作期间,旧副本和新副本同时需要内存空间。取决于它调整大小时使用的因素,您正在使用(或试图使用)大约60 GB RAM的更改是好的。除非您实际拥有至少64GB的物理RAM,否则这几乎肯定会非常缓慢

通过读取一个文件并写入另一个文件来进行处理可能会更好。平心而论,除非你的硬盘速度真的很快,否则速度不会很快——而且你更倾向于从一个硬盘读到另一个硬盘写

除非您有64G的物理RAM,否则从一个文件到另一个文件的处理速度几乎肯定会比使用虚拟内存快

std::string ToHex(char input)
{
    const char Hex[] = "0123456789ABCDEF";
    std::string Return;

    Return += Hex[(unsigned)input>>4 & 0xf];
    Return += Hex[(unsigned)input & 0xf];
    return Return;
}

std::transform(std::istream_iterator<char>(infile),
               std::istream_iterator<char>(),
               std::ostream_iterator<std::string>(outfile, ""),
               ToHex);
std::字符串到十六进制(字符输入)
{
常量字符十六进制[]=“0123456789ABCDEF”;
std::字符串返回;
返回+=十六进制[(无符号)输入>>4&0xf];
Return+=Hex[(无符号)输入&0xf];
回归;
}
std::transform(std::istream_迭代器(infle),
std::istream_迭代器(),
std::ostream_迭代器(outfile,“”),
ToHex);
为了使AddSpace的等效值为true,请将第二个参数更改为
ostream\u迭代器
,从
更改为


对于这么大的文件,您可能需要自己处理文件——因为您显然是在Windows上运行的,对于这种大小的文件,您可以直接使用
CreateFile
并指定避免在执行此操作时抖动缓存,从而获得相当多的好处。以4兆字节左右的数据块进行读取,转换成另一个数据块,然后写出结果。如果你有两个(或更多)光盘,这样你就可以从一个读到另一个,你也可以考虑使用重叠的I/O来允许从一个文件读取,写入到另一个,并同时处理。如果您只使用一张光盘,这仍然允许处理和I/O并行进行,但处理速度将比I/O快得多,因此可能无法获得足够的收益来证明所做的努力。

我保证这将在尽可能快的实现范围内:

#define _CRT_DISABLE_PERFCRIT_LOCKS
#include <stdio.h>
#include <io.h>
#include <fcntl.h>

int main(int argc, char **argv) {
    _setmode(fileno(stdin), _O_BINARY);
    _setmode(fileno(stdout), _O_BINARY);

    char hex[] = "0123456789ABCDEF";
    int c;
    while ((c = getchar()) != EOF) {
        putchar(hex[c >> 4]);
        putchar(hex[c & 0xF]);
    }

    return 0;
}
\define\u CRT\u DISABLE\u PERFCRIT\u锁
#包括
#包括
#包括
int main(int argc,字符**argv){
_设置模式(文件号(标准输入),二进制);
_设置模式(文件号(标准输出),\u O\u二进制文件);
字符十六进制[]=“0123456789ABCDEF”;
INTC;
而((c=getchar())!=EOF){
putchar(十六进制[c>>4]);
putchar(十六进制[c&0xF]);
}
返回0;
}
编译并作为
thisprogout
运行

在MSVC++上,stdio操作使用锁定来允许多线程代码中的线程安全行为。对于这个单线程程序,我们不需要它,所以我们用顶行(如上所述)将其关闭,这样可以大大加快速度。对
\u setmode()
的调用打开标准输入和输出流的二进制模式,默认情况下,标准输入和输出流处于文本模式(
\r\n
在输入时转换为
\n
,反之亦然)

它的速度很快,因为stdio使用自己的内部缓冲,所以您不需要每次向操作系统请求一个字符(操作系统在后台另外执行自己的磁盘缓冲)


如果您决定使用C++,则更改<代码>包含<代码> > <代码>包含< /代码>,并使用命名空间STD添加<代码>;<代码>之后。C运行库是标准C++库的一部分,经验表明它比使用IOFFROM快得多,可能是因为它不受区域设置的困扰。

一次添加一个字符到目标字符串,这样可能会相当慢——也许更好地预先分配目标字符串中的空间。(
string::reserve
,假设您使用的是C++11)。除非您有10s的GB内存可用,否则您这样做的任何操作都会非常缓慢--最好是处理文件到文件而不是字符串到字符串。我不记得很清楚,但VC++2010可能有
std::string::reserve
。如果没有,您可能希望使用