Suuntaaja.java |
1 package fi.jyu.mit.ohj2; 2 3 import java.io.ByteArrayInputStream; 4 import java.io.ByteArrayOutputStream; 5 import java.io.FileInputStream; 6 import java.io.FileNotFoundException; 7 import java.io.FileOutputStream; 8 import java.io.IOException; 9 import java.io.InputStream; 10 import java.io.OutputStream; 11 import java.io.PrintStream; 12 13 /** 14 * Luokka tietovirtojen uudelleen suuntaamiseksi 15 * @author vesal 16 * 17 */ 18 public class Suuntaaja { // NOPMD -luokkakirjasto 19 // #STATICIMPORT 20 // #import fi.jyu.mit.ohj2.*; 21 22 /** 23 * Rajapinta suuntajalle 24 * @author vesal 25 * 26 */ 27 public interface ISuuntaaja { 28 29 /** 30 * Palauttaa suuntauksen alkuperäiseen tilaan. 31 */ 32 void palauta(); 33 } 34 35 /** 36 * Käytössä olevan systeemin rivinvahdon merkkkijono 37 */ 38 private static String NL = getNL(); // NOPMD - tarkoituksella lyhyt nimi 39 40 41 /** 42 * Palauttaa systeemin käytössä olevan newline jonon 43 * @return rivinvaihdon merkkiyhdistelmä käytetyssä järjestelmässä 44 */ 45 public static String getNL() { 46 if ( NL != null ) return NL; 47 NL = ""; 48 StringOutput so = new StringOutput(); 49 System.out.println(); 50 NL = so.toString(); 51 so.palauta(); 52 return NL; 53 } 54 55 56 /** 57 * Suuntaa inputin uudelleen ja kertoo Syotto-luokalle 58 * @param is uusi tietovirta syötölle 59 * 60 */ 61 protected static void setIn(InputStream is) { 62 System.setIn(is); 63 Syotto.alusta(); 64 Readkey.init(); 65 } 66 67 /** 68 * Luokka jolla System.in otetaan tiedostosta 69 * @author vesal 70 * @version 11.3.2007 71 */ 72 public static class Input implements ISuuntaaja { 73 private static final InputStream origIn = System.in; // NOPMD - ei ole vakio 74 private InputStream stdin = null; 75 76 /** 77 * Asetetaan peruslukuvirta eri tiedostoon. 78 * Jos nimi on null, niin sitä virtaa ei suunnata uudelleen 79 * @param inNimi mistä tiedostosta System.in luetaan 80 * @throws FileNotFoundException jos tiedostoa ei saada käyttöön 81 * @example 82 * <pre name="test"> 83 * #THROWS IOException 84 * #import java.io.*; 85 * #import java.util.*; 86 * #import static fi.jyu.mit.ohj2.VertaaTiedosto.*; 87 * kirjoitaTiedosto("hiljaa1.txt", "33 hiljaa 1 hiipii\nhyvä 33 tulee\n"); 88 * Input in = new Input("hiljaa1.txt"); 89 * try ( Scanner sc = new Scanner(System.in) ) { 90 * sc.nextLine() === "33 hiljaa 1 hiipii"; 91 * sc.nextLine() === "hyvä 33 tulee"; 92 * sc.hasNextLine() === false; 93 * in.palauta(); 94 * tuhoaTiedosto("hiljaa1.txt"); 95 * in = new Input(null); 96 * in.palauta(); 97 * } 98 * </pre> 99 */ 100 public Input(String inNimi) throws FileNotFoundException { 101 // getNL(); 102 if ( inNimi != null ) { 103 stdin = new FileInputStream(inNimi); 104 setIn(stdin); 105 } 106 } 107 108 /** 109 * Palautetaan tietovirta takaisin alkuperäiseen tilaan 110 */ 111 @Override 112 public void palauta() { 113 if ( stdin != null ) { 114 try { 115 stdin.close(); 116 } catch (IOException e) { // NOPMD 117 } 118 setIn(origIn); 119 } 120 } 121 122 } 123 124 /** 125 * Luokka jolla System.out suunnataan toiseen tiedostoon 126 * @author vesal 127 * @version 11.3.2007 128 */ 129 public static class Output implements ISuuntaaja { 130 private PrintStream origOut = System.out; 131 private boolean syserr = false; 132 private PrintStream stdout = null; 133 134 /** 135 * Asetetaan perustulostusvirta eri tiedostoon. 136 * Jos nimi on null, niin sitä virtaa ei suunnata uudelleen 137 * @param outNimi mihin System.out kirjoitetaan 138 * @throws FileNotFoundException jos tiedostoa ei saada käyttöön 139 * @example 140 * <pre name="test"> 141 * #THROWS IOException 142 * #import java.io.*; 143 * #import java.util.*; 144 * #import static fi.jyu.mit.ohj2.VertaaTiedosto.*; 145 * Output out = new Output("hiljaa1.txt"); 146 * System.out.println("eka"); 147 * System.out.println("toka"); 148 * out.palauta(); 149 * vertaaFileString("hiljaa1.txt","eka\ntoka\n") === null; 150 * tuhoaTiedosto("hiljaa1.txt"); 151 * 152 * out = new Output(null); 153 * out.palauta(); 154 * </pre> 155 */ 156 public Output(String outNimi) throws FileNotFoundException { 157 this(outNimi,false); 158 } 159 160 /** 161 * @param outNimi mihin suunnataan 162 * @param syserr suunnataanko error-virta 163 * @throws FileNotFoundException jos tiedostoa ei saada auki 164 * <pre name="test"> 165 * #THROWS IOException 166 * #import java.io.*; 167 * #import java.util.*; 168 * #import static fi.jyu.mit.ohj2.VertaaTiedosto.*; 169 * Output out = new Output("koeOut.txt",false); 170 * Output err = new Output("koeErr.txt",true); 171 * System.out.println("eka"); 172 * System.err.println("toka"); 173 * out.palauta(); 174 * err.palauta(); 175 * vertaaFileString("koeOut.txt","eka\n") === null; 176 * vertaaFileString("koeErr.txt","toka\n") === null; 177 * tuhoaTiedosto("koeOut.txt"); 178 * tuhoaTiedosto("koeErr.txt"); 179 * </pre> 180 */ 181 public Output(String outNimi,boolean syserr) throws FileNotFoundException { 182 // getNL(); 183 if ( outNimi != null ) { 184 stdout = new PrintStream(new FileOutputStream(outNimi)); 185 if ( syserr ) { origOut = System.err; System.setErr(stdout); this.syserr = true; } 186 else { origOut = System.out; System.setOut(stdout); } 187 } 188 } 189 190 /** 191 * Palautetaan tietovirta takaisin alkuperäiseen tilaan 192 */ 193 @Override 194 public void palauta() { 195 if (stdout != null ) { 196 stdout.close(); 197 if ( syserr ) System.setErr(origOut); 198 else System.setOut(origOut); 199 } 200 } 201 202 } 203 204 /** 205 * Luokka syötön lukemiseksi merkkijonosta 206 * @author vesal 207 * @version 2.2.2008 208 * @example 209 * <pre name="test"> 210 * StringInput si = new StringInput("kissa\nkoira"); 211 * StringOutput so = new StringOutput(); 212 * Syotto.kysy("Mikä") === "kissa"; 213 * Syotto.kysy("Mikä") === "koira"; 214 * Syotto.kysy("Mikä") === ""; 215 * si = new StringInput("12\n13"); 216 * Syotto.kysy("Luku",0) === 12; 217 * Syotto.kysy("Luku",0) === 13; 218 * Syotto.kysy("Luku",0) === 0; 219 * si.palauta(); 220 * so.palauta(); 221 * </pre> 222 * 223 */ 224 public static class StringInput implements ISuuntaaja { 225 private static final InputStream origIn = System.in; // NOPMD ei ole vakio 226 private ByteArrayInputStream byteinput; 227 228 229 /** 230 * Alustetataan lukutietovirta 231 * @param inputString merkkijonojosta input otetaan 232 */ 233 public StringInput(String inputString) { 234 byteinput = new ByteArrayInputStream(inputString.getBytes()); 235 setIn(byteinput); 236 } 237 238 /** 239 * Palautetaan tietovirta takaisin alkuperäiseen tilaan 240 */ 241 @Override 242 public void palauta() { 243 setIn(origIn); 244 } 245 246 /** 247 * Laitetaan syöttöön uusi merkkijono jota luetaan- 248 * @param inputString merkkijonojosta input otetaan 249 * @example 250 * <pre name="test"> 251 * StringInput si = new StringInput("kissa\nkoira"); 252 * StringOutput so = new StringOutput(); 253 * Syotto.kysy("Mikä") === "kissa"; 254 * Syotto.kysy("Mikä") === "koira"; 255 * Syotto.kysy("Mikä") === ""; 256 * si.input("12\n13"); 257 * Syotto.kysy("Luku",0) === 12; 258 * Syotto.kysy("Luku",0) === 13; 259 * Syotto.kysy("Luku",0) === 0; 260 * si.palauta(); 261 * so.palauta(); 262 * </pre> 263 */ 264 public void input(String inputString) { 265 byteinput = new ByteArrayInputStream(inputString.getBytes()); 266 setIn(byteinput); 267 } 268 } 269 270 271 /** 272 * Luokka tulostuksen siirtämiseksi merkkijonoon 273 * @author vesal 274 * @version 2.2.2008 275 * 276 */ 277 public static class StringOutput implements ISuuntaaja { 278 private PrintStream origOut = System.out; // NOPMD - ei ole vakio 279 private boolean syserr = false; 280 private final ByteArrayOutputStream byteoutput; 281 282 283 /** 284 * Alustetataan kirjoitustietovirta 285 */ 286 public StringOutput() { 287 this(false); 288 } 289 290 /** 291 * Alustetataan kirjoitustietovirta 292 * @param syserr suunnattaanko System.err 293 * @example 294 * <pre name="test"> 295 * StringOutput se = new StringOutput(true); 296 * StringOutput so = new StringOutput(false); 297 * System.out.println("eka"); 298 * System.err.println("toka"); 299 * so.ero("eka\n") === null; 300 * se.ero("toka\n") === null; 301 * so.palauta(); 302 * se.palauta(); 303 * </pre> 304 */ 305 public StringOutput(boolean syserr) { 306 // if ( NL != null ) getNL(); 307 byteoutput = new ByteArrayOutputStream(); 308 PrintStream ps = new PrintStream(byteoutput); 309 if ( syserr ) { origOut = System.err; System.setErr(ps); this.syserr = true; } 310 else { origOut = System.out; System.setOut(ps); } 311 } 312 313 /** 314 * Palautetaan tietovirta takaisin alkuperäiseen tilaan 315 */ 316 @Override 317 public void palauta() { 318 if ( syserr ) System.setErr(origOut); 319 else System.setOut(origOut); 320 } 321 322 /** 323 * Palautetaan toistaiseksi tulostettu tieto merkkijonona 324 * @return tulostettu tieto 325 * @example 326 * <pre name="test"> 327 * String NL = getNL(); 328 * StringOutput so = new StringOutput(); 329 * System.out.println("eka"); 330 * System.out.println("toka"); 331 * so.toString() === "eka"+NL+"toka"+NL; 332 * System.out.println("kolmas"); 333 * so.toStringReset() === "eka"+NL+"toka"+NL+"kolmas"+NL; 334 * so.toString() === ""; 335 * System.out.println("neljäs"); 336 * so.toStringReset() === "neljäs"+NL; 337 * System.out.print("viides\nkuudes"); 338 * so.toStringReset() === "viides\nkuudes"; 339 * System.out.printf("viides%nkuudes"); 340 * so.toStringReset() === "viides"+NL+"kuudes"; 341 * so.palauta(); 342 * </pre> 343 */ 344 @Override 345 public String toString() { 346 return byteoutput.toString(); 347 } 348 349 /** 350 * Palautetaan toistaiseksi tulostettu tieto merkkijonona 351 * ja tyhjennetään tietovirta 352 * @return tulostettu tieto 353 */ 354 public String toStringReset() { 355 String result = byteoutput.toString(); 356 reset(); 357 return result; 358 } 359 360 /** 361 * Tyhjentää toistaiseksi tulostetun osan 362 */ 363 public void reset() { 364 byteoutput.reset(); 365 } 366 367 /** 368 * Kirjoittaa sisällön tietovirtaan 369 * @param out virta johon kirjoitetaan 370 * @throws IOException jos joku menee pieleen 371 * @example 372 * <pre name="test"> 373 * #THROWS IOException 374 * StringOutput so = new StringOutput(); 375 * try ( PrintStream fs = Tiedosto.avaa_kirjoittamista_varten_stream("hiljaa1.txt") ) { 376 * System.out.println("eka"); 377 * System.out.println("toka"); 378 * so.writeTo(fs); 379 * } 380 * so.palauta(); 381 * vertaaFileString("hiljaa1.txt","eka\ntoka\n") === null; 382 * tuhoaTiedosto("hiljaa1.txt"); 383 * </pre> 384 */ 385 public void writeTo(OutputStream out) throws IOException { 386 byteoutput.writeTo(out); 387 } 388 389 /** 390 * Palauttaa alkuperäisen tietovirran 391 * @return alkuperäinen tietovirta 392 */ 393 @SuppressWarnings("static-method") 394 public PrintStream getOrigOut() { 395 return origOut; 396 } 397 398 /** 399 * Vertaa tuloksen sisältöä jonoon ja palauttaa eron 400 * tai null jos samat. Tyhjentää tulosteen. 401 * @param verrattava jono johon output-jonon sisältöä verrataan 402 * @return null jos samat, muuten 1. ero 403 * @example 404 * <pre name="test"> 405 * StringOutput so = new StringOutput(); 406 * System.out.println("eka"); 407 * System.out.println("toka"); 408 * so.ero("eka\ntoka\n") === null; 409 * System.out.println("kolmas"); 410 * so.ero("eka\ntoka\nkolmas\n") === "Ero riveissä 1: kolmas ja eka"; 411 * so.toString() === ""; 412 * System.out.println("neljäs"); 413 * so.ero("neljäs\n") === null; 414 * System.out.print("viides\nkuudes"); 415 * so.ero("viides\nkuudes") === null; 416 * System.out.printf("viides%nkuudes"); 417 * so.ero("viides\nkuudes") === null; 418 * so.palauta(); 419 * so.getOrigOut() == System.out === true; 420 * </pre> 421 */ 422 public String ero(String verrattava) { 423 return VertaaTiedosto.vertaaString(toStringReset(), verrattava); 424 } 425 426 } 427 428 429 430 /** 431 * Luokka jolla System.in ja System.out suunnataan toiseen tiedostoon 432 * @author vesal 433 * @version 11.3.2007 434 */ 435 public static class InOut implements ISuuntaaja { 436 private final Input in; 437 private final Output out; 438 439 /** 440 * Asetetaan perusluku- ja tulostusvirta eri tiedostoon. 441 * Jos jompikumpi nimi on null, niin sitä virtaa ei suunnata uudelleen 442 * @param inNimi mistä tiedostosta System.in luetaan 443 * @param outNimi mihin System.out kirjoitetaan 444 * @throws FileNotFoundException jos tiedostoa ei saada käyttöön 445 * @example 446 * <pre name="test"> 447 * #THROWS IOException 448 * kirjoitaTiedosto("hiljaa1.txt", "eka\ntoka\n"); 449 * InOut io = new InOut("hiljaa1.txt","hiljaa2.txt"); 450 * Syotto.kysy("1.") === "eka"; 451 * Syotto.kysy("2.") === "toka"; 452 * Syotto.kysy("3.") === ""; 453 * io.palauta(); 454 * tuhoaTiedosto("hiljaa1.txt"); 455 * vertaaFileString("hiljaa2.txt","1. >2. >3. >") === null; 456 * tuhoaTiedosto("hiljaa2.txt"); 457 * </pre> 458 */ 459 public InOut(String inNimi, String outNimi) throws FileNotFoundException { 460 in = new Input(inNimi); 461 out = new Output(outNimi); 462 } 463 464 /** 465 * Palautetaan tietovirrat takaisin alkuperäiseen tilaan 466 */ 467 @Override 468 public void palauta() { 469 in.palauta(); 470 out.palauta(); 471 } 472 473 } 474 475 /** 476 * Testataan suuntaamista 477 * @param args ei käytössä 478 */ 479 /* 480 public static void main(String[] args) { 481 StringInput si = new StringInput("kissa\nkoira\nkana"); 482 StringOutput so = new StringOutput(); 483 String s1 = Syotto.kysy("Mikä"); 484 String so1 = so.toString(); 485 so.getOrigOut().println("so1=" + so1); 486 si = new StringInput("12\n13\n15\n16\n17"); 487 String s2 = Syotto.kysy("Kuka"); 488 //si.palauta(); 489 String s3 = Syotto.kysy("Mikä"); 490 so.reset(); 491 so.getOrigOut().println(s1 + "|" + s2 + "|" + s3); 492 String s4 = Syotto.kysy("Kuis"); 493 System.out.println(s4); 494 si = new StringInput("12\n13\n15\n16\n17"); 495 Scanner sc = new Scanner(System.in); 496 String s5 = sc.nextLine(); 497 String s6 = Syotto.kysy("No"); 498 si.palauta(); 499 String so2 = so.toString(); 500 so.palauta(); 501 System.out.println(so1 + "|" + so2 + "|" + s5 + "|" + s6); 502 } 503 */ 504 } 505