2013-07-26 2 views
2

Мы разрешаем людям загружать файлы на S3, а затем выводим количество строк, количество строк в этом файле. Мы делаем это, запустив фоновый процесс (DelayedJob), который извлекает файл из S3, а затем подсчитывает количество новых строк в документе. В целом, это работает очень хорошо.Получение количества строк файла, размещенного на S3

Вот код, который делает работу:

def self.line_count_from_s3(options={}) 

    options = { :key => options } if options.is_a?(String) 

    line_count = 0 

    unless options[:key] 
     raise ArgumentError, 'A valid S3 key is required.' 
    end 

    s3 = AWS::S3.new 
    file = s3.buckets[ENV['S3_BUCKET']].objects[options[:key]] 

    unless file.exists? 
     raise IOError, 'Unable to load that import from S3. Key does not exist.' 
    end 

    # Stream download chunks of the file instead of loading it all into memory 
    file.read do |chunk| 
     # Normalize line endings 
     chunk.gsub!(/\r\n?/, "\n") 
     line_count += chunk.scan("\n").count 
    end 
    # Don't count the empty newline (assumes there is one) 
    line_count -= 1 if line_count > 0 

    line_count 
    end 

По некоторым причинам, несколько файлов обращаются с подсчетами совершенно неправильными линиями. Например, файл с 10 000 строк отображается с количеством строк 40 000. Это непротиворечиво. Большинство файлов работают нормально.

Я пытаюсь выяснить, может ли это быть вызвано тем, как работает считыватель S3, или если что-то еще вызывает проблему. Любая идея, почему учетные записи ошибочны? Есть ли лучший способ сделать это, о котором я не знаю?

+0

все файлы того же формата? –

+0

Прямо сейчас они все одинаковые CSV-формат, однако это изменится довольно скоро. Что касается кодировки файлов, это, как правило, файлы UTF8, win32 или ASCII. Мы выполняем gsub (/ \ r \ n? /, "\ N"), чтобы нормализовать окончания строк в куске файла перед их подсчетом. –

+0

Делает тот же файл все время с одинаковым ошибочным счетом. Вы пробовали не мутировать кусок на месте? Похоже, net/http предполагает, что вы не будете изменять этот буфер, так что это может отбросить все. –

ответ

-1

Я не знаю, почему вы инициализируете line_count до 0 и делаете +=. Вам это не нужно. И ваш счетный режим будет упрощен как:

file.read do |chunk| 
    chunk.gsub!(/\r\n?/, "\n") 
    line_count = chunk.count("\n") 
end 
+0

Мы читаем файл в кусках, а не сразу читаем весь файл. У меня создается впечатление, что каждый фрагмент представляет только часть файла, поэтому мы добавляем количество строк каждого фрагмента вместе. Разве это не так? –

+0

Я вижу. Но я не вижу никакой рутины, которая повторяется над кусками. – sawa

+0

Если вы передадите блок S3Object.read, он автоматически купит загрузку: http://docs.aws.amazon.com/AWSRubySDK/latest/AWS/S3/S3Object.html –

Смежные вопросы