def write(self, map, fileName): # Open up a temporary file for saving the level. file = QSaveFile(fileName) if (not file.open(QIODevice.WriteOnly)): self.mError = self.tr("Could not open temporary file for writing.") return False # Create an output stream for serializing data. out = QDataStream(file) out.setByteOrder(QDataStream.LittleEndian) out.setFloatingPointPrecision(QDataStream.SinglePrecision) # Write out the signature and file header. out.writeInt8(96) # Signature. out.writeInt8(map.layerCount()) ok = False x, ok = Int2(map.property("background_index")) if (not ok): self.mError = self.tr("You must define a background_index property on the map!") return False out.writeInt8(x) # Write out each layer. for i in range(0, map.layerCount()): layer = map.layerAt(i).asTileLayer() if (not layer): self.mError = self.tr("Can't save non-tile layer!") return False if (not self.writeLayer(out, layer)): return False if not file.commit(): self.mError = file.errorString() return False return True
def send(self, command, *args): self._logger.info("GC<<: {}:{}".format(command, args)) ds = QDataStream(self._socket) ds.setByteOrder(QDataStream.LittleEndian) # Header ds.writeUInt32(len(command)) ds.writeRawData(command.encode()) # Chunks ds.writeUInt32(len(args)) for chunk in args: ds.writeRawData(self._packLuaVal(chunk))
def createPath(cls, x, y, fill=Qt.OddEvenFill): # https://code.woboq.org/qt5/qtbase/src/gui/painting/qpainterpath.cpp.html#_ZrsR11QDataStreamR12QPainterPath # http://doc.qt.io/qt-5/qpainterpath.html#ElementType-enum # http://doc.qt.io/qt-5/qt.html#FillRule-enum # QDataStream &QPainterPath::operator>>(QDataStream &s, QPainterPath &p) # offset size type description # 0 4 int32 element count (N) # 4 4 int32 element type (0 -- 3) # 8 8 double x # 16 8 double y # ... # 20*i+ 4 4 int32 element type (0 -- 3) # 20*i+ 8 8 double x # 20*i+16 8 double y # ... # 20*(N-1)+ 4 4 int32 element type (0 -- 3) # 20*(N-1)+ 8 8 double x # 20*(N-1)+16 8 double y # 20*(N-1)+20 4 int32 next starting i (N-1) # 20*(N-1)+24 4 int32 fill rule path = QPainterPath() N = x.shape[0] if N == 0: return path data = np.empty(N + 2, dtype=[('type', '<i4'), ('x', '<f8'), ('y', '<f8')]) data[1]['type'] = 0 data[2:N + 1]['type'] = 1 data[1:N + 1]['x'] = x data[1:N + 1]['y'] = y fpos = 20 * (N + 1) view = data.view(dtype=np.ubyte) view[:16] = 0 view.data[16:20] = struct.pack('<i', N) view.data[fpos:fpos + 8] = struct.pack('<ii', N - 1, int(fill)) buf = QByteArray.fromRawData(view.data[16:fpos + 8]) ds = QDataStream(buf) ds.setByteOrder(ds.LittleEndian) ds >> path return path
def write(self, map, fileName): collisionLayer = None for layer in map.layers(): if layer.name().lower() == "collision": tileLayer = layer.asTileLayer() if tileLayer: if (collisionLayer) : self.mError = self.tr("Multiple collision layers found!") return False collisionLayer = tileLayer if (not collisionLayer) : self.mError = self.tr("No collision layer found!") return False file = QSaveFile(fileName) if (not file.open(QIODevice.WriteOnly)) : self.mError = self.tr("Could not open file for writing.") return False width = collisionLayer.width() height = collisionLayer.height() stream = QDataStream(file) stream.setByteOrder(QDataStream.LittleEndian) stream.writeInt16(width&0xffff) stream.writeInt16(height&0xffff) for y in range(0, height): for x in range(0, width): tile = collisionLayer.cellAt(x, y).tile stream.writeInt8(int(tile and tile.id()> 0)&0xff) if not file.commit(): self.mError = file.errorString() return False return True
def _onReadyRead(self): while self._socket.bytesAvailable() >= 4: ds = QDataStream(self._socket) ds.setByteOrder(QDataStream.LittleEndian) # Header packet if self.header is None: size, = unpack('=l', self._socket.peek(4)) if self._socket.bytesAvailable() < size + 4: return # Omit size ds.readUInt32() self.header = ds.readRawData(size).decode() # Chunks packet else: if self.nchunks == -1: self.nchunks = ds.readUInt32() self.chunks = [] while len(self.chunks) < self.nchunks: chunk = self._readLuaVal(ds) if chunk is None: return self.chunks.append(chunk) # Packet pair reading done. self._logger.info("GC >> : %s : %s", self.header, self.chunks) self.messageReceived.emit(self.header, self.chunks) self.header = None self.nchunks = -1 self.chunks = None
def write(self, map, fileName): # Open up a temporary file for saving the level. file = QSaveFile(fileName) if (not file.open(QIODevice.WriteOnly)): self.mError = self.tr("Could not open temporary file for writing.") return False # Create an output stream for serializing data. out = QDataStream(file) out.setByteOrder(QDataStream.LittleEndian) out.setFloatingPointPrecision(QDataStream.SinglePrecision) # Write out the signature and file header. out.writeInt8(96) # Signature. out.writeInt8(map.layerCount()) ok = False x, ok = Int2(map.property("background_index")) if (not ok): self.mError = self.tr( "You must define a background_index property on the map!") return False out.writeInt8(x) # Write out each layer. for i in range(0, map.layerCount()): layer = map.layerAt(i).asTileLayer() if (not layer): self.mError = self.tr("Can't save non-tile layer!") return False if (not self.writeLayer(out, layer)): return False if not file.commit(): self.mError = file.errorString() return False return True
class QmyMainWindow(QMainWindow): def __init__(self, parent=None): super().__init__(parent) #调用父类构造函数,创建窗体 self.ui = Ui_MainWindow() #创建UI对象 self.ui.setupUi(self) #构造UI界面 self.ui.groupBox.setEnabled(False) self.ui.actSaveALL.setEnabled(False) self.ui.actReadALL.setEnabled(False) self.__testFileName = "" self.__typeSize = { "char": 1, "bool": 1, "int8": 1, "uint8": 1, "int16": 2, "uint16": 2, "int32": 4, "uint32": 4, "int64": 8, "uint64": 8, "int": 4, "uint": 4, "float": 4, "single": 4, "double": 8 } ## ==============自定义功能函数============ def __iniWrite(self): ##开始写文件操作 self.fileDevice = QFile(self.__testFileName) #创建文件对象 if not self.fileDevice.open(QIODevice.WriteOnly): del self.fileDevice #删除对象 return False self.fileStream = QDataStream(self.fileDevice) self.fileStream.setVersion(QDataStream.Qt_5_12) #设置流版本号,写入和读取的版本号要兼容 if self.ui.radio_BigEndian.isChecked(): self.fileStream.setByteOrder(QDataStream.BigEndian) else: self.fileStream.setByteOrder(QDataStream.LittleEndian) if self.ui.radio_Single.isChecked(): #必须要设置,float和double都按照这个精度 self.fileStream.setFloatingPointPrecision( QDataStream.SinglePrecision) else: self.fileStream.setFloatingPointPrecision( QDataStream.DoublePrecision) return True def __delFileStream(self): ##结束写文件操作 self.fileDevice.close() del self.fileStream del self.fileDevice def __iniRead(self): ##开始写文件操作 if not QFile.exists(self.__testFileName): QMessageBox.critical(self, "错误", "文件不存在") return False self.fileDevice = QFile(self.__testFileName) #创建文件对象 if not self.fileDevice.open(QIODevice.ReadOnly): del self.fileDevice #删除对象 return False self.fileStream = QDataStream(self.fileDevice) self.fileStream.setVersion(QDataStream.Qt_5_12) #设置版本号,写入和读取的版本号要兼容 if self.ui.radio_BigEndian.isChecked(): self.fileStream.setByteOrder(QDataStream.BigEndian) else: self.fileStream.setByteOrder(QDataStream.LittleEndian) if self.ui.radio_Single.isChecked(): #必须要设置,float和double都按照这个精度 self.fileStream.setFloatingPointPrecision( QDataStream.SinglePrecision) else: self.fileStream.setFloatingPointPrecision( QDataStream.DoublePrecision) return True ## ==========由connectSlotsByName() 自动连接的槽函数================== @pyqtSlot() def on_btnFile_clicked(self): curPath = QDir.currentPath() #获取系统当前目录 title = "选择文件" #对话框标题 filt = "原始数据文件(*.raw)" #文件过滤器 fileName, flt = QFileDialog.getSaveFileName(self, title, curPath, filt) if (fileName == ""): return self.__testFileName = fileName #测试用文件 self.ui.editFilename.setText(fileName) self.ui.groupBox.setEnabled(True) self.ui.actSaveALL.setEnabled(True) self.ui.actReadALL.setEnabled(True) @pyqtSlot() ##写 int8 def on_btnInt8_Write_clicked(self): Value = self.ui.spin_Int8.value() # Python的int类型 if self.__iniWrite(): try: bts = struct.pack('b', Value) # 'b'=signed char=int8 ## writeRawData(self, bytes) -> int self.fileStream.writeRawData(bts) except Exception as e: print(e) QMessageBox.critical(self, "写int8过程出现错误", str(e)) finally: self.__delFileStream() @pyqtSlot() ##读 int8 def on_btnInt8_Read_clicked(self): if self.__iniRead(): ##readRawData(self, int) -> bytes try: bts = self.fileStream.readRawData(self.__typeSize["int8"]) ## unpack(fmt, buffer) -> (v1, v2, ...) Value, = struct.unpack('b', bts) # 'b'=signed char=int8 self.ui.edit_Int8.setText("%d" % Value) except Exception as e: QMessageBox.critical(self, "读int8过程出现错误", str(e)) finally: self.__delFileStream() @pyqtSlot() ##写 uint8 def on_btnUInt8_Write_clicked(self): Value = self.ui.spin_UInt8.value() if self.__iniWrite(): try: bts = struct.pack('B', Value) # 'B'=unsigned char=uint8 self.fileStream.writeRawData(bts) except Exception as e: QMessageBox.critical(self, "写uint8过程出现错误", str(e)) finally: self.__delFileStream() @pyqtSlot() ##读 uint8 def on_btnUInt8_Read_clicked(self): if self.__iniRead(): try: bts = self.fileStream.readRawData(self.__typeSize["uint8"]) Value, = struct.unpack('B', bts) # 'B'=unsigned char=uint8 self.ui.edit_UInt8.setText("%d" % Value) except Exception as e: QMessageBox.critical(self, "读uint8过程出现错误", str(e)) finally: self.__delFileStream() @pyqtSlot() ##写 int16 def on_btnInt16_Write_clicked(self): Value = self.ui.spin_Int16.value() if self.__iniWrite(): try: bts = struct.pack('h', Value) # 'h'=short, 2字节,=int16 self.fileStream.writeRawData(bts) except Exception as e: QMessageBox.critical(self, "写int16过程出现错误", str(e)) finally: self.__delFileStream() @pyqtSlot() ##读 int16 def on_btnInt16_Read_clicked(self): if self.__iniRead(): try: bts = self.fileStream.readRawData(self.__typeSize["int16"]) Value, = struct.unpack('h', bts) # 'h'=short, 2字节,=int16 self.ui.edit_Int16.setText("%d" % Value) except Exception as e: QMessageBox.critical(self, "读int16过程出现错误", str(e)) finally: self.__delFileStream() @pyqtSlot() ##写 uint16 def on_btnUInt16_Write_clicked(self): Value = self.ui.spin_UInt16.value() if self.__iniWrite(): try: bts = struct.pack('H', Value) # 'H'=unsigned short, 2字节=uint16 self.fileStream.writeRawData(bts) except Exception as e: QMessageBox.critical(self, "写uint16过程出现错误", str(e)) finally: self.__delFileStream() @pyqtSlot() ##读 uint16 def on_btnUIn16_Read_clicked(self): if self.__iniRead(): try: bts = self.fileStream.readRawData(self.__typeSize["uint16"]) Value, = struct.unpack('H', bts) # 'H'=unsigned short, 2字节,=uint16 self.ui.edit_UInt16.setText("%d" % Value) except Exception as e: QMessageBox.critical(self, "读uint16过程出现错误", str(e)) finally: self.__delFileStream() @pyqtSlot() ##写 int32 def on_btnInt32_Write_clicked(self): Value = self.ui.spin_Int32.value() if self.__iniWrite(): try: bts = struct.pack('>l', Value) # '>l'=大字节序 int32 self.fileStream.writeRawData(bts) except Exception as e: QMessageBox.critical(self, "写int32过程出现错误", str(e)) finally: self.__delFileStream() @pyqtSlot() ##读 int32 def on_btnInt32_Read_clicked(self): if self.__iniRead(): try: bts = self.fileStream.readRawData(self.__typeSize["int32"]) Value, = struct.unpack('>l', bts) # '>l'= 大字节序int32 self.ui.edit_Int32.setText("%d" % Value) except Exception as e: QMessageBox.critical(self, "读int32过程出现错误", str(e)) finally: self.__delFileStream() @pyqtSlot() ##写 int64 def on_btnInt64_Write_clicked(self): Value = self.ui.spin_Int64.value() #Python的int类型 if self.__iniWrite(): try: bts = struct.pack('q', Value) # 'q'= long long, 8字节=int64 self.fileStream.writeRawData(bts) except Exception as e: QMessageBox.critical(self, "写int64过程出现错误", str(e)) finally: self.__delFileStream() @pyqtSlot() ##读 int64 def on_btnInt64_Read_clicked(self): if self.__iniRead(): try: bts = self.fileStream.readRawData(self.__typeSize["int64"]) Value, = struct.unpack('q', bts) # 'q'= long long, 8字节=int64 self.ui.edit_Int64.setText("%d" % Value) except Exception as e: QMessageBox.critical(self, "读int64过程出现错误", str(e)) finally: self.__delFileStream() @pyqtSlot() ##写 int def on_btnInt_Write_clicked(self): Value = self.ui.spin_Int.value() if self.__iniWrite(): try: bts = struct.pack('i', Value) # 'i'= int, 4字节=int self.fileStream.writeRawData(bts) except Exception as e: QMessageBox.critical(self, "写int过程出现错误", str(e)) finally: self.__delFileStream() @pyqtSlot() ##读 int def on_btnInt_Read_clicked(self): if self.__iniRead(): try: bts = self.fileStream.readRawData(self.__typeSize["int"]) Value, = struct.unpack('i', bts) # 'i'= int, 4字节=int self.ui.edit_Int.setText("%d" % Value) except Exception as e: QMessageBox.critical(self, "读int过程出现错误", str(e)) finally: self.__delFileStream() @pyqtSlot() ##写 bool def on_btnBool_Write_clicked(self): Value = self.ui.chkBox_In.isChecked() if self.__iniWrite(): bts = struct.pack('?', Value) # '?'= bool, 1字节 self.fileStream.writeRawData(bts) self.__delFileStream() @pyqtSlot() ##读 bool def on_btnBool_Read_clicked(self): if self.__iniRead(): bts = self.fileStream.readRawData(self.__typeSize["bool"]) Value, = struct.unpack('?', bts) # '?'= bool, 1字节 self.ui.chkBox_Out.setChecked(Value) self.__delFileStream() @pyqtSlot() ##写 float def on_btnFloat_Write_clicked(self): Value = self.ui.spin_Float.value() #float型 if self.__iniWrite(): try: bts = struct.pack('f', Value) # 'f'= float, 4字节 self.fileStream.writeRawData(bts) except Exception as e: QMessageBox.critical(self, "写float过程出现错误", str(e)) finally: self.__delFileStream() @pyqtSlot() ##读 float def on_btnFloat_Read_clicked(self): if self.__iniRead(): try: bts = self.fileStream.readRawData(self.__typeSize["float"]) Value, = struct.unpack('f', bts) # 'f'= float, 4字节 self.ui.edit_Float.setText("%.4f" % Value) except Exception as e: QMessageBox.critical(self, "读float过程出现错误", str(e)) finally: self.__delFileStream() @pyqtSlot() ##写 double def on_btnDouble_Write_clicked(self): Value = self.ui.spin_Double.value() if self.__iniWrite(): try: bts = struct.pack('d', Value) # 'd'= double, 8字节=double self.fileStream.writeRawData(bts) except Exception as e: QMessageBox.critical(self, "写double过程出现错误", str(e)) finally: self.__delFileStream() @pyqtSlot() ##读 double def on_btnDouble_Read_clicked(self): if self.__iniRead(): try: bts = self.fileStream.readRawData(self.__typeSize["double"]) Value, = struct.unpack('d', bts) # 'd'= double, 8字节 self.ui.edit_Double.setText("%.4f" % Value) except Exception as e: QMessageBox.critical(self, "读double过程出现错误", str(e)) finally: self.__delFileStream() ## BigEndian和LittleEndian会影响字符串前面表示长度的整数的存储顺序 @pyqtSlot() ## writeBytes写 String def on_btnStr_Write_clicked(self): strV = self.ui.editStr_In.text() #str类型 if self.__iniWrite(): bts = bytes(strV, encoding="utf-8") #转换为bytes类型 self.fileStream.writeBytes( bts) #writeBytes(self, bytes) -> QDataStream self.__delFileStream() @pyqtSlot() ## readBytes读 String def on_btnStr_Read_clicked(self): if self.__iniRead(): try: Value = self.fileStream.readBytes() #readBytes(self) -> bytes strV = Value.decode("utf-8") #从bytes类型解码为字符串,utf-8码 self.ui.editStr_Out.setText(strV) except Exception as e: QMessageBox.critical(self, "读String过程出现错误", str(e)) finally: self.__delFileStream() @pyqtSlot() ## writeRawData 写String, 未知长度无法读出 def on_btnStr_WriteRaw_clicked(self): strV = self.ui.editStr_RawIn.text() #str类型 if self.__iniWrite(): bts = bytes(strV, encoding="utf-8") #转换为bytes类型 self.fileStream.writeRawData(bts) self.__delFileStream() @pyqtSlot() ##读出编辑框全清空 def on_actClearOutput_triggered(self): self.ui.edit_Int8.clear() self.ui.edit_UInt8.clear() self.ui.edit_Int16.clear() self.ui.edit_UInt16.clear() self.ui.edit_Int32.clear() self.ui.edit_Int64.clear() self.ui.edit_Int.clear() self.ui.edit_Float.clear() self.ui.edit_Double.clear() self.ui.editStr_Out.clear() @pyqtSlot() ##连续写入文件 def on_actSaveALL_triggered(self): if not self.__iniWrite(): QMessageBox.critical(self, "错误", "为写入打开文件时出错") return #数据写入部分 Value = self.ui.spin_Int8.value() bts = struct.pack('b', Value) # 'b'=signed char, int8 self.fileStream.writeRawData(bts) Value = self.ui.spin_UInt8.value() bts = struct.pack('B', Value) # 'B'=unsigned char, uint8 self.fileStream.writeRawData(bts) Value = self.ui.spin_Int16.value() bts = struct.pack('h', Value) # 'h'=short, int16 self.fileStream.writeRawData(bts) Value = self.ui.spin_UInt16.value() bts = struct.pack('H', Value) # 'H'=unsigned short, uint16 self.fileStream.writeRawData(bts) Value = self.ui.spin_Int32.value() bts = struct.pack('l', Value) # 'l'= long, 4字节,int32 self.fileStream.writeRawData(bts) Value = self.ui.spin_Int64.value() bts = struct.pack('q', Value) # 'q'= long long, 8字节int64 self.fileStream.writeRawData(bts) Value = self.ui.spin_Int.value() bts = struct.pack('i', Value) # 'i'= int, 4字节int self.fileStream.writeRawData(bts) Value = self.ui.chkBox_In.isChecked() bts = struct.pack('?', Value) # '?'= bool, 1字节 self.fileStream.writeRawData(bts) Value = self.ui.spin_Float.value() bts = struct.pack('f', Value) # 'f'= float, 4字节 self.fileStream.writeRawData(bts) Value = self.ui.spin_Double.value() bts = struct.pack('d', Value) # 'd'= double, 8字节 self.fileStream.writeRawData(bts) strV = self.ui.editStr_In.text() #str类型 bts = bytes(strV, encoding="utf-8") #转换为bytes类型 self.fileStream.writeBytes(bts) #数据写入完成 self.__delFileStream() QMessageBox.information(self, "消息", "数据连续写入完成.") @pyqtSlot() ##连续读取文件 def on_actReadALL_triggered(self): if not self.__iniRead(): QMessageBox.critical(self, "错误", "为读取打开文件时出错") return #数据读取部分 bts = self.fileStream.readRawData(self.__typeSize["int8"]) Value, = struct.unpack('b', bts) # 'b'=signed char,int8 self.ui.edit_Int8.setText("%d" % Value) bts = self.fileStream.readRawData(self.__typeSize["uint8"]) Value, = struct.unpack('B', bts) # 'B'=unsigned char self.ui.edit_UInt8.setText("%d" % Value) bts = self.fileStream.readRawData(self.__typeSize["int16"]) Value, = struct.unpack('h', bts) # 'h'=short, 2字节 self.ui.edit_Int16.setText("%d" % Value) bts = self.fileStream.readRawData(self.__typeSize["uint16"]) Value, = struct.unpack('H', bts) # 'H'=unsigned short, 2字节 self.ui.edit_UInt16.setText("%d" % Value) bts = self.fileStream.readRawData(self.__typeSize["int32"]) Value, = struct.unpack('l', bts) # 'l'= long, 4字节 self.ui.edit_Int32.setText("%d" % Value) bts = self.fileStream.readRawData(self.__typeSize["int64"]) Value, = struct.unpack('q', bts) # 'q'= long long, 8字节 self.ui.edit_Int64.setText("%d" % Value) bts = self.fileStream.readRawData(self.__typeSize["int"]) Value, = struct.unpack('i', bts) # 'i'= int, 4字节 self.ui.edit_Int.setText("%d" % Value) bts = self.fileStream.readRawData(self.__typeSize["bool"]) Value, = struct.unpack('?', bts) # '?'= bool, 1字节 self.ui.chkBox_Out.setChecked(Value) bts = self.fileStream.readRawData(self.__typeSize["float"]) Value, = struct.unpack('f', bts) # 'f'= float, 4字节 self.ui.edit_Float.setText("%.4f" % Value) bts = self.fileStream.readRawData(self.__typeSize["double"]) Value, = struct.unpack('d', bts) # 'd'= double, 8字节 self.ui.edit_Double.setText("%.4f" % Value) Value = self.fileStream.readBytes() # bytes类型 strV = Value.decode("utf-8") #从bytes解码为字符串,utf-8码 self.ui.editStr_Out.setText(strV) #数据写入完成 self.__delFileStream() QMessageBox.information(self, "消息", "数据连续读取完成.")
def read(self, fileName): # Read data. file = QFile(fileName) if (not file.open(QIODevice.ReadOnly)): self.mError = self.tr("Cannot open Replica Island map file!") return 0 _in = QDataStream(file) _in.setByteOrder(QDataStream.LittleEndian) _in.setFloatingPointPrecision(QDataStream.SinglePrecision) # Parse file header. mapSignature = _in.readUInt8() layerCount = _in.readUInt8() backgroundIndex = _in.readUInt8() if (_in.status() == QDataStream.ReadPastEnd or mapSignature != 96): self.mError = self.tr("Can't parse file header!") return 0 # Create our map, setting width and height to 0 until we load a layer. map = Map(Map.Orientation.Orthogonal, 0, 0, 32, 32) map.setProperty("background_index", QString.number(backgroundIndex)) # Load our Tilesets. typeTilesets = QVector() tileIndexTilesets = QVector() self.loadTilesetsFromResources(map, typeTilesets, tileIndexTilesets) # Load each of our layers. for i in range(layerCount): # Parse layer header. _type = _in.readUInt8() tileIndex = _in.readUInt8() scrollSpeed = _in.readFloat() levelSignature = _in.readUInt8() width = _in.readUInt32() height = _in.readUInt32() if (_in.status() == QDataStream.ReadPastEnd or levelSignature != 42): self.mError = self.tr("Can't parse layer header!") return 0 # Make sure our width and height are consistent. if (map.width() == 0): map.setWidth(width) if (map.height() == 0): map.setHeight(height) if (map.width() != width or map.height() != height): self.mError = self.tr("Inconsistent layer sizes!") return 0 # Create a layer object. layer = TileLayer(self.layerTypeToName(_type), 0, 0, width, height) layer.setProperty("type", QString.number(_type)) layer.setProperty("tile_index", QString.number(tileIndex)) layer.setProperty("scroll_speed", QString.number(scrollSpeed, 'f')) map.addLayer(layer) # Look up the tileset for this layer. tileset = tilesetForLayer(_type, tileIndex, typeTilesets, tileIndexTilesets) # Read our tile data all at once. #tileData = QByteArray(width*height, b'\x00') bytesNeeded = width*height tileData = _in.readRawData(bytesNeeded) bytesRead = len(tileData) if (bytesRead != bytesNeeded): self.mError = self.tr("File ended in middle of layer!") return 0 i = 0 # Add the tiles to our layer. for y in range(0, height): for x in range(0, width): tile_id = tileData[i]&0xff i += 1 if (tile_id != 255): tile = tileset.tileAt(tile_id) layer.setCell(x, y, Cell(tile)) # Make sure we read the entire *.bin file. if (_in.status() != QDataStream.Ok or not _in.atEnd()): self.mError = self.tr("Unexpected data at end of file!") return 0 return map
class QmyMainWindow(QMainWindow): def __init__(self, parent=None): super().__init__(parent) #调用父类构造函数,创建窗体 self.ui=Ui_MainWindow() #创建UI对象 self.ui.setupUi(self) #构造UI界面 self.ui.groupBox.setEnabled(False) self.ui.actSaveALL.setEnabled(False) self.ui.actReadALL.setEnabled(False) self.setWindowTitle("二进制文件流化读写") self.__testFileName="" #测试用文件的文件名 ## ==============自定义功能函数============ def __iniWrite(self): ##初始化写文件操作 self.fileDevice=QFile(self.__testFileName) #创建文件对象 if not self.fileDevice.open(QIODevice.WriteOnly): del self.fileDevice #删除对象 return False self.fileStream=QDataStream(self.fileDevice) #流对象 self.fileStream.setVersion(QDataStream.Qt_5_12) #设置版本号,写入和读取的版本号要兼容 if self.ui.radio_BigEndian.isChecked(): self.fileStream.setByteOrder(QDataStream.BigEndian) else: self.fileStream.setByteOrder(QDataStream.LittleEndian) ##必须要设置精度,float和double都按照这个精度 precision=QDataStream.DoublePrecision if self.ui.radio_Single.isChecked(): precision=QDataStream.SinglePrecision self.fileStream.setFloatingPointPrecision(precision) return True def __delFileStream(self): ##结束写文件操作 self.fileDevice.close() del self.fileStream del self.fileDevice def __iniRead(self): ##开始读文件操作 if not QFile.exists(self.__testFileName): QMessageBox.critical(self,"错误","文件不存在") return False self.fileDevice=QFile(self.__testFileName) #创建文件对象 if not self.fileDevice.open(QIODevice.ReadOnly): del self.fileDevice #删除对象 return False self.fileStream=QDataStream(self.fileDevice) self.fileStream.setVersion(QDataStream.Qt_5_12) #设置流版本号,写入和读取的版本号要兼容 if self.ui.radio_BigEndian.isChecked(): self.fileStream.setByteOrder(QDataStream.BigEndian) else: self.fileStream.setByteOrder(QDataStream.LittleEndian) ##必须要设置精度,float和double都按照这个精度 precision=QDataStream.DoublePrecision if self.ui.radio_Single.isChecked(): precision=QDataStream.SinglePrecision self.fileStream.setFloatingPointPrecision(precision) return True ## ==========由connectSlotsByName() 自动连接的槽函数================== @pyqtSlot() ##选择测试用文件 def on_btnFile_clicked(self): curPath=QDir.currentPath() #当前目录 title="选择文件" #对话框标题 filt="流数据文件(*.stream)" #文件过滤器 fileName,flt=QFileDialog.getSaveFileName(self,title,curPath,filt) if (fileName == ""): return self.__testFileName=fileName #测试用文件 self.ui.editFilename.setText(fileName) self.ui.groupBox.setEnabled(True) self.ui.actSaveALL.setEnabled(True) self.ui.actReadALL.setEnabled(True) @pyqtSlot() ##写 int8 def on_btnInt8_Write_clicked(self): Value=self.ui.spin_Int8.value() #Python int if self.__iniWrite(): try: self.fileStream.writeInt8(Value) except Exception as e: QMessageBox.critical(self, "writeInt8()出现错误", str(e)) finally: self.__delFileStream() @pyqtSlot() ##读 int8 def on_btnInt8_Read_clicked(self): if self.__iniRead(): Value=self.fileStream.readInt8() self.ui.edit_Int8.setText("%d"%Value) self.__delFileStream() @pyqtSlot() ##写 uint8 def on_btnUInt8_Write_clicked(self): Value=self.ui.spin_UInt8.value() if self.__iniWrite(): try: self.fileStream.writeUInt8(Value) except Exception as e: QMessageBox.critical(self, "writeUInt8()出现错误", str(e)) finally: self.__delFileStream() @pyqtSlot() ##读 uint8 def on_btnUInt8_Read_clicked(self): if self.__iniRead(): Value=self.fileStream.readUInt8() self.ui.edit_UInt8.setText("%d"%Value) self.__delFileStream() @pyqtSlot() ##写int16 def on_btnInt16_Write_clicked(self): Value=self.ui.spin_Int16.value() #Python的int if self.__iniWrite(): try: self.fileStream.writeInt16(Value) #以int16类型写入文件 except Exception as e: QMessageBox.critical(self, "writeInt16()发生错误", str(e)) finally: self.__delFileStream() ## print("finally被执行") @pyqtSlot() ##读 int16 def on_btnInt16_Read_clicked(self): if self.__iniRead(): try: Value=self.fileStream.readInt16() self.ui.edit_Int16.setText("%d"%Value) except Exception as e: QMessageBox.critical(self, "readInt16()发生错误", str(e)) finally: self.__delFileStream() ## print("finally被执行") @pyqtSlot() ##写 uint16 def on_btnUInt16_Write_clicked(self): Value=self.ui.spin_UInt16.value() if self.__iniWrite(): try: self.fileStream.writeUInt16(Value) except Exception as e: QMessageBox.critical(self, "writeUInt16()发生错误", str(e)) finally: self.__delFileStream() @pyqtSlot() ##读 uint16 def on_btnUIn16_Read_clicked(self): if self.__iniRead(): Value=self.fileStream.readUInt16() self.ui.edit_UInt16.setText("%d"%Value) self.__delFileStream() @pyqtSlot() ##写 int32 def on_btnInt32_Write_clicked(self): Value=self.ui.spin_Int32.value() if self.__iniWrite(): try: self.fileStream.writeInt32(Value) except Exception as e: QMessageBox.critical(self, "writeInt32()发生错误", str(e)) finally: self.__delFileStream() @pyqtSlot() ##读 int32 def on_btnInt32_Read_clicked(self): if self.__iniRead(): Value=self.fileStream.readInt32() self.ui.edit_Int32.setText("%d"%Value) self.__delFileStream() @pyqtSlot() ##写 int64 def on_btnInt64_Write_clicked(self): Value=self.ui.spin_Int64.value() if self.__iniWrite(): try: self.fileStream.writeInt64(Value) except Exception as e: QMessageBox.critical(self, "writeInt64()发生错误", str(e)) finally: self.__delFileStream() @pyqtSlot() ##读 int64 def on_btnInt64_Read_clicked(self): if self.__iniRead(): Value=self.fileStream.readInt64() self.ui.edit_Int64.setText("%d"%Value) self.__delFileStream() @pyqtSlot() ##写 int def on_btnInt_Write_clicked(self): Value=self.ui.spin_Int.value() if self.__iniWrite(): try: self.fileStream.writeInt(Value) except Exception as e: QMessageBox.critical(self, "writeInt()发生错误", str(e)) finally: self.__delFileStream() @pyqtSlot() ##读 int def on_btnInt_Read_clicked(self): if self.__iniRead(): Value=self.fileStream.readInt() self.ui.edit_Int.setText("%d"%Value) self.__delFileStream() @pyqtSlot() ##写 bool def on_btnBool_Write_clicked(self): Value=self.ui.chkBox_In.isChecked() #bool型 if self.__iniWrite(): self.fileStream.writeBool(Value) self.__delFileStream() @pyqtSlot() ##读 bool def on_btnBool_Read_clicked(self): if self.__iniRead(): Value=self.fileStream.readBool() #bool型 self.ui.chkBox_Out.setChecked(Value) self.__delFileStream() @pyqtSlot() ##写 float def on_btnFloat_Write_clicked(self): Value=self.ui.spin_Float.value() if self.__iniWrite(): try: self.fileStream.writeFloat(Value) except Exception as e: QMessageBox.critical(self, "writeFloat()发生错误", str(e)) finally: self.__delFileStream() @pyqtSlot() ##读 float def on_btnFloat_Read_clicked(self): if self.__iniRead(): try: Value=self.fileStream.readFloat() self.ui.edit_Float.setText("%.4f"%Value) except Exception as e: QMessageBox.critical(self, "writeFloat()发生错误", str(e)) finally: self.__delFileStream() @pyqtSlot() ##写 double def on_btnDouble_Write_clicked(self): Value=self.ui.spin_Double.value() if self.__iniWrite(): try: self.fileStream.writeDouble(Value) except Exception as e: QMessageBox.critical(self, "writeDouble()发生错误", str(e)) finally: self.__delFileStream() @pyqtSlot() ##读 double def on_btnDouble_Read_clicked(self): if self.__iniRead(): try: Value=self.fileStream.readDouble() self.ui.edit_Double.setText("%.4f"%Value) except Exception as e: QMessageBox.critical(self, "readDouble()发生错误", str(e)) finally: self.__delFileStream() @pyqtSlot() ##写 QString,与Python的str兼容 def on_btnQStr_Write_clicked(self): Value=self.ui.editQStr_In.text() if self.__iniWrite(): try: self.fileStream.writeQString(Value) except Exception as e: QMessageBox.critical(self, "writeQString()发生错误", str(e)) finally: self.__delFileStream() @pyqtSlot() ##读 QString,与Python的str兼容 def on_btnQStr_Read_clicked(self): if self.__iniRead(): try: Value=self.fileStream.readQString() self.ui.editQStr_Out.setText(Value) except Exception as e: QMessageBox.critical(self, "readQString()发生错误", str(e)) finally: self.__delFileStream() @pyqtSlot() ##写 String def on_btnStr_Write_clicked(self): strV=self.ui.editStr_In.text() #str类型 if self.__iniWrite(): try: bts=bytes(strV,encoding="utf-8") #转换为bytes类型 self.fileStream.writeString(bts) except Exception as e: QMessageBox.critical(self, "写入时发生错误", str(e)) finally: self.__delFileStream() @pyqtSlot() ##读 String def on_btnStr_Read_clicked(self): if self.__iniRead(): try: Value=self.fileStream.readString() #bytes类型 strV=Value.decode("utf-8") #从bytes类型解码为字符串,编码utf-8 self.ui.editStr_Out.setText(strV) except Exception as e: QMessageBox.critical(self, "读取时发生错误", str(e)) finally: self.__delFileStream() ##===字体的写入与读取 @pyqtSlot() ##选择字体 def on_btnFont_In_clicked(self): font=self.ui.btnFont_In.font() font,OK=QFontDialog.getFont(font,self) #选择字体 if OK: self.ui.btnFont_In.setFont(font) @pyqtSlot() ##写 QVariant, QFont def on_btnFont_Write_clicked(self): font=self.ui.btnFont_In.font() #QFont类型 if self.__iniWrite(): self.fileStream.writeQVariant(font) #QFont类型 self.__delFileStream() @pyqtSlot() ##读 QVariant, QFont def on_btnFont_Read_clicked(self): if self.__iniRead(): try: font=self.fileStream.readQVariant() #QFont类型 self.ui.editFont_Out.setFont(font) except Exception as e: QMessageBox.critical(self, "读取时发生错误", str(e)) finally: self.__delFileStream() ##===颜色的写入与读取 @pyqtSlot() ##选择颜色 def on_btnColor_In_clicked(self): plet=self.ui.btnColor_In.palette() #QPalette color=plet.buttonText().color() #QColor color= QColorDialog.getColor(color,self) if color.isValid(): plet.setColor(QPalette.ButtonText,color) self.ui.btnColor_In.setPalette(plet) @pyqtSlot() ##写 QVariant, QColor def on_btnColor_Write_clicked(self): plet=self.ui.btnColor_In.palette() color=plet.buttonText().color() #QColor if self.__iniWrite(): self.fileStream.writeQVariant(color) #QColor self.__delFileStream() @pyqtSlot() ##读 QVariant, QColor def on_btnColor_Read_clicked(self): if self.__iniRead(): try: color=self.fileStream.readQVariant() #读取为QColor类型 plet=self.ui.editColor_Out.palette() plet.setColor(QPalette.Text,color) self.ui.editColor_Out.setPalette(plet) except Exception as e: QMessageBox.critical(self, "读取时发生错误", str(e)) finally: self.__delFileStream() @pyqtSlot() ##读出编辑框全清空 def on_actClearOutput_triggered(self): self.ui.edit_Int8.clear() self.ui.edit_UInt8.clear() self.ui.edit_Int16.clear() self.ui.edit_UInt16.clear() self.ui.edit_Int32.clear() self.ui.edit_Int64.clear() self.ui.edit_Int.clear() self.ui.edit_Float.clear() self.ui.edit_Double.clear() font=self.font() self.ui.editFont_Out.setFont(font) plet=self.palette() self.ui.editColor_Out.setPalette(plet) @pyqtSlot() ##连续写入文件 def on_actSaveALL_triggered(self): if not self.__iniWrite(): QMessageBox.critical(self,"错误","为写入打开文件时出错") return #数据写入部分 Value=self.ui.spin_Int8.value() self.fileStream.writeInt8(Value) #int8 Value=self.ui.spin_UInt8.value() self.fileStream.writeUInt8(Value) #uint8 Value=self.ui.spin_Int16.value() self.fileStream.writeInt16(Value) #int16 Value=self.ui.spin_UInt16.value() self.fileStream.writeUInt16(Value) #uint16 Value=self.ui.spin_Int32.value() self.fileStream.writeInt32(Value) #int32 Value=self.ui.spin_Int64.value() self.fileStream.writeInt64(Value) #int64 Value=self.ui.spin_Int.value() self.fileStream.writeInt(Value) #int Value=self.ui.chkBox_In.isChecked() self.fileStream.writeBool(Value) #bool Value=self.ui.spin_Float.value() self.fileStream.writeFloat(Value) #float Value=self.ui.spin_Double.value() self.fileStream.writeDouble(Value) #double str_Value=self.ui.editQStr_In.text() self.fileStream.writeQString(str_Value) #QString str_Value=self.ui.editStr_In.text() #str类型 bts=bytes(str_Value,encoding="utf-8") #转换为bytes类型 self.fileStream.writeString(bts) font=self.ui.btnFont_In.font() self.fileStream.writeQVariant(font) #QFont plet=self.ui.btnColor_In.palette() color=plet.buttonText().color() self.fileStream.writeQVariant(color) #QColor #数据写入完成 self.__delFileStream() QMessageBox.information(self,"消息","数据连续写入完成.") @pyqtSlot() ##连续读取文件 def on_actReadALL_triggered(self): if not self.__iniRead(): QMessageBox.critical(self,"错误","为读取打开文件时出错") return #数据读取部分 Value=self.fileStream.readInt8() #int8 self.ui.edit_Int8.setText("%d"%Value) Value=self.fileStream.readUInt8() #uint8 self.ui.edit_UInt8.setText("%d"%Value) Value=self.fileStream.readInt16() #int16 self.ui.edit_Int16.setText("%d"%Value) Value=self.fileStream.readUInt16() #uint16 self.ui.edit_UInt16.setText("%d"%Value) Value=self.fileStream.readInt32() #int32 self.ui.edit_Int32.setText("%d"%Value) Value=self.fileStream.readInt64() #int64 self.ui.edit_Int64.setText("%d"%Value) Value=self.fileStream.readInt() #int self.ui.edit_Int.setText("%d"%Value) Value=self.fileStream.readBool() #bool self.ui.chkBox_Out.setChecked(Value) Value=self.fileStream.readFloat() #float self.ui.edit_Float.setText("%.4f"%Value) Value=self.fileStream.readDouble() #double self.ui.edit_Double.setText("%.4f"%Value) str_Value=self.fileStream.readQString() #str self.ui.editQStr_Out.setText(str_Value) byteStr=self.fileStream.readString() #bytes str_Value=byteStr.decode("utf-8") #从bytes类型解码为字符串 self.ui.editStr_Out.setText(str_Value) font=self.fileStream.readQVariant() #QFont self.ui.editFont_Out.setFont(font) color=self.fileStream.readQVariant() #QColor plet=self.ui.editColor_Out.palette() plet.setColor(QPalette.Text,color) self.ui.editColor_Out.setPalette(plet) #数据写入完成 self.__delFileStream() QMessageBox.information(self,"消息","数据连续读取完成.")
def read(self, fileName): # Read data. file = QFile(fileName) if (not file.open(QIODevice.ReadOnly)): self.mError = self.tr("Cannot open Replica Island map file!") return 0 _in = QDataStream(file) _in.setByteOrder(QDataStream.LittleEndian) _in.setFloatingPointPrecision(QDataStream.SinglePrecision) # Parse file header. mapSignature = _in.readUInt8() layerCount = _in.readUInt8() backgroundIndex = _in.readUInt8() if (_in.status() == QDataStream.ReadPastEnd or mapSignature != 96): self.mError = self.tr("Can't parse file header!") return 0 # Create our map, setting width and height to 0 until we load a layer. map = Map(Map.Orientation.Orthogonal, 0, 0, 32, 32) map.setProperty("background_index", QString.number(backgroundIndex)) # Load our Tilesets. typeTilesets = QVector() tileIndexTilesets = QVector() self.loadTilesetsFromResources(map, typeTilesets, tileIndexTilesets) # Load each of our layers. for i in range(layerCount): # Parse layer header. _type = _in.readUInt8() tileIndex = _in.readUInt8() scrollSpeed = _in.readFloat() levelSignature = _in.readUInt8() width = _in.readUInt32() height = _in.readUInt32() if (_in.status() == QDataStream.ReadPastEnd or levelSignature != 42): self.mError = self.tr("Can't parse layer header!") return 0 # Make sure our width and height are consistent. if (map.width() == 0): map.setWidth(width) if (map.height() == 0): map.setHeight(height) if (map.width() != width or map.height() != height): self.mError = self.tr("Inconsistent layer sizes!") return 0 # Create a layer object. layer = TileLayer(self.layerTypeToName(_type), 0, 0, width, height) layer.setProperty("type", QString.number(_type)) layer.setProperty("tile_index", QString.number(tileIndex)) layer.setProperty("scroll_speed", QString.number(scrollSpeed, 'f')) map.addLayer(layer) # Look up the tileset for this layer. tileset = tilesetForLayer(_type, tileIndex, typeTilesets, tileIndexTilesets) # Read our tile data all at once. #tileData = QByteArray(width*height, b'\x00') bytesNeeded = width * height tileData = _in.readRawData(bytesNeeded) bytesRead = len(tileData) if (bytesRead != bytesNeeded): self.mError = self.tr("File ended in middle of layer!") return 0 i = 0 # Add the tiles to our layer. for y in range(0, height): for x in range(0, width): tile_id = tileData[i] & 0xff i += 1 if (tile_id != 255): tile = tileset.tileAt(tile_id) layer.setCell(x, y, Cell(tile)) # Make sure we read the entire *.bin file. if (_in.status() != QDataStream.Ok or not _in.atEnd()): self.mError = self.tr("Unexpected data at end of file!") return 0 return map