{"id":41389950,"url":"https://github.com/fralalonde/iostream","last_synced_at":"2026-01-23T12:28:57.003Z","repository":{"id":54309860,"uuid":"80986769","full_name":"fralalonde/iostream","owner":"fralalonde","description":"Java IO streams handling sugar library","archived":false,"fork":false,"pushed_at":"2023-06-27T04:39:42.000Z","size":356,"stargazers_count":8,"open_issues_count":3,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-08-01T07:57:20.418Z","etag":null,"topics":["base64","buffered","builder","charset","fluent","gzip","inputstream","intstream","iostreams","java","outputstream","pipe","printwriter","random","reader","socket","writer"],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fralalonde.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-02-05T10:53:45.000Z","updated_at":"2024-09-19T18:41:33.000Z","dependencies_parsed_at":"2022-08-13T11:40:31.945Z","dependency_job_id":null,"html_url":"https://github.com/fralalonde/iostream","commit_stats":null,"previous_names":[],"tags_count":21,"template":false,"template_full_name":null,"purl":"pkg:github/fralalonde/iostream","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fralalonde%2Fiostream","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fralalonde%2Fiostream/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fralalonde%2Fiostream/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fralalonde%2Fiostream/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fralalonde","download_url":"https://codeload.github.com/fralalonde/iostream/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fralalonde%2Fiostream/sbom","scorecard":{"id":408859,"data":{"date":"2025-08-11","repo":{"name":"github.com/fralalonde/iostream","commit":"ebfb76ccb60c78ed94565867a8a1cca56523269e"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Code-Review","score":0,"reason":"Found 0/28 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Mozilla Public License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 3 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-18T22:06:55.763Z","repository_id":54309860,"created_at":"2025-08-18T22:06:55.763Z","updated_at":"2025-08-18T22:06:55.763Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28691354,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-23T11:01:27.039Z","status":"ssl_error","status_checked_at":"2026-01-23T11:00:26.909Z","response_time":59,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["base64","buffered","builder","charset","fluent","gzip","inputstream","intstream","iostreams","java","outputstream","pipe","printwriter","random","reader","socket","writer"],"created_at":"2026-01-23T12:28:56.392Z","updated_at":"2026-01-23T12:28:56.991Z","avatar_url":"https://github.com/fralalonde.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# IoStream\n\n[![Codecov](https://img.shields.io/codecov/c/github/fralalonde/IO.svg)](https://codecov.io/gh/fralalonde/iostream)\n[![Maven Central](https://img.shields.io/maven-central/v/ca.rbon/IO.svg)](http://search.maven.org/#search%7Cga%7C1%7Crbon)\n[![License: MPL 2.0](https://img.shields.io/badge/License-MPL%202.0-brightgreen.svg)](https://opensource.org/licenses/MPL-2.0)\n[![Javadocs](http://www.javadoc.io/badge/ca.rbon/IO.svg)](http://www.javadoc.io/doc/ca.rbon/iostream)\n[![Dependencies](https://www.versioneye.com/user/projects/58b8255d01b5b7003d6201bc/badge.svg)](https://www.versioneye.com/user/projects/58b8255d01b5b7003d6201bc?child=summary)\n\nA fun experiment revisiting classic Java I/O API.\n\n* Fluent builder for Java standard InputStream, OutputStream, Reader and Writer and Filter classes\n* Provides File, ByteArray, String, Socket, Pipe, Buffered, Zip, Console and generic stream wrapper resources\n* Supports Base64, GZip and Cipher filters\n* Retains default Java behavior and parameters  \n* Composed objects are unambiguously closed as one\n* Composed objects expose underlying resource for retrieval of results / follow up operations\n\n```java\ntry (PrintWriterOf\u003cFile\u003e fileWriter = IO.file(\"myfile.gz\").gzip().printWriter()) {\n    File theFile = fileWriter.get();\n    fileWriter.write(\"Hello from file \" + theFile.getName());\n}\n```  \n\n_\"It's the little things\"_\n\n## What is this for?\n\nPart of the original JDK 1.0, Java's original blocking I/O API celebrated it's 21st birthday on January 23, 2017. The _venerable_ Java \"streams\" classes are now of legal drinking age in most of the places they're allowed to go! And because of Java's insistence on backward compatibility, everything is still as it was back then. Everything but the rest of the world, that is. Ahem. Who feels like programming like it's 1996?\n\nMind you, there isn't much that is broken with the streams functionality. Sequential I/O is not something that changes much, if ever. It's just that the classes have become somewhat unwieldy when used alongside contemporary Java libraries. Let's give them a little makeover, shall we?\n\nIf you are using Maven, start by adding this snippet to your `pom.xml`\n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003eca.rbon\u003c/groupId\u003e\n    \u003cartifactId\u003eiostream\u003c/artifactId\u003e\n    \u003cversion\u003e0.9.1\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nSadly I do no have gradle at the ready, but I'm sure you smart foxes will know where to \ninsert what I believe to be `ca.rbon:iostream:0.9.1`.\n\nBecause it uses default interface methods, this library requires Java 1.8 (and nothing but).\n      \n## How does it work?\n\nFirst, `IoStream` wraps the streams and their charset aware sibblings in a more palatable \nfluent-builder (or _Factory Method_, for you pattern freaks) so you don't have to `new` anything \nwhen you need to do some sweet blocking I/O. \n```java\nimport ca.rbon.iostream.IO;\n``` \nThen start by typing `IO.` and autocomplete-away!\n\n### Building\nBecause streams and readers/writers are often paired together, \nthe fluent builder guides you from the selection of the underlying resource (`File`, `byte[]`, `Socket`...) \nto the way of accessing it (`BufferedStream`, `ZipStream`, `Writer`...). \n```java\nPrintWriter writer = IO.file(\"yesss.txt\").printWriter();\n```\nYou will notice that `printWriter()` above actually returns something called `PrintWriterOf\u003cFile\u003e`. \nThis is a subclass of the standard `java.io.PrintWriter` that  can be safely use as such. \nAll `IoStream` final methods return `*Of\u003cFile\u003e` classes extending normal `java.io` classes. \nTheir added functionality is explained below (hint: checkout their `getInner()` method.).\n\nIf a resource only implements streams (like `socket()`), and you require `Writer` or `Reader` \nchar-oriented access, the builder will transparently insert an `OutputStreamWriter` or `InputStreamReader` \nadapter for you.\n```java\nBufferedWriter writer = IO.socket(\"spamaway.net\", 25).bufferedWriter();\n``` \n\n### try-with syntax\nObviously, `IoStream` goes hand in hand with the try-with syntax introduced in JDK 7.\n```java\ntry (Writer w = IO.file(\"mouha.txt\").printWriter()) {\n    w.append(\"haha\");\n}\n```\n\n### Retrieving inner results \nIt is often required to access the resource after all streams are closed in order to obtain the \nfinal operation result. This is a pattern especially common with auto-instantiated resources such as byte \narrays out streams, string writers or temp files.\n\n`IoStream` makes the job easier by allowing access to the resulting resource straight from the outmost object. \nThis is done magically with IoStream's `*Of\u003cT\u003e` classes, which subclass regular `java.io` classes.\nBecause we are modern, sane people, we can ignore this detail by using the `var` keyword from JDK 10+.\n Then all you have to do is call the `getInner()` method to retrieve the inner resource you just built.\n```java\nvar writer = IO.bytes().printWriter();\n// ...\nwriter.close();\nbyte[] myPrecious = writer.getInner();\n```\nBy comparison, classic JDK code forces you to juggle with the inner and outer streams: \n```java\nByteArrayOutputStream innerStream = new ByteArrayOutputStream();\nWriter outerStream = new PrintWriter(innerStream);\n// ...\nouterStream.close();\nbyte[] myPrecious = innerStream.toByteArray();\n```\n\n## Companion libraries\n\n`IoStream` is an excellent companion to Apache Commons IO's \n[IOUtils class](https://commons.apache.org/proper/commons-io/javadocs/api-2.4/index.html?org/apache/commons/io/IOUtils.html). \nThere is little overlap between the libraries. \n`IoStream` helps to build the streams while `IOUtils` takes care of the operations, such as `copy()` :\n\n```java\ntry (var in = IO.file(\"A\").reader(); var out = IO.file(\"B\").writer()) {\n    IOUtils.copy(in, out);\n}\n```\n\n## Things you can do with it\n\n### Convert to IntStream\n\n```java\ntry (var pw = IO.file(\"numbers.bin\").inputStream()) {\n    pw.intStream().sum();\n}\n```\n\n### Byte Arrays, Random \u0026 IOUtils \n```java\nIO.bytes().outputStream();\nbyte[] bytes = IO.bytes().dataOutputStream().getInner();\n\nIO.bytes(new byte[] { 0, 1, 2 }).objectInputStream();\n```\n\n### Files\n```java\nFileOutputStream out = IO.file(\"noooes.txt\").outputStream();\n\ntry (var myFile = IO.file(\"mouha.txt\").printWriter()) {\n    myFile.write(\"haha\");\n}\n   \n\nIO.file(\"doum.zip\").zipInputStream(\"UTF-8\");\nIO.file(\"dam.txt\", true).bufferedWriter();\n\nvar tmpout = IO.tempFile().dataOutputStream();\ntmpout.write(42);\nString tmpFilename = tmpout.getInner().getAbsolutePath();\n```\n\n### Strings\n```java\nIO.string(\"agaga gogo\").bufferedReader();\nIO.string(\"agaga gogo\").reader();\n\nString str = IO.string().bufferedWriter().getInner();\n```\n\n### Sockets\n```java\nIO.socket(\"gloogloo.com\", 80).bufferedOutputStream();\nInputStream smtpHoneypot = IO.socket(\"localhost\", 25).inputStream(); \n```\n\n### Pipe\n```java\nIO.socket(\"gloogloo.com\", 80).bufferedOutputStream();\nInputStream smtpHoneypot = IO.socket(\"localhost\", 25).inputStream(); \n```\n\n### Random \n```java\ntry (var pw = IO.random().inputStream()) {\n\t// add 5 random numbers\n    pw.intStream().limit(5).sum();\n}\n```\n\n### Existing input and output streams integration\n```java\nInputStream providedInput = new ByteArrayInputStream(new byte[7]);\nIO.stream(providedInput).gzipInputStream();\n\nOutputStream providedOutput = new ByteArrayOutputStream();\nIO.stream(providedOutput).printWriter(256);\n```\n\n### Writing text to a File, GZipped, Base64, UTF-16 encoded. 256-byte buffer, autoflush.\n```java\n// this example is pretty extreme\ntry (var pw = IO.file(\"myfile.txt\").base64().gzip(55).printWriter(\"UTF-16\", 256, true)) {\n    File myFileTxt = pw.getInner();\n    pw.write(\"Hello from file \" + myFileTxt.getName());\n}\n```\n\n## FAQ\n### Why not guava?\nYou mean [this](https://github.com/google/guava/wiki/IOExplained)?\nSure, but it's bigger and comes with its own classes and superseded the original Java classes.\nPlus, I could not wrap my head around it in 10 seconds, which is all it should take for such a thing. \nSo I spent 10 hours writing this lib instead.\n\n### But my eyes are _still_ bleeding!\nHey, Java can be a pain. We could push it further with compiler @Annotations or dynamically generated bytecode, \nbut then we'd have a different set of problems. \n[Why](https://www.rust-lang.org/) \n[don't](https://clojure.org/) \n[you](https://www.ceylon-lang.org/) \n[try](https://nim-lang.org/) \n[a](http://fsharp.org/) \n[different](http://www.dangermouse.net/esoteric/piet.html) \n[language](http://lolcode.org/)?     \n\n### Why doesn't `IoStream` support _$feature_\nThe goal is to support just Java stream classes (Sockets, Pipes) with their original semantics. \nNo additional transitive deps. No fixing of the original sins. \nSome parts are still missing, but once it's done, it's done. You'll know because it'll be version 1.0.   \n\n## Samples\n\n### Standard comparison\n\nIoStream enabled-code \n```java\npublic byte[] usingIoStream() throws IOException {\n    var writer = IO.bytes().printWriter();\n    writer.write(\"doodoo\");\n    writer.close();\n    return writer.getInner();\n}\n```\n  \nClassic java streams \n```java\npublic byte[] classicStreams() throws IOException {\n    ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();\n    PrintWriter writer = new PrintWriter(byteOutputStream);\n    writer.write(\"doodoo\");\n    writer.close();\n    byteOutputStream.close();\n    return byteOutputStream.toByteArray();\n}\n```\n\n### Commented\nIoStream enabled-code \n```java\npublic byte[] fluent() throws IOException {\n    // create and combine both objects\n    var writer = IO.bytes().printWriter();\n\n    // write the string\n    writer.write(\"doodoo\");\n\n    // close the writer and the inner stream at once\n    writer.close();\n\n    // extract result\n    return writer.getInner();\n}\n```\n  \nClassic java streams \n```java\npublic byte[] classic() throws IOException {\n    // explicitly create inner stream to extract result\n    ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();\n\n    // create outer writer\n    PrintWriter writer = new PrintWriter(byteOutputStream);\n\n    // write a string\n    writer.write(\"doodoo\");\n\n    // close the writer\n    writer.close();\n\n    // dont forget to close inner stream too\n    byteOutputStream.close();\n\n    // extract result from inner stream\n    return byteOutputStream.toByteArray();\n}\n```\n\n### Using try-with-resources\nIoStream enabled-code \n```java\ntry (var writer = IO.bytes().printWriter()) {\n    writer.write(\"doodoo\");\n    return writer.getInner();\n}\n```\n  \nClassic java streams \n```java\ntry (ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();\n    PrintWriter writer = new PrintWriter(byteOutputStream)) {\n    writer.write(\"doodoo\");\n    return byteOutputStream.toByteArray();\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffralalonde%2Fiostream","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffralalonde%2Fiostream","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffralalonde%2Fiostream/lists"}