001package Torello.Java; 002 003import Torello.Java.StrIndent; 004 005import static Torello.Java.C.*; 006 007import java.util.*; 008import java.util.stream.Stream; 009import java.io.*; 010import java.util.zip.*; 011 012import com.google.cloud.storage.*; 013import com.google.auth.oauth2.*; 014 015/** 016 * <B><CODE>Load File Exception Catch</CODE></B> provides an eloquent way for printing standardized 017 * <I>(consistent-looking)</I> error messages to terminal if a data-file fails to load from the 018 * file-system, and subsequently halting the JVM - immediately. 019 * 020 * <EMBED CLASS='external-html' DATA-FILE-ID=LFEC> 021 */ 022@Torello.JavaDoc.Annotations.StaticFunctional 023public class LFEC 024{ 025 private LFEC() { } 026 027 028 // ******************************************************************************************** 029 // ******************************************************************************************** 030 // These are error-printing methods. 031 // ******************************************************************************************** 032 // ******************************************************************************************** 033 034 035 /** 036 * This prints a message and a location and halts the current thread immediately. (Halts the 037 * program) The entire rational behind the {@code class LFEC} is to facilitate loading 038 * data-files, and forcing an immediate program halt if this operation fails. Generally, 039 * during development and debugging, failing to read from a data-file is serious enough to 040 * warrant stopping the software until the issue is fixed. "Hobbling along without reading 041 * the data-files" makes little sense. 042 * 043 * <BR /><BR />When the software is being released or distributed, the philosophy turns to 044 * loading mission critical data out of data-files in a java jar-file. If the jar-file is 045 * corrupted and those files are not present, generally <I>this situation would <B>also 046 * warrant</B> halting the program execution immediately until the jar file is fixed.</I> 047 * 048 * @param t An exception, error or other {@code Throwable} that generated a problem when 049 * attempting to read a data-file. 050 * 051 * @param message This is an internally generated message explaining what has occurred. 052 */ 053 protected static void ERROR_EXIT(Throwable t, String message) 054 { 055 System.out.println( 056 '\n' + 057 "There was an error loading a data-file, and program-execution is being halted " + 058 "immediately.\n" + 059 "Problem Encountered With:\n" + StrIndent.indent(message, 4) + "\n" + 060 "Exception or Error Message:\n" + 061 EXCC.toString(t) + "\n\n" + 062 "Exiting Program, Fatal Error Loading Critical Data File." 063 ); 064 065 System.exit(1); 066 } 067 068 /** 069 * This prints a message and a location and halts the current thread immediately. (Halts the 070 * program) The entire rational behind the {@code class LFEC} is to facilitate loading 071 * data-files, and forcing an immediate program halt if this operation fails. Generally, 072 * during development and debugging, failing to read from a data-file is serious enough to 073 * warrant stopping the software until the issue is fixed. "Hobbling along without reading 074 * the data-files" makes little sense. 075 * 076 * <BR /><BR />When the software is being released or distributed, the philosophy turns to 077 * loading mission critical data out of data-files in a java jar-file. If the jar-file is 078 * corrupted and those files are not present, generally <I>this situation would <B>also 079 * warrant</B> halting the program execution immediately until the jar file is fixed.</I> 080 * 081 * @param message This is an internally generated message explaining what has occurred. 082 */ 083 protected static void ERROR_EXIT(String message) 084 { 085 System.out.println( 086 '\n' + 087 "There was an error loading a data-file, and program-execution is being halted " + 088 "immediately.\n" + 089 "Problem Encountered With:\n" + message + "\n\n" + 090 "Exiting Program, Fatal Error Loading Critical Data File." 091 ); 092 093 System.exit(1); 094 } 095 096 097 // ******************************************************************************************** 098 // ******************************************************************************************** 099 // These are the data-loading methods. 100 // ******************************************************************************************** 101 // ******************************************************************************************** 102 103 104 /** 105 * Loads a file directly into a java-{@code String.} If this file fails to load, it halts the 106 * run-time environment. 107 * 108 * @param f This is a {@code java.lang.String} that contains the filename. 109 * 110 * @return The returned {@code String} contains the entire contents of the file. 111 * 112 * @see FileRW#loadFileToString(String) 113 * @see #ERROR_EXIT(Throwable, String) 114 */ 115 public static String loadFile(String f) 116 { 117 try 118 { return FileRW.loadFileToString(f); } 119 120 catch (Throwable t) 121 { ERROR_EXIT(t, "FileRW.loadFileToString(\"" + f + "\")"); } 122 123 throw new UnreachableError(); // Should not be possible to reach this statement 124 } 125 126 /** 127 * Loads a file directory to a string <I>from a java jar-file</I>. It halts the program, and 128 * prints a detailed message if any {@code Error's} or {@code Exception's} were thrown. The 129 * directory inside the jar-file where this file may be located identified by parameter 130 * {@code class 'classLoaderClass'}. 131 * 132 * @param classLoaderClass 133 * <EMBED CLASS='external-html' DATA-FILE-ID=LFEC_CLASS_LOAD_C> 134 * <EMBED CLASS='external-html' DATA-FILE-ID=RAWTYPES> 135 * 136 * @param f This is a {@code String} that contains the filename of the data-file that needs 137 * to be loaded. It is a 'relative file-name' that is relative to the jar-file / directory pair 138 * location that the class loader identifies using the {@code Class} from parameter 139 * {@code 'classLoaderClass'} 140 * 141 * @return The returned string contains the entire contents of the file. 142 * 143 * @see #ERROR_EXIT(Throwable, String) 144 */ 145 public static String loadFile_JAR(Class<?> classLoaderClass, String f) 146 { 147 // These are 'java.lang.AutoCloseable', and java handles them automatically 148 // if there is an exception 149 150 try ( 151 InputStream is = classLoaderClass.getResourceAsStream(f); 152 BufferedReader br = new BufferedReader(new InputStreamReader(is)); 153 ) 154 { 155 String s = ""; 156 StringBuffer sb = new StringBuffer(); 157 158 while ((s = br.readLine()) != null) sb.append(s + "\n"); 159 160 return sb.toString(); 161 } 162 163 catch (Throwable t) 164 { 165 ERROR_EXIT( 166 t, 167 "Error loading text-file [" + f + "] from jar-file.\n" + 168 "Class loader attempted to use information in class " + 169 "[" + classLoaderClass.getCanonicalName() + "], but failed." 170 ); 171 } 172 173 throw new UnreachableError(); // Should NOT be possible to reach this statement... 174 } 175 176 /** 177 * Loads a file <I>from a java jar-file</I> using an {@code InputStream} and copies that file, 178 * byte-for-byte, to {@code 'targetFileName'}. A detailed message is printed if any 179 * {@code Error's} or {@code Exception's} were thrown. The directory inside the jar-file 180 * where this file may be located identified by parameter {@code class 'classLoaderClass'}. 181 * 182 * @param classLoaderClass <EMBED CLASS='external-html' DATA-FILE-ID=LFEC_CLASS_LOAD_C> 183 * <EMBED CLASS='external-html' DATA-FILE-ID=RAWTYPES> 184 * 185 * @param fileName This is a {@code String} that contains the filename of the data-file that 186 * needs to be copied. It is a 'relative file-name' that is relative to the jar-file / 187 * directory pair location that the class loader identifies using the {@code Class} from 188 * parameter {@code 'classLoaderClass'}. 189 * 190 * @param targetFileName This is the file and directory that contains the target location 191 * (as a {@code String}) to where the file should be copied. 192 * 193 * @see #ERROR_EXIT(Throwable, String) 194 */ 195 public static void copyFile_JAR 196 (Class<?> classLoaderClass, String fileName, String targetFileName) 197 { 198 // These are 'java.lang.AutoCloseable', and java handles them automatically 199 // if there is an exception 200 201 try ( 202 InputStream is = classLoaderClass.getResourceAsStream(fileName); 203 FileOutputStream fos = new FileOutputStream(targetFileName); 204 ) 205 { 206 byte[] b = new byte[5000]; 207 int result = 0; 208 209 while ((result = is.read(b)) != -1) fos.write(b, 0, result); 210 } 211 212 catch (Throwable t) 213 { 214 ERROR_EXIT( 215 t, 216 "Error copying file [" + fileName + "] from jar-file to " + 217 "[" + targetFileName + "].\n" + 218 "Class loader attempted to use information in class " + 219 "[" + classLoaderClass.getCanonicalName() + "]." 220 ); 221 } 222 } 223 224 /** 225 * This loads a file to a {@code Vector} of {@code String's}. It halts the program, and prints 226 * a detailed message if any errors or exceptions occur. 227 * 228 * @param f The name of the file to load 229 * 230 * @param includeNewLine States whether the {@code '\n'} (new-line) character should be appended 231 * to each element of the returned {@code Vector<String>}. 232 * 233 * @return a {@code Vector} of {@code String's}, where each element in the {@code Vector} is a 234 * line retrieved from the text-file. 235 * 236 * @see #ERROR_EXIT(Throwable, String) 237 */ 238 public static Vector<String> loadFileToVector(String f, boolean includeNewLine) 239 { 240 try 241 { return FileRW.loadFileToVector(f, includeNewLine); } 242 243 catch (Throwable t) 244 { 245 ERROR_EXIT( 246 t, 247 "Attempting to Invoke this Load-Method with these Arguments:\n" + 248 "FileRW.loadFileToVector(\"" + f + "\", " + includeNewLine + ");" 249 ); 250 } 251 252 throw new UnreachableError(); // Should NOT be possible to reach this statement... 253 } 254 255 256 /** 257 * This loads a file to a {@code Stream} of {@code String's}. It halts the program, and prints 258 * a detailed message if any errors or exceptions occur. 259 * 260 * @param f The name of the file to load 261 * 262 * @param includeNewLine States whether the {@code '\n'} (new-line) character should be appended 263 * to each element of the returned {@code Vector<String>}. 264 * 265 * @return a {@code Stream} of {@code String's}, where each element in the {@code Stream} is a 266 * line retrieved from the text-file. 267 * 268 * @see #ERROR_EXIT(Throwable, String) 269 */ 270 public static Stream<String> loadFileToStream(String f, boolean includeNewLine) 271 { 272 try 273 { return FileRW.loadFileToStream(f, includeNewLine); } 274 275 catch (Throwable t) 276 { 277 ERROR_EXIT( 278 t, 279 "Attempting to Invoke this Load-Method with these Arguments:\n" + 280 "FileRW.loadFileToStream(\"" + f + "\", " + includeNewLine + ");" 281 ); 282 } 283 284 throw new UnreachableError(); // Should NOT be possible to reach this statement... 285 } 286 287 /** 288 * This loads a file to a {@code Vector} of {@code String's}. It halts the program, and prints 289 * a detailed message if any {@code Error's} or {@code Exception's} occur. The directory inside 290 * the jar-file where this file may be located identified by parameter 291 * {@code 'classLoaderClass'}. 292 * 293 * @param classLoaderClass <EMBED CLASS='external-html' DATA-FILE-ID=LFEC_CLASS_LOAD_C> 294 * <EMBED CLASS='external-html' DATA-FILE-ID=RAWTYPES> 295 * 296 * @param f This is a {@code String} that contains the filename of the data-file that needs to 297 * be loaded. It is a 'relative file-name' that is relative to the jar-file / directory pair 298 * location that the class loader identifies using the {@code Class} from parameter 299 * {@code 'classLoaderClass'}. 300 * 301 * @param includeNewLine States whether the {@code '\n'} (newline) character should be appended 302 * to each element of the {@code Vector}. 303 * 304 * @return a {@code Vector} of {@code String's}, where each element in the {@code Vector} is a 305 * line retrieved from the text-file. 306 * 307 * @see #ERROR_EXIT(Throwable, String) 308 */ 309 public static Vector<String> loadFileToVector_JAR 310 (Class<?> classLoaderClass, String f, boolean includeNewLine) 311 { 312 // These are 'java.lang.AutoCloseable', and java handles them automatically 313 // if there is an exception 314 315 try ( 316 InputStream is = classLoaderClass.getResourceAsStream(f); 317 BufferedReader br = new BufferedReader(new InputStreamReader(is)); 318 ) 319 { 320 String s = ""; 321 Vector<String> ret = new Vector<>(); 322 323 if (includeNewLine) 324 while ((s = br.readLine()) != null) 325 ret.addElement(s + '\n'); 326 327 else 328 while ((s = br.readLine()) != null) 329 ret.addElement(s); 330 331 return ret; 332 } 333 334 catch (Throwable t) 335 { 336 ERROR_EXIT( 337 t, 338 "Error loading text-file [" + f + "] from jar-file.\n" + 339 "Parameter includeNewLine was: " + includeNewLine + "\n" + 340 "Class loader attempted to use information in class " + 341 "[" + classLoaderClass.getCanonicalName() + "], but failed." 342 ); 343 } 344 345 throw new UnreachableError(); // Should NOT be possible to reach this statement... 346 } 347 348 /** 349 * This loads a {@code java.lang.Object} from a data-file. 350 * <EMBED CLASS='external-html' DATA-FILE-ID=LFEC_CONTAINER> 351 * 352 * @param f The name of the file containing a serialized {@code java.lang.Object} to load 353 * 354 * @param zip This should be <I>TRUE</I> if, when serialized, the {@code Object} was compressed 355 * too, and <I>FALSE</I> if compression was not used. 356 * 357 * @param returnClass <EMBED CLASS='external-html' DATA-FILE-ID=LFEC_RET_CLASS> 358 * 359 * @param <T> This type parameter is simply provided for convenience, to allow the user to 360 * specify the return class, without having to cast the object and suppress warnings, or catch 361 * exceptions. 362 * 363 * @return A de-serialized {@code java.lang.Object} present in the data-file passed by-name 364 * through file-name parameter {@code 'f'}, and cast to the type denoted by parameter 365 * {@code returnClass}. 366 * 367 * @see FileRW#readObjectFromFile(String, boolean) 368 * @see #ERROR_EXIT(Throwable, String) 369 */ 370 public static <T> T readObjectFromFile(String f, boolean zip, Class<T> returnClass) 371 { 372 try 373 { 374 Object ret = FileRW.readObjectFromFile(f, zip); 375 376 if (! returnClass.isInstance(ret)) 377 378 ERROR_EXIT( 379 "Serialized Object from file: " + f + "\n" + 380 "Using expected (" + (zip ? "zip-compression" : "no-compression") + ")\n" + 381 "Didn't have an object with class-name: [" + returnClass + "]\n" + 382 "but rather with class-name: [" + ret.getClass().getName() + "]" 383 ); 384 385 return returnClass.cast(ret); 386 } 387 388 catch (Throwable t) 389 { 390 ERROR_EXIT( 391 t, 392 "Exception reading Serialized Object from file: " + f + "\n" + 393 "With intended read class-name of: " + returnClass + "\n" + 394 "Using expected (" + (zip ? "zip-compression" : "no-compression") + ")\n" 395 ); 396 } 397 398 throw new UnreachableError(); // Should NOT be possible to reach this statement... 399 } 400 401 /** 402 * This loads a {@code java.lang.Object} from a data-file located in a JAR File. 403 * <EMBED CLASS='external-html' DATA-FILE-ID=LFEC_CONTAINER> 404 * 405 * @param classLoaderClass <EMBED CLASS='external-html' DATA-FILE-ID=LFEC_CLASS_LOAD_C> 406 * <EMBED CLASS='external-html' DATA-FILE-ID=RAWTYPES> 407 * 408 * @param f The name of the file containing a serialized {@code java.lang.Object} to load 409 * 410 * @param zip This should be <I>TRUE</I> if, when serialized, the {@code Object} was compressed 411 * too, and <I>FALSE</I> if compression was not used. 412 * 413 * @param returnClass <EMBED CLASS='external-html' DATA-FILE-ID=LFEC_RET_CLASS> 414 * 415 * @param <T> This type parameter is simply provided for convenience, to allow the user to 416 * specify the return class, without having to cast the object and suppress warnings, or catch 417 * exceptions. 418 * 419 * @return a de-serialized {@code java.lang.Object} present in the data-file passed by-name 420 * through file-name parameter {@code 'f'}, and cast to the type denoted by parameter 421 * {@code 'returnClass'}. 422 * 423 * @see #ERROR_EXIT(Throwable, String) 424 */ 425 public static <T> T readObjectFromFile_JAR 426 (Class<?> classLoaderClass, String f, boolean zip, Class<T> returnClass) 427 { 428 // These are 'java.lang.AutoCloseable', and java handles them automatically 429 // if there is an exception 430 431 final InputStream checked = classLoaderClass.getResourceAsStream(f); 432 433 // If the resource is not there. the "InputStream" would be null, and NPE would throw 434 if (checked == null) ERROR_EXIT( 435 "Serialized Object from jar-file loading-using class: " + 436 classLoaderClass.getCanonicalName() + "\n" + 437 "Looking for data-file named: " + f + "\n" + 438 "This file or resource was not found on disk or in the jar" 439 ); 440 441 try ( 442 InputStream raw = checked; 443 InputStream is = zip ? new GZIPInputStream(raw) : raw; 444 ObjectInputStream ois = new ObjectInputStream(is) 445 ) 446 { 447 Object ret = ois.readObject(); 448 449 if (! returnClass.isInstance(ret)) ERROR_EXIT( 450 "Serialized Object from jar-file loading-using class: " + 451 classLoaderClass.getCanonicalName() + "\n" + 452 "Looking for data-file named: " + f + "\n" + 453 "Using expected (" + (zip ? "zip-compression" : "no-compression") + ")\n" + 454 "Didn't have an object with class-name: [" + returnClass + "]\n" + 455 "but rather with class-name: [" + ret.getClass().getName() + "]" 456 ); 457 458 return returnClass.cast(ret); 459 } 460 461 catch (Throwable t) 462 { 463 ERROR_EXIT( 464 t, 465 "Exception reading Serialized Object from jar-file, loading-using class: " + 466 classLoaderClass.getCanonicalName() + "\n" + 467 "Looking for data-file named: " + f + "\n" + 468 "And attempting to retrieve an object having class-name: " + returnClass + "\n" + 469 "Using expected (" + (zip ? "zip-compression" : "no-compression") + ")\n" 470 ); 471 472 throw new UnreachableError(); // Should NOT be possible to reach this statement... 473 } 474 } 475 476 477 // ******************************************************************************************** 478 // ******************************************************************************************** 479 // Google Cloud Server - Public Static Inner Class 480 // ******************************************************************************************** 481 // ******************************************************************************************** 482 483 484 /** 485 * The Google Cloud Server Storage Bucket extension of "Load File Exception Catch" does the 486 * work that <CODE>LFEC</CODE> does, but for GCS Storage Buckets, rather than operating 487 * system files. 488 * 489 * <EMBED CLASS='external-html' DATA-FILE-ID=LFEC_GCSSB> 490 */ 491 @Torello.JavaDoc.Annotations.StaticFunctional 492 public static class GCSSB 493 { 494 private GCSSB() { } 495 496 /** 497 * This will read a Java Serialized {@code java.lang.Object} from a location in a Google 498 * Cloud Server {@code Storage Bucket}. 499 * 500 * @param storage <EMBED CLASS='external-html' DATA-FILE-ID=GCSSB_STORAGE> 501 * 502 * @param bucket The {@code bucket} name of the {@code bucket} from a Google Cloud Server 503 * account. 504 * 505 * @param completeFileName <EMBED CLASS='external-html' DATA-FILE-ID=GCSSB_CMPL_FNAME> 506 * 507 * @param zip <EMBED CLASS='external-html' DATA-FILE-ID=GCSSB_ZIP> 508 * 509 * @param returnClass This is the type expected to be found by Java in the Serialized 510 * {@code Object} Data-File. If an {@code Object} is read from this location, but it does 511 * not have the type indicated by this parameter, the program will also halt, and an 512 * explanatory exception message will be printed to the console/terminal. 513 * 514 * @param <T> This type parameter is simply provided for convenience, to allow the user 515 * to specify the return class, without having to cast the object and suppress warnings, 516 * or catch exceptions. 517 * 518 * @return A de-serialized java {@code java.lang.Object} that has been read from a GCS 519 * {@code Storage Bucket}, and cast to the type denoted by parameter 520 * {@code 'returnClass'}. 521 * 522 * @see FileRW#readObjectFromFile(String, boolean) 523 * @see FileRW#readObjectFromFileNOCNFE(String, boolean) 524 * @see #readObjectFromFile(String, boolean, Class) 525 * @see #ERROR_EXIT(String) 526 */ 527 public static <T> T readObjectFromFile( 528 Storage storage, String bucket, String completeFileName, 529 boolean zip, Class<T> returnClass 530 ) 531 { 532 try 533 { 534 // Read Storage Bucket Data into a byte[] array 535 byte[] bArr = storage.get(bucket, completeFileName).getContent(); 536 537 // Build an Input Stream, using that byte[] array as input 538 ByteArrayInputStream bis = new ByteArrayInputStream(bArr); 539 540 // Build an Object Input Stream, using the byte-array input-stream as input 541 ObjectInputStream ois = zip 542 ? new ObjectInputStream(new GZIPInputStream(bis)) 543 : new ObjectInputStream(bis); 544 545 // Use Java's Object Serialization method to read the Object 546 Object ret = ois.readObject(); 547 548 if (! returnClass.isInstance(ret)) ERROR_EXIT( 549 "Serialized Object read from GCS Storage Bucket: " + bucket + "\n" + 550 "And file-name: " + completeFileName + "\n" + 551 "Using expected (" + (zip ? "zip-compression" : "no-compression") + ")\n" + 552 "Didn't have an object with class-name: " + returnClass + "\n" + 553 "But rather with className: " + ret.getClass().getName() 554 ); 555 556 ois.close(); bis.close(); 557 558 return returnClass.cast(ret); 559 } 560 561 catch (Throwable t) 562 { 563 ERROR_EXIT( 564 t, 565 "Serialized Object read from GCS Storage Bucket: " + bucket + "\n" + 566 "And file-name: " + completeFileName + "\n" + 567 "Using expected (" + (zip ? "zip-compression" : "no-compression") + ")\n" + 568 "And Expected class-name: " + returnClass + "\n" 569 ); 570 571 throw new UnreachableError(); // Cannot reach this statement 572 } 573 } 574 575 /** 576 * This merely loads a text-file from Google's Storage Bucket infrastructure into a 577 * {@code String.} Make sure to check that the file you are loading does indeed have 578 * text-content. 579 * 580 * @param storage <EMBED CLASS='external-html' DATA-FILE-ID=GCSSB_STORAGE> 581 * 582 * @param bucket The {@code bucket} name of the {@code bucket} from a Google Cloud Server 583 * account. 584 * 585 * @param completeFileName <EMBED CLASS='external-html' DATA-FILE-ID=GCSSB_CMPL_FNAME> 586 * 587 * @return The text file on Google Cloud Server's Storage Bucket file/directory returned as 588 * a {@code java.lang.String} 589 */ 590 public static String loadFileToString 591 (Storage storage, String bucket, String completeFileName) 592 { return new String(storage.get(bucket, completeFileName).getContent()); } 593 594 /** 595 * This merely loads a text-file from Google's Storage Bucket infrastructure into a 596 * {@code String}. Make sure to check that the file you are loading does indeed have 597 * text-content. 598 * 599 * @param storage <EMBED CLASS='external-html' DATA-FILE-ID=GCSSB_STORAGE> 600 * 601 * @param bucket The {@code bucket} name of the {@code bucket} from a Google Cloud Server 602 * account. 603 * 604 * @param completeFileName <EMBED CLASS='external-html' DATA-FILE-ID=GCSSB_CMPL_FNAME> 605 * 606 * @param includeNewLine This tells the method to include, or not-include, a {@code '\n'} 607 * (newline) character to each {@code String}. 608 * 609 * @return The text file on Google Cloud Server's {@code Storage Bucket} file/directory 610 * stuff as a {@code Vector} of {@code String's}. 611 * 612 * @see #loadFileToString(Storage, String, String) 613 */ 614 public static Vector<String> loadFileToVector 615 (Storage storage, String bucket, String completeFileName, boolean includeNewLine) 616 { 617 String s = loadFileToString(storage, bucket, completeFileName); 618 Vector<String> ret = new Vector<>(); 619 620 int pos = 0; 621 int delta = includeNewLine ? 1 : 0; 622 int lastPos = 0; 623 624 while ((pos = s.indexOf('\n')) != -1) 625 { 626 ret.add(s.substring(lastPos, pos + delta)); 627 lastPos = pos + 1; 628 } 629 630 if (lastPos < s.length()) ret.add(s.substring(lastPos)); 631 632 return ret; 633 } 634 635 /** 636 * This will write the contents of a java {@code 'CharSequence'} - includes 637 * {@code String, StringBuffer & StringBuilder} to a file on Google Cloud Server's 638 * storage bucket system. 639 * 640 * @param storage <EMBED CLASS='external-html' DATA-FILE-ID=GCSSB_STORAGE> 641 * 642 * @param bucket The {@code bucket} name of the {@code bucket} from a Google Cloud Server 643 * account. 644 * 645 * @param completeFileName <EMBED CLASS='external-html' DATA-FILE-ID=GCSSB_CMPL_FNAME> 646 * 647 * @param ASCIIorUTF8 When writing java {@code String's} the file-system, it is generally 648 * not to important to worry about whether java has stored an {@code 'ASCII'} encoded 649 * {@code String}, or a {@code String} encoded using {@code 'UTF-8'}. Most 650 * foreign-language news-sites require the latter ({@code 'UTF-8'}), but any site that is 651 * strictly English can get by with plain old ASCII. 652 * 653 * <BR /><BR /><DIV CLASS=JDHint> 654 * <B STYLE="color: red">Important:</B> When this boolean is 655 * {@code TRUE}, this method will attempt to presume the character-sequence you have passed 656 * is in ASCII, and write it that way. When this boolean is set to {@code FALSE}, 657 * this method will attempt to write the {@code String} of {@code byte's} as a 658 * {@code 'UTF-8'} encoded character-set. 659 * </DIV> 660 * 661 * <BR /><DIV CLASS=JDHintAlt> 662 * <B STYLE="color: red">Also:</B> I have not made any allowance for Unicode or Unicode 663 * little endian, because I have never used them with either the Chinese or Spanish sites I 664 * scrape. UTF-8 has been the only other character set I encounter. 665 * </DIV> 666 */ 667 public static void writeFile( 668 CharSequence fileAsStr, Storage storage, String bucket, 669 String completeFileName, boolean ASCIIorUTF8 670 ) 671 { 672 BlobInfo blobInfo = BlobInfo.newBuilder 673 (BlobId.of(bucket, completeFileName)).setContentType("text/plain").build(); 674 675 byte[] file = ASCIIorUTF8 676 ? fileAsStr.toString().getBytes() 677 : fileAsStr.toString().getBytes(java.nio.charset.Charset.forName("UTF-8")); 678 679 Blob blob = storage.create(blobInfo, file); 680 } 681 682 /** 683 * This will write a Java {@code Serializable Object} to a location in a Google Cloud 684 * Server Storage Bucket. 685 * 686 * @param storage <EMBED CLASS='external-html' DATA-FILE-ID=GCSSB_STORAGE> 687 * 688 * @param o This may be any {@code Serializable Java Object}. {@code Serializable Java 689 * Objects} are ones which implement the {@code interface java.io.Serializable}. 690 * 691 * @param bucket The {@code bucket} name of the {@code bucket} from a Google Cloud Server 692 * account. 693 * 694 * @param completeFileName <EMBED CLASS='external-html' DATA-FILE-ID=GCSSB_CMPL_FNAME> 695 * 696 * @param zip <EMBED CLASS='external-html' DATA-FILE-ID=GCSSB_ZIP> 697 */ 698 public static void writeObjectToFile( 699 Object o, Storage storage, String bucket, 700 String completeFileName, boolean zip 701 ) 702 throws IOException 703 { 704 // Retrieves a file-name object using a GCS BUCKET-NAME, and the FILE-NAME (in 705 // the bucket) 706 707 BlobId blobId = BlobId.of(bucket, completeFileName); 708 709 710 // This BlobInfo is GCS version of "java.io.File". It points to a specific file 711 // inside a GCS Bucket (which was specified earlier) 712 713 BlobInfo blobInfo = BlobInfo 714 .newBuilder(blobId) 715 // .setContentType("text/plain") 716 .build(); 717 718 // This will save the Serialized Object Data to a Stream (and eventually an array) 719 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 720 721 // This stream writes serialized Java-Objects to the Storage Bucket 722 ObjectOutputStream oos = zip 723 ? new ObjectOutputStream(new GZIPOutputStream(baos)) 724 : new ObjectOutputStream(baos); 725 726 oos.writeObject(o); 727 728 oos.flush(); baos.flush(); oos.close(); 729 730 // Convert that BAOS to a Byte-Array 731 byte[] bArr = baos.toByteArray(); 732 733 734 // Write the BYTE-ARRAY to the GCS Bucket and file using the "BlobInfo" that was built 735 // a few lines ago. 736 737 Blob blob = storage.create(blobInfo, bArr); 738 } 739 } 740}