/* * Copyright 2018 faddenSoft * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Diagnostics; using System.IO; using System.Text; namespace CommonUtil { public static class FileUtil { /// /// Compares the contents of a file against a byte array. /// /// Expected data values. /// Pathname of file to inspect. /// Offset of first mismatch. If this is equal to expected.Length /// or File(pathName).Length, then the contents were equal but one source stopped /// early. The badFileVal parameter will be zero. /// Mismatched value, from the file. /// True if the contents match, false if not. public static bool CompareBinaryFile(byte[] expected, string pathName, out int badOffset, out byte badFileVal) { badOffset = -1; badFileVal = 0; int chunkOffset = 0; byte[] buffer = new byte[65536]; using (FileStream fs = File.Open(pathName, FileMode.Open, FileAccess.Read)) { //if (fs.Length != expected.Length) { // return false; //} int fileRemain = (int)fs.Length; while (fileRemain != 0) { int toRead = Math.Min(buffer.Length, fileRemain); int actual = fs.Read(buffer, 0, toRead); if (actual != toRead) { // File I/O problem; unexpected. return false; } for (int i = 0; i < toRead; i++) { if (chunkOffset + i >= expected.Length) { // File on disk was too long. Debug.Assert(fs.Length > expected.Length); badOffset = chunkOffset + i; return false; } if (expected[chunkOffset + i] != buffer[i]) { badOffset = chunkOffset + i; badFileVal = buffer[i]; return false; } } fileRemain -= toRead; chunkOffset += toRead; } if (fs.Length != expected.Length) { Debug.Assert(fs.Length < expected.Length); badOffset = (int) fs.Length; return false; } } return true; } /// /// Compares two text files line-by-line. Ignores line termination characters. /// Assumes UTF-8 encoding. /// /// Full path of first file. /// Full path of second file. /// Line number of first differing line. /// Differing line from first file. /// Differing line from second file. /// True if the files are equal. public static bool CompareTextFiles(string pathName1, string pathName2, out int firstDiffLine, out string line1, out string line2) { int line = 0; using (StreamReader sr1 = new StreamReader(pathName1, Encoding.UTF8)) { using (StreamReader sr2 = new StreamReader(pathName2, Encoding.UTF8)) { while (true) { // ReadLine strips the EOL char(s) string str1 = sr1.ReadLine(); string str2 = sr2.ReadLine(); line++; if (str1 != str2) { firstDiffLine = line; line1 = str1; line2 = str2; return false; } if (str1 == null) { Debug.Assert(str2 == null); break; } } } } firstDiffLine = -1; line1 = line2 = null; return true; } /// /// Determines whether the destination file is missing or older than the source file. /// This can be used do decide whether it's necessary to copy srcFile over. /// /// File of interest. /// File to compare dates with. /// True if dstFile is missing or older than srcFile. public static bool IsFileMissingOrOlder(string dstFile, string srcFile) { FileInfo fid = new FileInfo(dstFile); if (!fid.Exists) { return true; // not there } FileInfo fis = new FileInfo(srcFile); if (!fis.Exists) { return false; // nothing to compare against } return (fid.LastWriteTimeUtc < fis.LastWriteTimeUtc); } } }