VertaaTiedosto.java |
1 package fi.jyu.mit.ohj2; 2 3 import java.io.*; 4 import java.util.Scanner; 5 6 /** 7 * Aliohjelma kahden tekstitiedoston vertaamiseksi. 8 * Käyttö lähinnä JUnit testeissä esim. seuraavasti: 9 * <pre> 10 * VertaaTiedosto.kirjoitaTiedosto("hiljaa.txt", 11 * "33 hiljaa 1 hiipii\n"+ 12 * "hyvä 33 tulee\n"+ 13 * "36 1 3 5 55\n"+ 14 * "nyt 33 riittää\n"); 15 * VertaaTiedosto.kirjoitaTiedosto("hiljaayli30.txt", 16 * "33 hiljaa 1 hiipii\n"+ 17 * "36 1 3 5 55\n"); 18 * VertaaTiedosto.tuhoaTiedosto("tulos.txt"); 19 * TulYli30.main(new String[]{"hiljaa.txt","tulos.txt"}); 20 * VertaaTiedosto.vertaaFileFile("tulos.txt","hiljaayli30.txt") === null; 21 * VertaaTiedosto.tuhoaTiedosto("hiljaa.txt"); 22 * VertaaTiedosto.tuhoaTiedosto("hiljaayli30.txt"); 23 * </pre> 24 * @author vesal 25 * @version 10.3.2007 26 */ 27 public class VertaaTiedosto { // NOPMD Cyclomatic 28 /** 29 * Verrataan kahta tekstitiedostoa ja heti kun tulee ensimmäin poikkeava 30 * rivi palautetaanvirhe. Lopussa olevat pelkkä yksi rivi ei tee eroa. 31 * @param nimi1 1. verrattavan tiedoston nimi 32 * @param nimi2 2. verrattavan tiedoston nimi 33 * @return ensimmäinen eroavaisuus joka löytyy. Null jos ei eroja. 34 * @throws IOException jos lukemisessa tapahtuu virhe. 35 * @example 36 * <pre name="test"> 37 * #THROWS IOException 38 * #import java.io.*; 39 * #STATICIMPORT 40 * kirjoitaTiedosto("hiljaa1.txt", "33 hiljaa 1 hiipii\nhyvä 33 tulee\n"); 41 * 42 * kirjoitaTiedosto("hiljaa2.txt", "33 hiljaa 1 hiipii\nhyvä 33 tulee\n"); 43 * vertaaFileFile("hiljaa1.txt","hiljaa2.txt") === null; 44 * 45 * kirjoitaTiedosto("hiljaa2.txt", "33 hiljaa 1 hiipii\nhyvä 33 tulee"); 46 * vertaaFileFile("hiljaa1.txt","hiljaa2.txt") === null; 47 * 48 * kirjoitaTiedosto("hiljaa2.txt", "33 hiljaa 1 hiipii\nhyvä 33 tulee\n\n\n"); 49 * vertaaFileFile("hiljaa1.txt","hiljaa2.txt") === "Rivi 3: hiljaa1.txt loppui ensin, hiljaa2.txt on "; 50 * 51 * kirjoitaTiedosto("hiljaa2.txt", "33 hiljaa 1 hiipii\nhyvä 34 tulee\n"); 52 * vertaaFileFile("hiljaa1.txt","hiljaa2.txt") === "Ero riveissä 2: hyvä 33 tulee ja hyvä 34 tulee"; 53 * 54 * kirjoitaTiedosto("hiljaa2.txt", "33 hiljaa 1 hiipii\n"); 55 * vertaaFileFile("hiljaa1.txt","hiljaa2.txt") === "Rivi 2: hiljaa2.txt loppui ensin, hiljaa1.txt on hyvä 33 tulee"; 56 * 57 * kirjoitaTiedosto("hiljaa2.txt", "33 hiljaa 1 hiipii\nhyvä 33 tulee\nja 34 tulee\n"); 58 * vertaaFileFile("hiljaa1.txt","hiljaa2.txt") === "Rivi 3: hiljaa1.txt loppui ensin, hiljaa2.txt on ja 34 tulee"; 59 * vertaaFileFile("hiljaa1.txt","hiljaa3.txt") === "Tiedosto ei aukea: hiljaa3.txt"; 60 * vertaaFileFile("hiljaa4.txt","hiljaa2.txt") === "Tiedosto ei aukea: hiljaa4.txt"; 61 * 62 * tuhoaTiedosto("hiljaa1.txt"); 63 * tuhoaTiedosto("hiljaa2.txt"); 64 * 65 * </pre> 66 */ 67 @SuppressWarnings({ "resource", "null" }) // finally hoitaa sulkemisen, s1 ei ole null s1.compare-lauseessa 68 public static String vertaaFileFile(String nimi1, String nimi2) throws IOException { // NOPMD 69 BufferedReader f1 = null; 70 BufferedReader f2 = null; 71 try { 72 f1 = Tiedosto.avaa_lukemista_varten(nimi1); 73 f2 = Tiedosto.avaa_lukemista_varten(nimi2); 74 if (f1 == null) return "Tiedosto ei aukea: " + nimi1; 75 if (f2 == null) return "Tiedosto ei aukea: " + nimi2; 76 int n = 1; 77 78 while (true) { 79 String s1 = f1.readLine(); 80 String s2 = f2.readLine(); 81 if (s1 == null && s2 == null) return null; 82 if (s1 != null && s2 == null) return "Rivi " + n + ": " + nimi2 + " loppui ensin, " + nimi1 + " on " + s1; // NOPMD 83 if (s1 == null && s2 != null) return "Rivi " + n + ": " + nimi1 + " loppui ensin, " + nimi2 + " on " + s2; // NOPMD 84 if (s1.compareTo(s2) != 0) return "Ero riveissä " + n + ": " + s1 + " ja " + s2; // NOPMD 85 n++; 86 } 87 } finally { 88 if (f1 != null) f1.close(); 89 if (f2 != null) f2.close(); 90 } 91 } 92 93 94 /** 95 * Verrataan tekstitiedostoa merkkijonoon ja heti kun tulee ensimmäinen poikkeava 96 * rivi palautetaan virhe. Lopussa olevat pelkkä yksi tyhkä rivi eo tee eroa. 97 * @param nimi1 1. verrattavan tiedoston nimi 98 * @param ss2 2. verrattava sisältö 99 * @return ensimmäinen eroavaisuus joka löytyy. Null jos ei eroja. 100 * @throws IOException jos lukemisessa tapahtuu virhe. 101 * @example 102 * <pre name="test"> 103 * #THROWS IOException 104 * #import java.io.*; 105 * #STATICIMPORT 106 * kirjoitaTiedosto("hiljaa1.txt", "33 hiljaa 1 hiipii\nhyvä 33 tulee\n"); 107 * 108 * vertaaFileString("hiljaa1.txt","33 hiljaa 1 hiipii\nhyvä 33 tulee\n") === null; 109 * 110 * vertaaFileString("hiljaa1.txt","33 hiljaa 1 hiipii\nhyvä 33 tulee") === null; 111 * 112 * vertaaFileString("hiljaa1.txt","33 hiljaa 1 hiipii\nhyvä 33 tulee\n\n") === "Rivi 3: hiljaa1.txt loppui ensin, jono on "; 113 * 114 * vertaaFileString("hiljaa1.txt","33 hiljaa 1 hiipii\nhyvä 33 tulee\n\n\n") === "Rivi 3: hiljaa1.txt loppui ensin, jono on "; 115 * 116 * vertaaFileString("hiljaa1.txt","33 hiljaa 1 hiipii\nhyvä 34 tulee\n") === "Ero riveissä 2: hyvä 33 tulee ja hyvä 34 tulee"; 117 * 118 * vertaaFileString("hiljaa1.txt","33 hiljaa 1 hiipii\n") === "Rivi 2: Jono loppui ensin, hiljaa1.txt on hyvä 33 tulee"; 119 * 120 * vertaaFileString("hiljaa1.txt","33 hiljaa 1 hiipii\nhyvä 33 tulee\nja 34 tulee\n") === "Rivi 3: hiljaa1.txt loppui ensin, jono on ja 34 tulee"; 121 * vertaaFileString("hiljaa1.txt",null) === "Jono on null"; 122 * vertaaFileString("hiljaa4.txt","hiljaa2.txt") === "Tiedosto ei aukea: hiljaa4.txt"; 123 * 124 * tuhoaTiedosto("hiljaa1.txt"); 125 * 126 * </pre> 127 */ 128 @SuppressWarnings({ "null", "resource" }) // finally sulkee, s1 ei ole null s1.compare-lauseessa 129 public static String vertaaFileString(String nimi1, String ss2) throws IOException { // NOPMD 130 if (ss2 == null) return "Jono on null"; 131 BufferedReader f1 = null; 132 @SuppressWarnings("resource") 133 Scanner f2 = new Scanner(ss2); 134 int n = 1; 135 try { 136 f1 = Tiedosto.avaa_lukemista_varten(nimi1); 137 if (f1 == null) return "Tiedosto ei aukea: " + nimi1; 138 139 while (true) { 140 String s1 = f1.readLine(); 141 boolean b2 = f2.hasNextLine(); 142 String s2 = null; 143 if (b2) s2 = f2.nextLine(); 144 if (s1 == null && !b2) return null; 145 if (s1 != null && !b2) return "Rivi " + n + ": " + "Jono loppui ensin, " + nimi1 + " on " + s1; 146 if (s1 == null && b2) return "Rivi " + n + ": " + nimi1 + " loppui ensin, " + "jono on " + s2; 147 if (s1.compareTo(s2) != 0) return "Ero riveissä " + n + ": " + s1 + " ja " + s2; 148 n++; 149 } 150 } finally { 151 if (f1 != null) f1.close(); 152 if (f2 != null) f2.close(); 153 } 154 } 155 156 157 /** 158 * Verrataan kahta tekstitiedoston kaltaista merkkijonoa ja heti kun tulee ensimmäinen poikkeava 159 * rivi palautetaan virhe. Lopussa oleva yksi tyhjä rivi ei tee eroa. 160 * @param ss1 1. verrattava sisältö 161 * @param ss2 2. verrattava sisältö 162 * @return ensimmäinen eroavaisuus joka löytyy. Null jos ei eroja. 163 * @example 164 * <pre name="test"> 165 * #THROWS IOException 166 * #import java.io.*; 167 * #STATICIMPORT 168 * vertaaString2("","\n") === "Rivi 1: 1. loppui ensin, 2. on "; 169 * vertaaString2("kissa\n","kissa") === null; 170 * vertaaString2("\n\n","\n") === "Rivi 2: 2. loppui ensin, 1. on "; 171 * vertaaString2("\r\n","\n") === null; 172 * vertaaString2("\r\n","\n\n") === "Rivi 2: 1. loppui ensin, 2. on "; 173 * vertaaString2("33 hiljaa 1 hiipii\r\nhyvä 33 tulee\r\n","33 hiljaa 1 hiipii\nhyvä 33 tulee\n") === null; 174 * vertaaString2("a b","a c") === "Ero riveissä 1: a b ja a c" 175 * vertaaString2(null,null) === null; 176 * vertaaString2(null," ") === "1. on null"; 177 * vertaaString2(" ",null) === "2. on null"; 178 * </pre> 179 */ 180 @SuppressWarnings({ "null", "resource" }) 181 public static String vertaaString2(String ss1, String ss2) { // NOPMD 182 if (ss1 == null & ss2 == null) return null; 183 if (ss1 == null) return "1. on null"; 184 if (ss2 == null) return "2. on null"; 185 Scanner f1 = new Scanner(ss1); 186 Scanner f2 = new Scanner(ss2); 187 int n = 1; 188 try { 189 while (true) { 190 String s1 = null; 191 String s2 = null; 192 boolean b1 = f1.hasNextLine(); 193 boolean b2 = f2.hasNextLine(); 194 if (b1) s1 = f1.nextLine(); 195 if (b2) s2 = f2.nextLine(); 196 if (!b1 && !b2) return null; 197 if (b1 && !b2) return "Rivi " + n + ": " + "2. loppui ensin, 1. on " + s1; 198 if (!b1 && b2) return "Rivi " + n + ": " + "1. loppui ensin, 2. on " + s2; 199 if (s1.compareTo(s2) != 0) return "Ero riveissä " + n + ": " + s1 + " ja " + s2; 200 n++; 201 } 202 } finally { 203 f1.close(); 204 f2.close(); 205 } 206 } 207 208 209 /** 210 * Verrataan kahta tekstitiedoston kaltaista merkkijonoa ja heti kun tulee ensimmäinen poikkeava 211 * rivi palautetaan virhe. Lopussa olevat pelkät tyhjät rivit merkitsevät. 212 * @param ss1 1. verrattava sisältö 213 * @param ss2 2. verrattava sisältö 214 * @return ensimmäinen eroavaisuus joka löytyy. Null jos ei eroja. 215 * @example 216 * <pre name="test"> 217 * #THROWS IOException 218 * #import java.io.*; 219 * #STATICIMPORT 220 * vertaaString("kissa\n","kissa") === "Rivi 2: 2. loppui ensin, 1. on "; 221 * vertaaString("","\n") === "Rivi 1: 1. loppui ensin, 2. on "; 222 * vertaaString("\n\n","\n") === "Rivi 3: 2. loppui ensin, 1. on "; 223 * vertaaString("\r\n","\n") === null; 224 * vertaaString("\r","\n") === null; 225 * vertaaString("\r\n","\n\n") === "Rivi 3: 1. loppui ensin, 2. on "; 226 * vertaaString("33 hiljaa 1 hiipii\r\nhyvä 33 tulee\r\n","33 hiljaa 1 hiipii\nhyvä 33 tulee\n") === null; 227 * vertaaString("a b","a c") === "Ero riveissä 1: a b ja a c" 228 * vertaaString((String)null,null) === null; 229 * vertaaString((String)null," ") === "1. on null"; 230 * vertaaString(" ",null) === "2. on null"; 231 * </pre> 232 */ 233 @SuppressWarnings("null") 234 public static String vertaaString(String ss1, String ss2) { // NOPMD 235 String st1 = ss1; 236 String st2 = ss2; 237 if (st1 == null & st2 == null) return null; 238 if (st1 == null) return "1. on null"; 239 if (st2 == null) return "2. on null"; 240 st1 = st1.replaceAll("\\r\\n", "\n"); 241 st2 = st2.replaceAll("\\r\\n", "\n"); 242 st1 = st1.replaceAll("\\r", "\n"); 243 st2 = st2.replaceAll("\\r", "\n"); // Toki nyt voitaisiin verrata 244 // pelkkiä jonoja sellaisenaan 245 Erottelija f1 = new Erottelija(st1, "\n"); 246 Erottelija f2 = new Erottelija(st2, "\n"); 247 int n = 1; 248 while (true) { 249 String s1 = null; 250 String s2 = null; 251 boolean b1 = f1.hasMoreTokens(); 252 boolean b2 = f2.hasMoreTokens(); 253 if (b1) s1 = f1.nextToken(); 254 if (b2) s2 = f2.nextToken(); 255 if (!b1 && !b2) return null; 256 if (b1 && !b2) return "Rivi " + n + ": " + "2. loppui ensin, 1. on " + s1; 257 if (!b1 && b2) return "Rivi " + n + ": " + "1. loppui ensin, 2. on " + s2; 258 if (s1.compareTo(s2) != 0) return "Ero riveissä " + n + ": " + s1 + " ja " + s2; 259 n++; 260 } 261 } 262 263 264 /** 265 * Verrataan keskenään merkkijonotietovirtaa ja merkkijon sisältöä. 266 * Kakkki rivit (myös tyhjät) pitää olla samalla tavalla. 267 * bs tyhjennetään vertailun jälkeen. 268 * @param bs verrattava merkkijonotietovirta 269 * @param ss2 merkkijono johon verrataan 270 * @return null jos samat, muuten eroava rivi 271 * @example 272 * <pre name="test"> 273 * #import java.io.ByteArrayOutputStream; 274 * ByteArrayOutputStream bs = new ByteArrayOutputStream(); 275 * PrintStream out = new PrintStream(bs); 276 * out.println("kissa\n"); 277 * vertaaString(bs,"kissa") === "Rivi 2: 2. loppui ensin, 1. on "; 278 * vertaaString(bs,"\n") === "Rivi 1: 1. loppui ensin, 2. on "; 279 * out.println("\n\n"); 280 * vertaaString(bs,"\n") === "Rivi 3: 2. loppui ensin, 1. on "; 281 * out.println("\r"); vertaaString(bs,"\n\n") === null; 282 * out.println("33 hiljaa 1 hiipii\r\nhyvä 33 tulee"); 283 * vertaaString(bs,"33 hiljaa 1 hiipii\nhyvä 33 tulee\n") === null; 284 * out.print("a b"); 285 * vertaaString(bs,"a c") === "Ero riveissä 1: a b ja a c" 286 * vertaaString(bs,null) === "2. on null"; 287 * </pre> 288 */ 289 public static String vertaaString(ByteArrayOutputStream bs, String ss2) { // NOPMD 290 String ero = vertaaString(bs.toString(), ss2); 291 bs.reset(); 292 return ero; 293 } 294 295 296 /** 297 * Kirjoitetaan tiedostoon sisältö 298 * @param nimi tiedoston nimi johon kirjoitetaan 299 * @param sisalto merkkijono joka kirjoitetaan tiedostoon 300 * @throws IOException jos tiedosto ei aukea. 301 * @example 302 * <pre name="test"> 303 * #THROWS IOException 304 * kirjoitaTiedosto("hiljaa1.txt", "33 hiljaa 1 hiipii\nhyvä 33 tulee\n"); 305 * tuhoaTiedosto("hiljaa1.txt"); 306 * kirjoitaTiedosto("ö:\\ö.ö", "33 hiljaa 1 hiipii\nhyvä 33 tulee\n"); #THROWS IOException 307 * </pre> 308 */ 309 public static void kirjoitaTiedosto(String nimi, String sisalto) throws IOException { 310 @SuppressWarnings("resource") // suljetaan finalyssä 311 PrintWriter out = null; 312 try { 313 out = new PrintWriter(new FileWriter(nimi)); 314 out.write(sisalto); 315 out.close(); 316 } finally { 317 if (out != null) out.close(); 318 } 319 } 320 321 322 /** 323 * Tuhotaan tiedosto levyltä 324 * @param nimi tuhottavan tiedoston nimi 325 */ 326 public static void tuhoaTiedosto(String nimi) { 327 File f = new File(nimi); 328 f.delete(); 329 } 330 331 /** 332 * Testataan tiedostojen vertaamista 333 * @param args ei käytössä 334 * @throws IOException jos tulee virhe 335 */ 336 /* 337 * public static void main(String[] args) throws IOException { String koe = 338 * vertaaFileFile("fi/jyu/mit/ohj2/IO.java","fi/jyu/mit/ohj2/Syotto.java"); 339 * System.out.println(koe); } 340 */ 341 } 342