2013-04-15 2 views
1

다른 비 Qt 프로그램에서 생성 된 정의 된 구조의 스트리밍 된 바이너리 데이터 (QDataStream)를 처리해야합니다. 나는 그 데이터를 해석하는 가장 좋은 방법이 무엇인지 궁금합니다. 데이터가 다음과 같이 텔레 그램에 구조화되어 있고 (구조 정의가 제공됨) 자신이 변경할 수 없다고 가정 해 보겠습니다.모범 사례 : QDataStream을 해석/처리하는 방법?

4 바이트 헤더 | 2 바이트 시퀀스 번호 | 1 바이트 체크섬 | 10 개 바이트 데이터

나는 다음과 같은 가능성은 "전보"클래스의 데이터를 처리하기 위해 참조

:

  1. 전보 클래스는 개인 QByteArray 멤버 변수가 있습니다. 모든 데이터 (17 바이트)는 readRawData 메서드로 스트림에서 즉시 읽히고 거기에 저장됩니다. 변수는 시퀀스 번호에 대해 return (array.at(4)<<8) + array.at(5)과 같은 공용 메소드를 통해 액세스되고 해석되며 매우 우아하지 않습니다.
  2. Telegram 클래스에는 구조체와 함께 공용 char [17] 멤버 변수가 있습니다. 모든 데이터는 readRawData로 스트림에서 읽어 와서 거기에 저장됩니다. 이후에 변수에 액세스 할 때 이것은 struct에만 적용됩니다 (예 : telegramstruct.squenceNumber). 엔디안과 패딩과 같은 잠재적 인 문제가 있습니다.
  3. Telegram 클래스에는 QString strHeader과 같은 전신 필드에 대한 전용 멤버 변수가 있습니다. 스트림에서 텔레 그램을 읽을 때 데이터는 이러한 변수에 직접 저장됩니다. 읽기는 readRawData 또는 기본 유형 인 >> 연산자로 수행됩니다.

처리 할 데이터가 많으므로 가능한 빨리 코드를 작성해야합니다. MinGW가 설치된 Windows에서 Qt 5.0.1을 사용하고 있습니다.

내 질문 : 위의 솔루션

  • 하나의 모범 사례와 빨리, 또는 더 나은 방법은 무엇입니까?
  • 3 에서처럼 4 바이트, 2 바이트, 1 바이트를 읽는 것보다 한 번에 모두 빠르게 읽는 것과 비슷합니까?
  • 1과 3을 사용하면 제공된 헤더 파일을 정의 된 구조체와 함께 사용할 수 없습니다. 이는 나쁜 습관입니까?
  • QByteArray와 구조체의 "공용체"를 가질 수 있습니까?
  • 솔루션 3으로 체크섬을 어떻게 쉽게 계산할 수 있습니까?

의견과 힌트를 보내 주셔서 감사합니다.

크리스

+0

모든 질문에 답변 할 시간이 없지만 분명히 노조 및 비트 필드 방식을 사용합니다. 비트 필드의 경우 http://publib.boulder.ibm.com/infocenter/macxhelp/v6v81/index.jsp?topic=%2Fcom.ibm.vacpp6m.doc%2Flanguage%2Fref%2Fclrc03defbitf.htm – Matthew

+0

@Matthew 감사합니다. 너의 답. 그러나 비트 필드가있는 구조체는 패딩되므로 적어도 무작위 레이아웃에는 적합하지 않습니다. 기억, 나는 이진 데이터의 구조에 영향을 미칠 수 없습니다. – Chris

답변

2

음, 미안 많은 시간이 코드 예제를 작성하는 것을 해달라고하지만, 간단한 힌트를 제공하기 위해 노력할 것입니다. 1) 성능 문제. 성능 제약 조건을 갖게되면 최적화 할 첫 번째 작업은 데이터가 들어오는 스트림에서 실제로 읽는 양입니다. 그것이 File/Socket/etc 이건간에 그것은 어쨌든 QIODevice입니다. 먼저해야 할 일은 준비된 모든 시도/데이터 수신 통지에서 QIODevice에서 사용 가능한 모든 데이터를 추가하는 일종의 QByteArray를 유지하는 것입니다. 그래서 나는 현재 처리되지 않은 바이트를 보유하고있는 특정 QByteArray m_rawData가 있다고 가정합니다.이 바이트는 전보의 일부가 될 수 있으며 부분적으로 수신 할 수있는 마지막 전보가 될 수 있습니다.

2)이 약 ​​취향에 생성자와 연산자

class Telegram { 
     QString  header; 
     int   sequenceNumber; 
     unsigned char checkSum; 
     QByteArray data; 

     ... 

     bool   checkSumOK(); // check is checksum is OK for provided data 

} 

말 전보 데이터를 보유 전보와 같은 클래스를 만들 것 (당신이 복사 생성자/등)을 구현할 수 있습니다 .. 은 그럼 확장 할 것 이 클래스는 (1)에서 언급 한 임시 버퍼에서 작동하는 QDataStream을 지원하는 (< <, >>) 연산자를 사용합니다.

그래서 일반적으로 가능한 한 빨리 스트림의 데이터를 임시 버퍼로 읽어 들이고 읽기가 완료되면 가능한 많은 텔레 그램 인스턴스만큼 결과 버퍼에서 가져옵니다. QByteArray에 적용된 QDataSteam으로 작업하면 일반적으로 포인터를 이동하는 것과 관련하여 많은 성능상의 영향없이 4 바이트 읽기, 1 바이트 등의 호출을 안전하게 사용할 수 있습니다.

3) 물론 극단적 인 조건에 대해 이야기하는 경우 ... 정렬 된 구조의 맨 위에 원시 데이터의 직접 복사를 만들기 위해 (이전 대답에서 언급 한 것처럼) 유니온을 생각할 수 있지만 그렇게하면 훨씬 더주의 깊은 프로그래밍이 필요합니다. (특히 x32/x64 아치뿐만 아니라 빅/리틀 엔디안 플랫폼도 포함)

+0

답변 해 주셔서 감사합니다. 나는 연산자 >> 구현의 제안을 좋아한다. 그러나, 만약 내가 1)에서 당신을 잘 모르겠다. 그래서 당신이 그것을 확인해 주시겠습니까 :'stream >> telegram;과 같은 것을하는 것이 더 느립니다.'stream.readRawData (tempArray, asMuchAsPossible);'와'tempArray >> 전보;'? – Chris

+1

그렇습니다. 정확히 말하자면, 스트림의 내부 구조로 갈 경우, 모든 << 연산자가 read() 또는 유사한 시스템 호출로 끝나고 오버 헤드가 너무 많다는 것을 알게 될 것이기 때문입니다. 한 번 프로세스 들어오는 데이터. – evilruff