Вот простое решение, которое просто читает оба файла и сравнивает данные. Это должно быть не медленнее, чем метод хеша, так как оба метода должны будут считать весь файл. РЕДАКТИРОВАНИЕ , Как отмечено другими, эта реализация на самом деле несколько медленнее, чем метод хеша из-за его простоты. Посмотрите ниже для более быстрого метода.
static bool FilesAreEqual( string f1, string f2 )
{
// get file length and make sure lengths are identical
long length = new FileInfo( f1 ).Length;
if( length != new FileInfo( f2 ).Length )
return false;
// open both for reading
using( FileStream stream1 = File.OpenRead( f1 ) )
using( FileStream stream2 = File.OpenRead( f2 ) )
{
// compare content for equality
int b1, b2;
while( length-- > 0 )
{
b1 = stream1.ReadByte();
b2 = stream2.ReadByte();
if( b1 != b2 )
return false;
}
}
return true;
}
Вы могли изменить его для чтения больше чем одного байта за один раз, но внутренний поток файла должен уже буферизовать данные, поэтому даже этот простой код должен быть относительно быстрым.
РЕДАКТИРОВАНИЕ спасибо за обратную связь на скорости здесь. Я все еще поддерживаю, что compare-all-bytes метод может быть настолько же быстрым как метод MD5, так как оба метода должны считать весь файл. Я подозревал бы (но не знайте наверняка), что, как только файлы были считаны, compare-all-bytes метод требует менее фактического вычисления. В любом случае я копировал Ваши наблюдения производительности для своего начального внедрения, но когда я добавил некоторую простую буферизацию, compare-all-bytes метод был так же быстр. Ниже реализация буферизации, не стесняйтесь комментировать далее!
РЕДАКТИРОВАНИЕ Jon B делает другое правильное замечание: в случае, где файлы на самом деле отличаются, может остановиться этот метод, как только это находит первый различный байт, тогда как метод хеша должен считать полноту обоих файлов в каждом случае.
static bool FilesAreEqualFaster( string f1, string f2 )
{
// get file length and make sure lengths are identical
long length = new FileInfo( f1 ).Length;
if( length != new FileInfo( f2 ).Length )
return false;
byte[] buf1 = new byte[4096];
byte[] buf2 = new byte[4096];
// open both for reading
using( FileStream stream1 = File.OpenRead( f1 ) )
using( FileStream stream2 = File.OpenRead( f2 ) )
{
// compare content for equality
int b1, b2;
while( length > 0 )
{
// figure out how much to read
int toRead = buf1.Length;
if( toRead > length )
toRead = (int)length;
length -= toRead;
// read a chunk from each and compare
b1 = stream1.Read( buf1, 0, toRead );
b2 = stream2.Read( buf2, 0, toRead );
for( int i = 0; i < toRead; ++i )
if( buf1[i] != buf2[i] )
return false;
}
}
return true;
}
Вы можете использовать eval
:
code = '@var.reverse'
@var = 'Hello'
@result = eval(code) # => "olleH"
Но будьте при этом очень осторожны; вы предоставляете этому коду полный доступ к вашей системе. Попробуйте eval ('exit ()')
и посмотрите, что произойдет.
К ответу eval
(который является правильным) я бы добавил: принеси тебе копию Книги Кирки (либо Программирование Ruby , либо Программирование Ruby 1.9 в зависимости от вашей версии Ruby) и прочтите главу под названием «Блокирование Ruby в сейфе». Эта глава посвящена безопасным уровням Ruby и испорченным объектам, и глава открывается с точно ваш вариант использования и почему вам нужно быть параноиком по этому поводу.