본문 바로가기
QT and Symbian

QT 파일 읽고 쓰기

by leo21c 2014. 9. 24.

1. Read & Write
 QT에서 파일을 읽고 쓰기 위해서는 QFile과 QDataStream 클래스를 이용해서 처리할 수 있다.

 Text 같은 경우에는 QTextStream 이라는 클래스를 이용하면 편하다.
 참고 자료는 역시 qt-project.org에서 제공하는 document를 보면 된다.
 http://qt-project.org/doc/qt-5/qfile.html

2. 주의 사항
 : QDateStream을 이용해서 binary data를 읽을 때 주의해야 할 부분이 있다. QT는 default로 BigEndian을 사용한다.
 그러나 Windows는 LittleEndian을 사용한다. 그러기 때문에 Windows에서 파일을 읽을 때에는 반듯이 setByteOrder() 함수 세팅을 해줘야 한다.
 꼭 QDataStream::LittleEndian 처리를 잊지 말도록 한다. 

3. QT에서 제공하지 않는 Struct, Class를 Stream 처리하는 방법
 : QDataStream class 자료를 찾아 보면 "Reading and writing other Qt classes" 제목의 단락이 있다. 이 곳의 내용을 참고해서 처리하면 된다.
 간단하게 설명하면 stream operator (>>, <<)를 overload 해서 새로 만들어 사용하라는 것이다.
 
http://qt-project.org/doc/qt-4.8/qdatastream.html

 예를 들어 아래와 같은 Struct가 있다고 해보자.

 struct TKindValue{
    int kind;
    int value;
 };


 위의 구조체를 QDataStream 객체로 처리하기 위해서는 아래와 같은 operator를 overload한 함수를 만들면 된다.

 QDataStream & operator<<(QDataStream& stream, const TKindValue& data)
 {
    stream << data.kind << data.value;
    return stream;
 }
 QDataStream & operator>>(QDataStream& stream, TKindValue& data)
 {
    stream >> data.kind >> data.value;
    return stream;
 }



 위와 같이 만든 함수를 사용하는 cpp의 전역 함수로 만들어서 사용하면 된다.

 stream을 이용해서 처리를 하다보니 이상한 문제가 발생이 되었다. byteorder가 이상하게 꼬이는 문제이다. 왜 발생하는지 원인은 이 글을 쓰고 있는 현재까지 찾지는 못했다. 파일의 앞부분을 처리할 때 LittleEndian으로 처리하면 정상적으로 데이터가 들어왔는데 중간부터는 안되어 다시 BigEndian으로 바꾸니 문제가 없는 것이다. 왜일까? 테스트 한 파일은 C++ Builder를 통해 제작한 윈도우 프로그램에서 저장한 파일이고 QT는 MSVS를 이용해서 윈도우 상에서 파일을 읽은 것이다.
 이런 문제로 아래와 같은 template를 만들어 버렸다. linux에서는 문제가 발생하려나? window에서는 문제가 없었는데 linux에서 처리할 때 재확인을 해봐야 할 것 같다.

template <class T> bool ReadFileFromStream(QDataStream &stream, T &data)
{
	char *buf = 0;
	int nRet = 0, len = 0;
	bool bRet = false;
	len = sizeof(T);
	buf = new char[len];
	memset(buf, 0, len);
	if (buf) {
		nRet = stream.readRawData(buf, len);
		if (nRet == len) {
			memcpy(&data, buf, len);
			bRet = true;
		}
		else bRet = false;
		delete[] buf;
	}
	buf = 0;
	return bRet;
}

위와 같이 처리를 하면 byteorder를 지정하지 않아도 정상적으로 데이터를 읽어왔다.