1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
public static boolean fileContentsEquals(File file1, File file2) { InputStream is1 = null; InputStream is2 = null; if (file1.length() != file2.length()) return false; try { is1 = new FileInputStream(file1); is2 = new FileInputStream(file2); return inputStreamEquals(is1, is2); } catch (Exception ei) { return false; } finally { try { if (is1 != null) is1.close(); if (is2 != null) is2.close(); } catch (Exception ei2) { } } } public static boolean inputStreamEquals(InputStream is1, InputStream is2) { if (is1 == is2) return true; if (is1 == null && is2 == null) return true; if (is1 == null || is2 == null) return false; try { int read1 = -1; int read2 = -1; do { int offset1 = 0; while (offset1 < BUFFSIZE && (read1 = is1.read(buff1, offset1, BUFFSIZE - offset1)) >= 0) { offset1 += read1; } int offset2 = 0; while (offset2 < BUFFSIZE && (read2 = is2.read(buff2, offset2, BUFFSIZE - offset2)) >= 0) { offset2 += read2; } if (offset1 != offset2) return false; if (offset1 != BUFFSIZE) { Arrays.fill(buff1, offset1, BUFFSIZE, (byte) 0); Arrays.fill(buff2, offset2, BUFFSIZE, (byte) 0); } if (!Arrays.equals(buff1, buff2)) return false; } while (read1 >= 0 && read2 >= 0); if (read1 < 0 && read2 < 0) return true; // both at EOF return false; } catch (Exception ei) { return false; } }
Refactorings
No refactoring yet !
Maciej Piechotka
August 18, 2008, August 18, 2008 10:40, permalink
1. Yes. It will work on bytes
2. May be something like that - 3 lines in NIO.
1 2 3 4 5
public static boolean fileContentsEquals(File file1, File file2) throws IOException { ByteBuffer buf1 = new FileInputStream(file1).getChannel().map(MapMode.READ_ONLY, 0, file1.length()); ByteBuffer buf2 = new FileInputStream(file2).getChannel().map(MapMode.READ_ONLY, 0, file2.length()); return buf1.equals(buf2); }
TFrey
August 18, 2008, August 18, 2008 15:10, permalink
I think this solution is basically the same idea as yours but uses stuff from the Java NIO libraries. In production code you'll have to make sure you close everything and handle exceptions properly but that really clutters the code so I'll leave it as an exercise for the reader ;-) It seems to work for any kind of file because it's comparing raw bytes instead of characters.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
private static boolean areSame(File f1, File f2) throws IOException { FileChannel fc1 = new FileInputStream(f1).getChannel(); FileChannel fc2 = new FileInputStream(f2).getChannel(); if(fc1.size() != fc2.size()) return false; ByteBuffer buf1 = ByteBuffer.allocate(1024); ByteBuffer buf2 = ByteBuffer.allocate(1024); while(fc1.read(buf1) != -1 && fc2.read(buf2) != -1) { if(buf1.compareTo(buf2) != 0) return false; buf1.clear(); buf2.clear(); } return true; }
Maciej Piechotka
August 19, 2008, August 19, 2008 08:14, permalink
I'm tring once more - I've posted 3 minutes after the orginal post but it get spammed:
1 2 3 4 5 6 7 8 9 10 11
private static boolean areSame(File f1, File f2) throws IOException { if(f1 == f2) return true; if(f1 == null || f2 == null) return false; MappedByteBuffer buf1 = new FileInputStream(f1).getChannel().map(FileChannel.MapMode.READ_ONLY, 0, f1.length); MappedByteBuffer buf2 = new FileInputStream(f2).getChannel().map(FileChannel.MapMode.READ_ONLY, 0, f1.length); return buf1.equals(buf2); }
This method checks if the contents of two text files are equal. Is this the best way?
How could it work also for binary files?