将数据块快速附加到另一个数组中

时间:2013-11-05 01:36:14

标签: c++

我正在读取大小为4096的数组寄存器中的文件。

我在循环之外有一个容器数组,我想按顺序“追加”数据块,这是最快最有效的方法吗?

PointRecord4 * AllRegisters = new PointRecord4[ptr->Number_of_Point_records];

    if (ptr->Point_Data_Format_ID == 4)
        switch ((*ptr).Point_Data_Format_ID)
        {
        case 4:
            {
                PointRecord4 registers[4096];
                ULONG32 pointsToRead = 4096;
                ULONG32 pointsLoaded = 0;               
                ULONG32 i;

                for (i = 0; pointsLoaded < ptr->Number_of_Point_records; i += pointsToRead)
                {
                    pointsToRead =  std::min(pointsToRead, ptr->Number_of_Point_records - pointsLoaded);
                    input_file.read(PTR(&registers), sizeof(PointRecord4) * pointsToRead);
                    pointsLoaded += pointsToRead;

                    //Insert registers[4096] into AllRegisters, Appending it
                } 
            } break;
    }

我试图简单地迭代超过4096并且只是推回向量但是这非常慢。

下面是我的完整代码:

#include "vgl.h"
#include <fstream>
#include <iostream>
#include <vector>
#include <string.h>


using namespace std;

#define PTR reinterpret_cast<char *>

#pragma pack(1)
typedef struct LasHeader
{
    char           File_Signature[4];                            // 4 Bytes
    UINT16 FileSourceID;                                         // 2 Bytes
    UINT16 Global_Encoding;                                      // 2 Bytes
    ULONG32  GUID1;                                              // 4 Bytes
    UINT16 GUID2;                                                // 2 Bytes
    UINT16 GUID3;                                                // 2 Bytes
    UCHAR  GUID4[8];                                             // 2 Bytes
    UCHAR  Version_Major;                                        // 1 Bytes
    UCHAR  Version_Minor;                                        // 1 Bytes
    CHAR           System_Identifier[32];                        // 32 Bytes
    CHAR           Generating_Software[32];                      // 32 Bytes
    UINT16 File_Creation_Day_Of_Year;                            // 2 Bytes
    UINT16 File_Creation_Year;                                   // 2 Bytes
    UINT16 Header_Size;                                          // 2 Bytes
    ULONG32 Offset_to_point_data;                                // 4 Bytes
    ULONG32 Number_of_Variable_Length_Records;                   // 4 Bytes
    CHAR Point_Data_Format_ID;                                   // 1 Bytes
    UINT16 Point_Data_Record_Length;                             // 2 Bytes
    ULONG32 Number_of_Point_records;                             // 4 Bytes 
    ULONG32 Number_of_points_by_return[5];                       // 20 Bytes / Verified

    double X_Scale_Factor;                                       // 8 bytes  / Verified
    double Y_Scale_Factor;                                       // 8 bytes
    double Z_Scale_Factor;                                       // 8 bytes
    double X_Offset;                                             // 8 bytes
    double Y_Offset;                                             // 8 bytes
    double Z_Offset;                                             // 8 bytes
    double Max_X;                                                // 8 bytes
    double Min_X;                                                // 8 bytes
    double Max_Y;                                                // 8 bytes
    double Min_Y;                                                // 8 bytes
    double Max_Z;                                                // 8 bytes
    double Min_Z;                                                // 8 bytes

    #ifdef FULLWAVE
        unsigned long long Start_of_Waveform_Data_Packet_Record; // 8 bytes
    #endif

    union
    {
        char* MemoryBlock;
    };

} *header;

struct PointRecord4
{
    UINT32 X;
    UINT32 Y;
    UINT32 Z;
    UINT16 Intensity;
    CHAR BitMask;
    CHAR Classification;
    CHAR ScanAngleRank;
    CHAR UserData;
    UINT16 PointSourceID;
    double GPSTime;
    CHAR WPDI;
    UINT64 WFOffset;
    UINT32 WFPacketSize;
    float WFReturnLocation;
    float WFXt;
    float WFYt;
    float WFZt;
};

extern header ptr = new LasHeader;

HRESULT OpenLasFile(char *path)
{
    HRESULT result;
    ifstream input_file(path, ios::in | ios::binary);
    result = GetLastError();

    input_file.read(PTR(ptr), sizeof(LasHeader));
    result = GetLastError();
    input_file.seekg (ptr->Offset_to_point_data, input_file.beg);

    PointRecord4 * AllRegisters = new PointRecord4[ptr->Number_of_Point_records];

    if (ptr->Point_Data_Format_ID == 4)
        switch ((*ptr).Point_Data_Format_ID)
        {
        case 4:
            {
                PointRecord4 registers[4096];
                ULONG32 pointsToRead = 4096;
                ULONG32 pointsLoaded = 0;               
                ULONG32 i;

                for (i = 0; pointsLoaded < ptr->Number_of_Point_records; i += pointsToRead)
                {
                    pointsToRead =  std::min(pointsToRead, ptr->Number_of_Point_records - pointsLoaded);
                    input_file.read(PTR(&registers), sizeof(PointRecord4) * pointsToRead);
                    pointsLoaded += pointsToRead;

                    //Insert registers[4096] into AllRegisters, Appending it
                } 
            } break;
    }

    input_file.close();

    return result;
}

2 个答案:

答案 0 :(得分:0)

对于您的特定情况,您只需读入目标缓冲区即可保存副本:

input_file.read(AllRegisters + pointsLoaded, sizeof(PointRecord4) * pointsToRead);

在需要复制的其他情况下,memcpy是复制大量POD数据的最佳选择。

答案 1 :(得分:0)

目前还不清楚为什么你不只是直接阅读AllRegisters

但是,我怀疑追加阶段不是的瓶颈。当您以这样的大块读取数据时,使用无缓冲的I / O是值得的。磁盘I / O将是您的限制因素,而不是内存I / O.

请参阅我关于buffered vs unbuffered I/O in C的帖子。

以下是处理unbuffered I/O on std::ifstream

的帖子