2009-07-07 29 views
6

Tôi khá mới để lập trình, vì vậy hãy nhẹ nhàng. Tôi đang cố gắng trích xuất các số IBSN từ một tệp cơ sở dữ liệu thư viện .dat. Tôi đã viết mã hoạt động, nhưng nó chỉ tìm kiếm thông qua khoảng một nửa của tập tin 180MB. Làm thế nào tôi có thể điều chỉnh nó để tìm kiếm toàn bộ tập tin? Hoặc làm thế nào tôi có thể viết một chương trình sẽ chia các tập tin dat thành khối quản lý?Làm cách nào để xử lý các tệp lớn trong Ruby?

chỉnh sửa: Dưới đây là mã của tôi:

export = File.new("resultsfinal.txt","w+") 

File.open("bibrec2.dat").each do |line| 
    line.scan(/[a]{1}[1234567890xX]{10}\W/) do |x| 
    export.puts x 
    end 
    line.scan(/[a]{1}[1234567890xX]{13}/) do |x| 
    export.puts x 
    end 
end 
+0

@ zed_0xff: Cách tiếp cận của Yoann Le Touche không đọc toàn bộ tệp trong bộ nhớ. –

Trả lời

-2

Nếu bạn đang lập trình trên một hệ điều hành hiện đại và máy tính có đủ bộ nhớ (nói 512megs), Ruby nên không có vấn đề đọc toàn bộ tập tin vào bộ nhớ .

Mọi thứ thường trở nên khó chịu khi bạn đạt đến khoảng 2 gigabyte bộ làm việc trên một hệ điều hành 32 bit điển hình.

+0

Vâng, tôi nhận được iffy với 4GB trên Vista, nếu điều đó giúp. Ngoài ra, nó không mang lại một lỗi, chỉ là một tập hợp các kết quả không đầy đủ. –

+0

Tôi tin rằng anh ấy có nghĩa là dữ liệu là 4GB, không phải kích thước bộ nhớ của bạn. Các hệ điều hành 32 bit không thể xử lý nhiều hơn ~ 3,5GB RAM, do đó bạn không có RAM làm việc 4GB theo ý của bạn, bất kể (trừ khi bạn đang chạy 64bit Vista). Nếu tập dữ liệu của bạn chỉ có 180MB, sự cố phải nằm trong mã của bạn. Bạn có đăng kịch bản không? – jkeys

+0

Không sao, tôi sẽ đăng nó vào ngày mai. Cảm ơn rất nhiều. –

1

Về vấn đề hiệu suất, tôi không thể thấy bất cứ điều gì đặc biệt đáng lo ngại về kích thước tệp: 180MB không nên gây ra bất kỳ sự cố nào. Điều gì xảy ra với bộ nhớ khi bạn đang chạy kịch bản?

Tôi không chắc chắn, tuy nhiên, Cụm từ thông dụng của bạn đang làm những gì bạn muốn. Này, ví dụ:

/[a]{1}[1234567890xX]{10}\W/ 

không (tôi nghĩ) này:

  • một "a". Bạn có thực sự muốn phù hợp với "a" không? "a" sẽ đủ, thay vì "[a] {1}", trong trường hợp đó.
  • chính xác 10 (chữ số hay "x" hoặc "X")
  • một "non-word" duy nhất nhân vật tức là không az, AZ, 0-9 hoặc nhấn

Có một vài các đối sánh ISBN mẫu herehere, mặc dù chúng có vẻ giống với định dạng mà chúng ta thấy trên bìa sau của sách và tôi đoán tệp đầu vào của bạn đã loại bỏ một số định dạng đó.

+0

Vâng, tệp dữ liệu gốc đã định dạng lại các ISBN để chúng ở định dạng đó. Tôi không biết tại sao nó lại làm thế! Tốt gọi trên chỉ là viết 'a', có vẻ đơn giản hơn rất nhiều. –

4

Bạn nên cố gắng nắm bắt ngoại lệ để kiểm tra xem sự cố có thực sự ở trên khối đọc hay không.

Chỉ cần bạn biết tôi đã tạo một kịch bản với cùng một cú pháp để tìm kiếm tệp lớn thực sự của ~ 8GB mà không gặp vấn đề gì.

export = File.new("resultsfinal.txt","w+") 

File.open("bibrec2.dat").each do |line| 
    begin 
    line.scan(/[a]{1}[1234567890xX]{10}\W/) do |x| 
     export.puts x 
    end 
    line.scan(/[a]{1}[1234567890xX]{13}/) do |x| 
     export.puts x 
    end 
    rescue 
    puts "Problem while adding the result" 
    end 
end 
2
file = File.new("bibrec2.dat", "r") 
while (line = file.gets) 
    line.scan(/[a]{1}[1234567890xX]{10}\W/) do |x| 
    export.puts x 
    end 
    line.scan(/[a]{1}[1234567890xX]{13}/) do |x| 
    export.puts x 
    end 
end 
file.close 
3

Điều quan trọng là để làm sạch và kết hợp các regex với hiệu suất cao. Ngoài ra bạn nên luôn luôn sử dụng cú pháp khối với các tập tin để đảm bảo fd đang nhận được đóng đúng cách. File # từng không tải toàn bộ tập tin vào bộ nhớ, nó không một dòng tại một thời điểm:

File.open("resultsfinal.txt","w+") do |output| 
    File.open("bibrec2.dat").each do |line| 
     output.puts line.scan(/a[\dxX]{10}(?:[\dxX]{3}|\W)/) 
    end 
end 
1

Bạn có thể nhìn vào sử dụng File#truncateIO#seek và sử dụng các thuật toán kiểu tìm kiếm nhị phân. #truncate có thể phá hoại, do đó bạn nên trùng lặp tệp (Tôi biết đây là một rắc rối).

middle = File.new("my_huge_file.dat").size/2 
tmpfile = File.new("my_huge_file.dat", "r+").truncate(middle) 
# run search algoritm on 'tmpfile' 
File.open("my_huge_file.dat") do |huge_file| 
    huge_file.seek(middle + 1) 
    # run search algorithm from here 
end 

Mã này chưa được kiểm chứng, dễ vỡ và không đầy đủ. Nhưng tôi hy vọng nó cung cấp cho bạn một nền tảng để xây dựng của off.

+0

nếu bạn chia tệp của mình ở giữa một dòng thì sao? ;) – fenec

Các vấn đề liên quan