#!/usr/bin/ruby -w
# -*- ruby -*-
module FileTester
# the percentage of characters that we allow to be odd in a text file
ODD_FACTOR = 0.3
# how many bytes (characters) of a file we test
TEST_LENGTH = 1024
# extensions associated with files that are always text:
KNOWN_TEXT = %w{ txt c cpp mk h hpp html java }
# extensions associated with files that are never text:
KNOWN_NONTEXT = %w{ a o obj class elc gif gz jar jpg jpeg png pdf tar Z }
# returns if the given file is nothing but text (ASCII).
def FileTester.text?(file)
# Don't waste our time if it doesn't even exist:
return false unless File.exists?(file)
if file.index(/\.(\w+)\s*$/)
suffix = $1
return true if KNOWN_TEXT.include?(suffix)
return false if KNOWN_NONTEXT.include?(suffix)
end
ntested = 0
nodd = 0
f = File.new(file)
f.each do |line|
# split returns strings, whereas we want characters (bytes)
chars = line.split(//, TEST_LENGTH).collect { |w| w[0] }
# using the limit parameter to split results in the last character being
# "0" (nil), so remove it
if chars.size > 1 and chars[-1].to_i == 0
chars = chars[0 .. -2]
end
chars.each do |ch|
ntested += 1
# never allow null in a text file
return false if ch.to_i == 0
nodd += 1 unless FileTester.ascii?(ch)
return FileTester.summary(nodd, ntested) if ntested >= TEST_LENGTH
end
end
return FileTester.summary(nodd, ntested)
end
def FileTester.summary(nodd, ntested)
return nodd < ntested * ODD_FACTOR
end
# returns if the given character is ASCII.
def FileTester.ascii?(c)
# from ctype.h
return (c.to_i & ~0x7f) == 0
end
end
if __FILE__ == $0
ARGV.each do |a|
istext = FileTester.text?(a)
puts "#{a}: " + (istext ? "text" : "binary")
end
end
syntax highlighted by Code2HTML, v. 0.9.1