| 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