I am trying to run a sed command from java without success. Here is my java code:
String[] cmd = {"sed", "-i", "'"+lineIndex+"s/"+line+"/"+currentBid+"/g'", "/data/jsp/items.xml"};
Runtime.getRuntime().exec(cmd);
I also tried:
String[] cmd = {"/bin/sh","-c","sed", "-i", "'"+lineIndex+"s/"+line+"/"+currentBid+"/g'", "/data/jsp/items.xml"};
Runtime.getRuntime().exec(cmd);
Thing is, if I print out the contents of the cmd String and run it in a terminal it does work. It's just not executing it from java for some reason. Te make this more clear, when I run the command directly from a terminal the file "items.xml" changes. When I run it from java the file does not change. I've verified that the command is correct as sown below.
Am I missing something?
The output from cmd is sed -i '21s/2/102/g' /data/jsp/items.xml
** EDIT
I made the following changes based on comments below. No change in output however.
String[] cmd = {"/bin/sh","-c","sed", "-i", "'"+lineIndex+"s/"+line+"/"+currentBid+"/g'", "/data/jsp/items.xml"};
Process p = Runtime.getRuntime().exec(cmd);
p.waitFor();
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line2 = reader.readLine();
while (line2 != null) {
line2 = reader.readLine();
}
reader.close();
Try that :)
The advantage of this solution , it's more easier to debugging because you have the temporary file !
String lineIndex="21";
String line="2";
String currentBid="102";
File temp = File.createTempFile("temp-sh", ".sh");
FileWriter fw = new FileWriter(temp);
fw.write("#!/bin/bash\n");
fw.write("sed -i '"+lineIndex+"s/"+line+"/"+currentBid+"/g' data/jsp/items.xml\n");
fw.close();
System.out.println(". "+temp.getAbsolutePath());
Runtime.getRuntime().exec(". "+temp.getAbsolutePath());
You should probably use a ProcessBuilder instead of Runtime.exec, perhaps something like this -
try {
String replaceCommand ="'"+lineIndex+"s/"+line+"/"+currentBid+"/g'";
String [] cmd = new String[] {
"sed", "-i", replaceCommand, "/data/jsp/items.xml"
};
Process process = new ProcessBuilder(cmd)
.start();
InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String lineRead;
System.out.printf("Output of running %s is:",
Arrays.toString(cmd));
while ((lineRead = br.readLine()) != null) {
System.out.println(lineRead);
}
} catch (IOException e) {
e.printStackTrace();
}
You need to make sure the path to the file is correct, java may not have the same path to the file unless it is in the jar. You can do this by trying to open the file or checking if it exists before passing it to the command.
see: How to read file from relative path in Java project? java.io.File cannot find the path specified
Honestly there is no need to externally execute sed in this case. Read the file in Java and use Pattern. Then you have code that could run on any platform. Combine this with org.apache.commons.io.FileUtils and you can do it in a few lines of code.
final File = new File("/data/jsp/items.xml");
String contents = FileUtils.readFileToString(file, StandardCharsets.UTF_8.name());
contents = Pattern.compile(line).matcher(contents).replaceAll(currentBid);
FileUtils.write(file, contents);
Or, in a short, self-contained, correct example
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.regex.Pattern;
public final class SedUtil {
public static void main(String... args) throws Exception {
final File file = new File("items.xml");
final String line = "<bid>\\d+</bid>";
final String currentBid = "<bid>20</bid>";
final String data = "<bids><bid>10</bid></bids>";
FileUtils.write(file, data);
sed(file, Pattern.compile(line), currentBid);
System.out.println(data);
System.out.println(FileUtils.readFileToString(file, StandardCharsets.UTF_8));
}
public static void sed(File file, Pattern regex, String value) throws IOException {
String contents = FileUtils.readFileToString(file, StandardCharsets.UTF_8.name());
contents = regex.matcher(contents).replaceAll(value);
FileUtils.write(file, contents);
}
}
which gives output
<bids><bid>10</bid></bids>
<bids><bid>20</bid></bids>
Related
I have around 150 folder and inside each folder images are present , I am trying to copy the whole directory inside the other directory . For few directories it is working then after it stops automatically without throwing any error or exception . I am using FileUtils method to achieve this .
org.apache.commons.io.FileUtils.copyDirectoryToDirectory(originalImageFolder, new File(this.ctx.getRealPath(newFilePath)));
I provided an alternate solution without the need to use a third party, such as apache FileUtils. This can be done through the command line.
I tested this out on Windows and it works for me. A Linux solution follows.
Here I am utilizing Windows xcopy command to copy all files including subdirectories.
The parameters that I pass are defined as per below.
/e - Copies all subdirectories, even if they are empty.
/i - If Source is a directory or contains wildcards and Destination
does not exist, xcopy assumes Destination specifies a directory name
and creates a new directory. Then, xcopy copies all specified files
into the new directory.
/h - Copies files with hidden and system file attributes. By default,
xcopy does not copy hidden or system files
My example(s) utilizes the ProcessBuilder class to construct a process to execute the copy(xcopy & cp) commands.
Windows:
String src = "C:\\srcDir";
String dest = "C:\\destDir";
List<String> cmd = Arrays.asList("xcopy", src, dest, "/e", "/i", "/h");
try {
Process proc = new ProcessBuilder(cmd).start();
BufferedReader inp = new BufferedReader(new InputStreamReader(proc.getInputStream()));
String line = null;
while ((line = inp.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
Linux:
String src = "srcDir/";
String dest = "~/destDir/";
List<String> cmd = Arrays.asList("/bin/bash", "-c", "cp", "r", src, dest);
try {
Process proc = new ProcessBuilder(cmd).start();
BufferedReader inp = new BufferedReader(new InputStreamReader(proc.getInputStream()));
String line = null;
while ((line = inp.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
A combo that can work on both Windows or Linux environments.
private static final String OS = System.getProperty("os.name");
private static String src = null;
private static String dest = null;
private static List<String> cmd = null;
public static void main(String[] args) {
if (OS.toLowerCase().contains("windows")) { // setup WINDOWS environment
src = "C:\\srcDir";
dest = "C:\\destDir";
cmd = Arrays.asList("xcopy", src, dest, "/s", "/e", "/i", "/h");
System.out.println("on: " + OS);
} else if (OS.toLowerCase().contains("linux")){ // setup LINUX environment
src = "srcDir/";
dest = "~/destDir/";
cmd = Arrays.asList("/bin/bash", "-c", "cp", "r", src, dest);
System.out.println("on: " + OS);
}
try {
Process proc = new ProcessBuilder(cmd).start();
BufferedReader inp = new BufferedReader(new InputStreamReader(proc.getInputStream()));
String line = null;
while ((line = inp.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
I want to run a python script(tensorflow's Image label script) after RPi's camera module captures a photo using a jar file. I have tried both Runtime and ProcessBuilder, but it says no file or Directory found.
Here's my Code for the Runtime Code:
Process rt = Runtime.getRuntime().exec("python3 -m scripts.image-label.py");
rt.waitFor();
BufferedReader in = new BufferedReader(new InputStreamReader(rt.getInputStream()));
String read = in.readLine();
ML = read;
result resfin = new result();
resfin.setVisible(true);
And here's the code for my ProcessBuilder one:
ProcessBuilder builder = new ProcessBuilder("/home/pi/Desktop/ML/scripts/image-label.py");
Process np = builder.start();
np.waitFor();
BufferedReader in = new BufferedReader(new InputStreamReader(np.getInputStream()));
String read = in.readLine();
ML = read;
result resfin = new result();
resfin.setVisible(true);
Am i doing something wrong? Or am i missing something? Any help would be appreciated!
I have tried with the following code, it is working fine, though I have not tried with -m "module" flag, since I do not know how to create a module file in python.
Found some of the issues with code:
1. You need to pass python3 as an argument to process builder as shown below
2. Provide an absolute path for a python file.
3. You can use either of Runtime or ProcessBuilder without an issue.
// Process rt = Runtime.getRuntime().exec("python3 -m /Users/<user-name>/demo/JavaNotepad/src/main/java/com/mypython.py");
ProcessBuilder builder = new ProcessBuilder("python3", "-m", "/Users/<user-name>/demo/JavaNotepad/src/main/java/com/mypython.py");
Process rt = builder.start();
int exitCode = rt.waitFor();
System.out.println("Process exited with : " + exitCode);
BufferedReader in = new BufferedReader(new InputStreamReader(rt.getInputStream()));
BufferedReader err = new BufferedReader(new InputStreamReader(rt.getErrorStream()));
System.out.println("Python file output:");
String line;
BufferedReader reader;
if (exitCode != 0) {
reader = err;
} else {
reader = in;
}
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
I am trying to write a Java application that executes a python script in order to return a value to the original program. However, the script is written in Python3 so I can't use Jython.
My current program works fine in Intellij but when I export to a JAR file it no longer works (I'm assuming because the filepath is different). I know questions similar to this have been asked in the past but none of the solutions seem to be working.
String currentPath = new File("").getAbsolutePath();
String path = Paths.get(currentPath, "src", "com", "engine", "pythonScript.py").toUri().toString();
String[] cmd = new String[]{"python", path, data};
try {
Process p = Runtime.getRuntime().exec(cmd);
BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
String output;
while ((output = stdInput.readLine()) != null) {
System.out.println(output);
if (checkOutput(output)) {
return output;
}
}
BufferedReader error = new BufferedReader(new InputStreamReader(p.getErrorStream()));
String s;
while ((s=error.readLine()) != null) {
System.out.println(s);
}
} catch (IOException e) {
e.printStackTrace();
}
Using a Buffer reader I parse throughout a file. If Oranges: pattern is found, I want to replace it with ApplesAndOranges.
try (BufferedReader br = new BufferedReader(new FileReader(resourcesFilePath))) {
String line;
while ((line = br.readLine()) != null) {
if (line.startsWith("Oranges:")){
int startIndex = line.indexOf(":");
line = line.substring(startIndex + 2);
String updatedLine = "ApplesAndOranges";
updateLine(line, updatedLine);
I call a method updateLine and I pass my original line as well as the updated line value.
private static void updateLine(String toUpdate, String updated) throws IOException {
BufferedReader file = new BufferedReader(new FileReader(resourcesFilePath));
PrintWriter writer = new PrintWriter(new File(resourcesFilePath+".out"), "UTF-8");
String line;
while ((line = file.readLine()) != null)
{
line = line.replace(toUpdate, updated);
writer.println(line);
}
file.close();
if (writer.checkError())
throw new IOException("Can't Write To File"+ resourcesFilePath);
writer.close();
}
To get the file to update I have to save it with a different name (resourcesFilePath+".out"). If I use the original file name the saved version become blank.
So here is my question, how can I replace a line with any value in the original file without losing any data.
For this you need to use the regular expressions (RegExp) like this:
str = str.replaceAll("^Orange:(.*)", "OrangeAndApples:$1");
It's an example and maybe it's not excactly what you want, but here, in the first parameter, the expression in parentesis is called a capturing group. The expression found will be replaced by the second parameter and the $1 will be replaced by the value of the capturing group. In our example Orange:Hello at the beggining of a line will be replaced by OrangeAndApples:Hello.
In your code, it seams you create one file per line ... maybe inlining the sub-method would be better.
try (
BufferedReader br = new BufferedReader(new FileReader(resourcesFilePath));
BufferedWriter writer = Files.newBufferedWriter(outputFilePath, charset);
) {
String line;
while ((line = br.readLine()) != null) {
String repl = line.replaceAll("Orange:(.*)","OrangeAndApples:$1");
writer.writeln(repl);
}
}
The easiest way to write over everything in your original final would be to read in everything - changing whatever you want to change and closing the stream. Afterwards open up the file again, then overwrite the file and all its lines with the data you want.
You can use RandomAccessFile to write to the file, and nio.Files to read the bytes from it. In this case, I put it as a string.
You can also read the file with RandomAccessFile, but it is easier to do it this way, in my opinion.
import java.io.RandomAccessFile;
import java.io.File;
import java.io.IOException;
import java.nio.file.*;
public void replace(File file){
try {
RandomAccessFile raf = new RandomAccessFile(file, "rw");
Path p = Paths.get(file.toURI());
String line = new String(Files.readAllBytes(p));
if(line.startsWith("Oranges:")){
line.replaceAll("Oranges:", "ApplesandOranges:");
raf.writeUTF(line);
}
raf.close();
} catch (IOException e) {
e.printStackTrace();
}
}
I've a code which replaces 10:A to 12:A in a text file called sample.txt. Also, the code I've now is changing the file format, which shouldn't. Can someone please let me know how to do the same using regular expression in Java which doesn't change the file format? File has original format as below 10:A 14:Saxws But after executing the code it outputs as 10:A 14:Saxws.
import java.io.*;
import java.util.*;
public class FileReplace
{
List<String> lines = new ArrayList<String>();
String line = null;
public void doIt()
{
try
{
File f1 = new File("sample.txt");
FileReader fr = new FileReader(f1);
BufferedReader br = new BufferedReader(fr);
while ((line = br.readLine()) != null)
{
if (line.contains("10:A"))
line = line.replaceAll("10:A", "12:A") + System.lineSeparator();
lines.add(line);
}
fr.close();
br.close();
FileWriter fw = new FileWriter(f1);
BufferedWriter out = new BufferedWriter(fw);
for(String s : lines)
out.write(s);
out.flush();
out.close();
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
public static void main(String[] args)
{
FileReplace fr = new FileReplace();
fr.doIt();
}
}
It looks like your OS or editor is not able to print correctly line separators generated by System.lineSeparator(). In that case consider
reading content of entire file to string (including original line separators), - then replacing part which you are interested in
and writing replaced string back to your file
You can do it using this code:
Path file = Paths.get("sample.txt");
//read all bytes from file (they will include bytes representing used line separtors)
byte[] bytesFromFile = Files.readAllBytes(file);
//convert themm to string
String textFromFile = new String(bytesFromFile, StandardCharsets.UTF_8);//use proper charset
//replace what you need (line separators will stay the same)
textFromFile = textFromFile.replaceAll("10:A", "12:A");
//write back data to file
Files.write(file, textFromFile.getBytes(StandardCharsets.UTF_8), StandardOpenOption.CREATE);