0

I need to pipe data into another process. The data is an array of strings that I concatenated into one large string. The external process accepts a text file. Currently, I am writing the string into a ByteArrayOutputStream but is there a better way to do this?

public OutputStream generateBoxFile() throws IOException {
    OutputStream boxStream = new ByteArrayOutputStream();
    for (String boxLine : boxLines) {
        boxLine += "\n";
        boxStream.write(boxLine.getBytes(Charset.forName("UTF-8")));
    }
    return boxStream;
}

EDIT: For further clarifications, I am launching a program called trainer which accepts a text file. So I would invoke this program like this in the shell ./trainer textfile. However, I want to do everything in memory, so I'm looking for a good way to write data into a temporary file that is not on disk and then feed this into trainer.

mrQWERTY
  • 4,039
  • 13
  • 43
  • 91
  • Doesn't it work? Is there any problem you have with that setup? – Philipp Jun 26 '15 at 13:10
  • Do I need to convert this into an InputStream in order to write it into some external process? I've been trying to look that up. But I was wondering if there was something that doesn't care about which direction the stream goes and that you can write into it or get stuff out of it. – mrQWERTY Jun 26 '15 at 13:12
  • Define "other process"; do you mean this as a process created by your operating system or something else? How is the full chain invoked? – fge Jun 26 '15 at 13:13
  • Unclear what you're asking. In what way does using a `ByteArrayOutputStream` constitute writing anything to a text file? Surely the answer is `FileOutputStream` or `FileWriter`. However if the process only understands a text file you can't call it 'piping'. – user207421 Jun 26 '15 at 13:14
  • The other process is launched from this Java program. – mrQWERTY Jun 26 '15 at 13:14
  • I suggest you start with something which works, and then find the best way to do it. If you want to write to a file, I suggest you just write the Strings to a file. – Peter Lawrey Jun 26 '15 at 13:15
  • Do you own the code of the process you're launching? Because there are some simple ways to pipe data to another process without a file, especially when you've launched it. – Andy Thomas Jun 26 '15 at 13:22
  • Yes, this program launches the trainer process. However, that process accepts a textfile. But since I need to to this many times, performance is important so I'm trying to avoid writing stuff like writing textfiles onto the disk and just giving the path to the process for it to open. – mrQWERTY Jun 26 '15 at 13:24
  • From the way you are launching your Java processes it looks as though you're using a *nix platform? If so and you don't care about multiplatform support you could try a Java library that wraps around Unix domain sockets. – D-Dᴙum Jun 26 '15 at 13:24
  • You're not making sense. If the program *only* accepts a text file, you have to provide a text file. If it *also* accepts piped input via stdin, there is no point in even mentioning that it also accepts text files. Please clarify your unintelligible question. – user207421 Jun 27 '15 at 00:58
  • @EJP Actually named pipes allows a program to accept data from pipes even though it only accepts a text file. – mrQWERTY Jun 27 '15 at 02:49

2 Answers2

1

The simplest way to write a collection String to a file is to use a PrintWriter

public static void writeToFile(String filename, Iterable<String> strings) {
    try (PrintWriter pw = new PrintWriter(filename)) {
       for(String str : strings)
            pw.println(str);
    }
}

If you need to write UTF-8 you can change the encoding with

try (PrintWriter pw = new PrintWriter(
                      new OutputStreamWriter(new FileOutputStream(filename), "UTF-8")) {
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • I'll accept this answer. Apologies for not being clear in my question. I have remembered something called "named pipes" which act as files on the filesystem. I think that is suitable to my application. – mrQWERTY Jun 26 '15 at 13:36
  • Yeah, then I think the solution might just be to create a Java wrapper around C code that creates those pipes. – mrQWERTY Jun 26 '15 at 13:43
  • @Renren29 You can create pipes in Java also, no need to use C code. – Peter Lawrey Jun 26 '15 at 14:27
  • The "built-in" Java pipes are for between threads in the same process, not between threads in different processes. – D-Dᴙum Jun 26 '15 at 14:30
  • @Renren29 a simple way to stay in memory is to write to a `tmpfs`. I have `/tmp` mounted as tmpfs. – Peter Lawrey Jun 26 '15 at 14:30
  • @Kerry which is why you need to create a named pipe instead e.g. run `mkfifo myPipe` – Peter Lawrey Jun 26 '15 at 14:31
1

You can easily pipe data to a process you've launched through its standard input stream. In the parent process, you can access the child's standard input stream through Process.getOutputStream().

This does require your child process to accept data through standard input rather than a file. Your child process currently gets its input from a file. Fortunately, you note in a comment that you own the code of the child process.

Andy Thomas
  • 84,978
  • 11
  • 107
  • 151