Как маршалировать класс в Jruby, который содержит массив

У меня есть двумерный массив, содержащий множество экземпляров класса. Класс содержит 4 массива. Я хотел бы сохранить и загрузить 2D-массив на/с диска с помощью Marshal. Я успешно использовал Marshal для этой цели с другими 2D-массивами, содержащими классы, но эти классы не содержали массива. Вот определение класса, доставляющего мне неприятности.

class Light
       attr_accessor :R,:G,:B,:A

       def initialize(i)

            @R = Array.new(4, i)
            @G = Array.new(4, i)
            @B = Array.new(4, i)
            @A = Array.new(4, i)

       end

       @R
       @G
       @B
       @A

end

Я попытался определить свои собственные функции маршала в классе Light:

def marshal_dump
    {'R' => @R,'G' => @G,'B' => @B,'A' => @A}
end


def marshal_load(data)
    self.R = data['R']
    self.G = data['G']
    self.B = data['B']
    self.A = data['A']
end

Вот создание 2D-массива, содержащего этот класс

def createLightMap(width,height)
     a = Array.new(width) { Light.new(0.7) }
     a.map! { Array.new(height) { Light.new(0.7) } }
     return a
end

@lightMap = createLightMap(10,10)

Вот как я сохраняю и загружаю

#save
File.open('lightData','w') do |file|
     Marshal.dump(@lightMap, file)
end

#load
@lightMap = if File.exists?('lightData')
                  File.open('lightData','w') do |file|
                       Marshal.load(file)
                  end
             else
                  puts 'no light data found'
             end

При загрузке я получаю сообщение об ошибке «в« загрузке »: ошибка формата дампа (несвязанный, индекс: -96) (ошибка аргумента)»

Я пробовал с пользовательскими функциями маршала дампа/загрузки и без них. Я использую jruby 1.5.1, рубин 1.8.7


person Spencer    schedule 12.04.2012    source источник
comment
Для чего нужны эти голые @R и т. д. в объявлении класса?   -  person Dave Newton    schedule 12.04.2012
comment
Это привычка, оставшаяся от написания кода на C++. Я так понимаю они не нужны?   -  person Spencer    schedule 12.04.2012
comment
На самом деле они ничего делать не будут; объявление класса выполняется по порядку. Итак, attr_accessors создает функции доступа. def объявляет функцию ctor. @X будет просто оцениваться в контексте класса, а не экземпляра, и будет nil, потому что они ничем не инициализированы и совершенно бессмысленны на уровне класса (поскольку они являются экземплярами). переменные).   -  person Dave Newton    schedule 12.04.2012


Ответы (1)


Я не думаю, что проблема заключается в дампе/загрузке Marshal, возможно, это просто файловый ввод-вывод. Это отлично работает для меня (без пользовательского маршалинга):

class Light
  # You might want to downcase these variables as capitalized 
  # variables in Ruby generally denote constants
  attr_accessor :R,:G,:B,:A

  def initialize(i)
    @R = Array.new(4, i)
    @G = Array.new(4, i)
    @B = Array.new(4, i)
    @A = Array.new(4, i)
  end

  def ==(other)
    @R == other.R && @G == other.G && @B == other.B && @A == other.A
  end
end

# Method names are generally underscored / snake cased
# (JRuby is even smart enough to map this to Java's camel casing).
# Also should probably attach this method to a class or module to prevent
# polluting global namespace
def create_light_map(width,height)
  a = Array.new(width) { Light.new(0.7) }
  # Note you don't need explicit returns - the last value evaluated is the return value
  a.map { Array.new(height) { Light.new(0.7) } } # You can also lose the ! on map
end

# Same casing style applies to variables
light_map = create_light_map(10,10)
# => [[#<Light:0x5ec736e4 @A=[0.7, 0.7, 0.7, 0.7], ...

# Note with marshaled data you should probably open file in binary mode
File.open('/tmp/lightData','wb') { |f| f.write(Marshal.dump(light_map)) }
# => 5240

light_map_demarshaled = File.open('/tmp/lightData','rb') { |f| Marshal.load(f.read) }
# => [[#<Light:0x6a2d0483 @A=[0.7, 0.7, 0.7, 0.7], ...

light_map_demarshaled == light_map
# => true
person Abe Voelker    schedule 14.04.2012
comment
Вы были полностью правы насчет File IO. Должно быть, я неправильно назвал переменную или что-то в этом роде и исправил ее после написания маршал-дампа и функций загрузки для класса. Я просто удалил их, и все работает нормально. Спасибо, что позволили мне почистить мой код! - person Spencer; 14.04.2012