def _read_file_data(self, message_name_filter_list, read_until=None):
        """
        read the file data section
        :param read_until: an optional file offset: if set, parse only up to
                           this offset (smaller than)
        """

        if read_until is None:
            read_until = 1 << 50 # make it larger than any possible log file

        try:
            # pre-init reusable objects
            header = self._MessageHeader()
            msg_data = self._MessageData()

            while True:
                data = self._file_handle.read(3)
                header.initialize(data)
                data = self._file_handle.read(header.msg_size)
                if len(data) < header.msg_size:
                    break # less data than expected. File is most likely cut

                if self._file_handle.tell() > read_until:
                    if self._debug:
                        print('read until offset=%i done, current pos=%i' %
                              (read_until, self._file_handle.tell()))
                    break

                if header.msg_type == self.MSG_TYPE_INFO:
                    msg_info = self._MessageInfo(data, header)
                    self._msg_info_dict[msg_info.key] = msg_info.value
                elif header.msg_type == self.MSG_TYPE_INFO_MULTIPLE:
                    msg_info = self._MessageInfo(data, header, is_info_multiple=True)
                    self._add_message_info_multiple(msg_info)
                elif header.msg_type == self.MSG_TYPE_PARAMETER:
                    msg_info = self._MessageInfo(data, header)
                    self._changed_parameters.append((self._last_timestamp,
                                                     msg_info.key, msg_info.value))
                elif header.msg_type == self.MSG_TYPE_ADD_LOGGED_MSG:
                    msg_add_logged = self._MessageAddLogged(data, header,
                                                            self._message_formats)
                    if (message_name_filter_list is None or
                            msg_add_logged.message_name in message_name_filter_list):
                        self._subscriptions[msg_add_logged.msg_id] = msg_add_logged
                    else:
                        self._filtered_message_ids.add(msg_add_logged.msg_id)
                elif header.msg_type == self.MSG_TYPE_LOGGING:
                    msg_logging = self.MessageLogging(data, header)
                    self._logged_messages.append(msg_logging)
                elif header.msg_type == self.MSG_TYPE_DATA:
                    msg_data.initialize(data, header, self._subscriptions, self)
                    if msg_data.timestamp != 0 and msg_data.timestamp > self._last_timestamp:
                        self._last_timestamp = msg_data.timestamp
                elif header.msg_type == self.MSG_TYPE_DROPOUT:
                    msg_dropout = self.MessageDropout(data, header,
                                                      self._last_timestamp)
                    self._dropouts.append(msg_dropout)
                else:
                    if self._debug:
                        print('_read_file_data: unknown message type: %i (%s)' %
                              (header.msg_type, chr(header.msg_type)))
                        file_position = self._file_handle.tell()
                        print('file position: %i (0x%x) msg size: %i' % (
                            file_position, file_position, header.msg_size))

                    if self._check_file_corruption(header):
                        # seek back to advance only by a single byte instead of
                        # skipping the message
                        self._file_handle.seek(-2-header.msg_size, 1)

        except struct.error:
            pass #we read past the end of the file

        # convert into final representation
        while self._subscriptions:
            _, value = self._subscriptions.popitem()
            if len(value.buffer) > 0: # only add if we have data
                data_item = ULog.Data(value)
                self._data_list.append(data_item)
read the file data section
        :param read_until: an optional file offset: if set, parse only up to
                           this offset (smaller than)