2013-05-29 74 views
19

Tôi đã viết một bảng mã Huffman đơn giản trong Ruby. Khi đầu ra tôi có một mảng, ví dụ:Làm cách nào để đọc/ghi tệp nhị phân?

["010", "1111", "10", "10", "110", "1110", "001", "110", "000", "10", "011"] 

Tôi cần phải viết, và sau đó đọc, nó đến và từ một tệp. Tôi đã thử một số phương pháp:

IO.binwrite("out.cake", array) 

Tôi nhận được tệp văn bản đơn giản chứ không phải nhị phân.

Hoặc:

File.open("out.cake", 'wb') do |output| 
    array.each do | byte | 
     output.print byte.chr 
    end 
end 

nào trông giống như nó hoạt động, nhưng sau đó tôi không thể đọc nó vào mảng.

Tôi nên sử dụng mã hóa nào?

+0

Bạn muốn tệp của mình chứa gì? Nhân vật? Hoặc bit? Hoặc mảng Ruby? Hay cái gì khác? –

+0

Bits. Coz Tôi cần kích thước tệp ít hơn. –

+0

Câu trả lời có thể liên quan đến việc sử dụng 'gói' –

Trả lời

27

Tôi nghĩ rằng bạn chỉ có thể sử dụng Array#packString#unpack như đoạn mã sau:

# Writing 
a = ["010", "1111", "10", "10", "110", "1110", "001", "110", "000", "10", "011"] 
File.open("out.cake", 'wb') do |output| 
    output.write [a.join].pack("B*") 
end 

# Reading 
s = File.binread("out.cake") 
bits = s.unpack("B*")[0] # "01011111010110111000111000010011" 

Tôi không biết định dạng ưa thích của bạn cho kết quả của việc đọc và tôi biết các phương pháp trên không hiệu quả. Nhưng dù sao bạn cũng có thể lấy "0" hoặc "1" liên tiếp từ kết quả của unpack để duyệt cây Huffman của bạn.

+0

@IvanKozlov Ở đây bạn có thể xem cách đọc các bit trở lại chuỗi. Bây giờ bạn chỉ cần chia nó thành nhiều phần bằng cách giải mã Huffman. –

3

Nếu bạn muốn bit, sau đó bạn phải làm cả đóng gói và giải nén thủ công. Cả Ruby lẫn bất kỳ ngôn ngữ thông dụng nào khác đều không làm được điều đó cho bạn.

Mảng của bạn chứa các chuỗi là các nhóm ký tự, nhưng bạn cần phải tạo một mảng các byte và viết các byte đó vào tệp.

Từ này: ["010", "1111", "10", "10", "110", "1110", "001", "110", "000", "10", "011"]

bạn nên xây dựng các byte: 01011111 01011011 10001110 00010011

Kể từ khi nó chỉ là bốn byte, bạn có thể đặt chúng vào một số 32-bit đơn 01011111010110111000111000010011 đó là 5F5B8E13 hex.

Cả hai mẫu mã của bạn đều làm những việc khác nhau. Người đầu tiên ghi vào tệp một biểu diễn chuỗi của một mảng Ruby. Cái thứ hai viết 32 byte, mỗi cái là 48 ('0') hoặc 49 ('1').

Nếu bạn muốn bit, kích thước tệp đầu ra của bạn sẽ chỉ là bốn byte.

Đọc về các thao tác bit để tìm hiểu cách đạt được điều đó.


Đây là bản nháp. Tôi đã không kiểm tra nó. Điều gì đó có thể sai.

a = ["010", "1111", "10", "10", "110", "1110", "001", "110", "000", "10", "011"] 

# Join all the characters together. Add 7 zeros to the end. 
bit_sequence = a.join + "0" * 7 # "010111110101101110001110000100110000000" 

# Split into 8-digit chunks. 
chunks = bit_sequence.scan(/.{8}/) # ["01011111", "01011011", "10001110", "00010011"] 

# Convert every chunk into character with the corresponding code. 
bytes = chunks.map { |chunk| chunk.to_i(2).chr } # ["_", "[", "\x8E", "\x13"] 

File.open("my_huffman.bin", 'wb') do |output| 
    bytes.each { |b| output.write b } 
end 

Lưu ý: bảy số không được bổ sung để xử lý trường hợp khi tổng số ký tự là không chia hết cho 8. Nếu không có những số không, bit_sequence.scan(/.{8}/) sẽ thả những nhân vật còn lại.

+0

Bạn có thể dán một số mã mẫu không?Đối với mảng có thể, làm thế nào để đóng gói và giải nén nó? –

+0

Về cơ bản mã Huffman được sử dụng để nén hoặc lưu trữ. Vì vậy, kết quả là tôi muốn có tệp với kích thước tối thiểu. Ý tưởng của bạn về nó? Bạn đề xuất phương pháp nào? –

+0

Tôi đã thêm bản nháp làm ví dụ. Tôi không có thời gian để kiểm tra cẩn thận. –

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