3

I am trying to use the cat command from within a java program to merge two files into one. The line of code which contains the cat command takes two files file1 and file2 and writes to a third file called combinedfile. However, what I observe is the instead of creating this file (combinedfile) and writing to it, my program merely displays the output on the terminal.

How can I make sure that indeed the two files are copied to a third file.

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class ExecuteShellCommand 
{

    public static void main(String[] args) 
    {

        ExecuteShellCommand obj = new ExecuteShellCommand();

        String command = "cat file1 file2 > combinedfile";

        String output = obj.executeCommand(command);

        System.out.println(output);

    }

    private String executeCommand(String command) 
    {

        StringBuffer output = new StringBuffer();

        Process p;
        try 
        {
            p = Runtime.getRuntime().exec(command);
            p.waitFor();
            BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));

            String line = "";           

            while ((line = reader.readLine())!= null) 
            {
                output.append(line + "\n");
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        return output.toString();

    }

}

EDIT:

I tried out with the ProcessBuilder as suggested, but I get this error. Code

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.*;
import java.util.*;

public class ExecuteShellCommand
{
    public static void main(String[] args) 
    {
        try
        {            
            ProcessBuilder builder = new ProcessBuilder("cat", "/home/PepperBoy/Desktop/file1.txt","/home/PepperBoy/Desktop/file2.txt");
            File combinedFile = new File("/home/PepperBoy/Desktop/file3.txt");
            builder.redirectOutput(combinedFile);
            builder.redirectError(combinedFile);
            Process p = builder.start();
        } 
        catch(IOException e)
        {
                e.printStackTrace();
        }

    }
}

Error

ExecuteShellCommand.java:14: cannot find symbol
symbol  : method redirectOutput(java.io.File)
location: class java.lang.ProcessBuilder
            builder.redirectOutput(combinedFile);
tubby
  • 2,074
  • 3
  • 33
  • 55

1 Answers1

0

I found a related question. To summarize the useful things from a couple answers found there, file redirection requires a shell, but exec doesn't have a shell context. Luckily, you can execute processes with redirection using ProcessBuilder. For your case, that would look something like:

public static void main(String[] args) 
{

    try{            
        ProcessBuilder builder = new ProcessBuilder("cat", "file1","file2");
        File combinedFile = new File("combinedFile");
        builder.redirectOutput(combinedFile);
        builder.redirectError(combinedFile);
        Process p = builder.start();
    } catch(IOException e){
        //handle exception...
    }

}

Note: You may receive an error when calling redirectError or redirectOutput stating that the symbol cannot be found. This will occur if you are compiling against a version of Java before 1.7, since 1.7 is when these methods were introduced. If it is possible to upgrade your Java, doing so will eliminate this error.

If it is not possible to upgrade Java, the following code will work:

public static void main(String[] args) 
{

    try{            
        ProcessBuilder builder = new ProcessBuilder("cat", "file1","file2");
        File combinedFile = new File("combinedFile");
        Process p = builder.start();

        InputStream isFromCat = p.getInputStream();
        OutputStream osCombinedFile = new FileOutputStream(combinedFile);

        byte[] buffer = new byte[1024];
        int read = 0;
        while((read = isFromCat.read(buffer)) != -1) {
            osCombinedFile.write(buffer, 0, read);
        }

    } catch(IOException e){
        //handle exception...
    }

}

It is also probably worthwhile to note that making a system call to cat is not the optimal way to combine files from Java. I have been assuming this is a toy case to represent a more complex use case for you. If all you really want to do is combine two files, you should write your code to avoid system calls and just append the files by reading both in as input streams and then writing them out to the result file. If you're having trouble figuring that out, those details definitely belong in another question.

Community
  • 1
  • 1
augray
  • 3,043
  • 1
  • 17
  • 30
  • @PepperBoy Okay, I adjusted my answer as well. What version of Java are you compiling against? – augray Jun 04 '15 at 03:00