I'm taking an input string as Java source code, editing it a little bit, and generate a .java file in Java.
Here is my code.
BufferedWriter writer = new BufferedWriter(new FileWriter("javacode.java"));
//msg = msg.substring(4); //ignore this
String newcontent = "import java.io.BufferedWriter;import java.io.ByteArrayOutputStream;import java.io.FileWriter;import java.io.PrintStream;";
char[] content = msg.toCharArray();
int j = msg.indexOf("String[] args") + 14;
boolean inMain = false;
for (int x=0;x<content.length;x++) {
if (x == j) {
inMain = true;
if (content[j] != '{') {
j += 1;
newcontent += String.valueOf(content[x]);
continue;
}
newcontent += String.valueOf(content[x]);
String prefix = "ByteArrayOutputStream consoleStorage = new ByteArrayOutputStream();PrintStream newConsole = System.out;System.setOut(new PrintStream(consoleStorage));";
newcontent += prefix;
}
else if (content[x] == '}' && inMain) {
String post = "String str = consoleStorage.toString();try {BufferedWriter writer = new BufferedWriter(new FileWriter(\"javaoutput.txt\"));writer.write(str);writer.close();} catch (Exception e) {}";
newcontent += post;
newcontent += String.valueOf(content[x]);
inMain = false;
}
else {
newcontent += String.valueOf(content[x]);
}
}
writer.write(newcontent);
writer.close();
It may look a little bit complicated, but generally speaking, I'm adding these three pieces of code into the main method of the source code input.
//At the beginning of the program, insert the following code
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.FileWriter;
import java.io.PrintStream;
...
...
...
//At the beginning of the main method, insert the following code
ByteArrayOutputStream consoleStorage = new ByteArrayOutputStream();
PrintStream newConsole = System.out;
System.setOut(new PrintStream(consoleStorage));
...
...
...
//At the end of the main method, insert the following code
String str = consoleStorage.toString();
try {
BufferedWriter writer = new BufferedWriter(new FileWriter("javaoutput.txt"));
writer.write(str);
writer.close();
} catch (Exception e) {}
However, when I test it out, with a simple Hello World example, I got this .java file.
Here is my source code input ("msg" variable, it is a simple String)
public class myClass {
public static void main(String[] args) {
System.out.println("Hello");
}
}
Here is what I got.
(I re-formatted this file for a better look)
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.FileWriter;
import java.io.PrintStream;
public class myClass {
ByteArrayOutputStream consoleStorage = new ByteArrayOutputStream();
PrintStream newConsole = System.out;
System.setOut(new PrintStream(consoleStorage));
public static void main(String[] args) {
System.out.println("Hello");
String str = consoleStorage.toString();
try {
BufferedWriter writer = new BufferedWriter(new FileWriter("javaoutput.txt"));
writer.write(str);
writer.close();
} catch (Exception e) {}
}
}
As you can see, Java fails to put "[" and "]" into the file and write "[]" instead, and thus (probably) "int j = msg.indexOf("String[] args") + 14;" fails to locate the main method.
I tried many methods to fix this, including replacing "[" by "\\[" etc, none of them works. To be honest, I'm not even sure whether "[]" generates the problem.
Update:
I tested all contents of "msg" and "content" variable/array in different phases, by inserting the following test prints into my program.
Note:
CQ.sendPrivateMsg(msgReceiver, message) is used to send the message to the receiver, this is working appropriately.
"msg" variable is passed from the chatting software, which I can only use its API to send/receive messages, while I don't have its source code...
This program is a part of an plugin of a chatting software.
...
...
...
BufferedWriter writer = new BufferedWriter(new FileWriter("javacode.java"));
msg = msg.substring(4);
//test print 1
CQ.sendPrivateMsg(fromQQ, CC.at(fromQQ) + "\n" + msg);
String newcontent = "import java.io.BufferedWriter;import java.io.ByteArrayOutputStream;import java.io.FileWriter;import java.io.PrintStream;";
char[] content = msg.toCharArray();
//test print 2
CQ.sendPrivateMsg(fromQQ, CC.at(fromQQ) + "\n" + content[55] + content[56] + content[57] + content[58]);
//test print 3
String tempstr = new String();
for (int i=0;i<content.length;i++) {
tempstr += String.valueOf(content[i]);
}
CQ.sendPrivateMsg(fromQQ, CC.at(fromQQ) + "\n" + tempstr);
int j = msg.indexOf("String[] args") + 14;
...
...
...
The actual result is shown below
//test print 1: msg
public class myClass {
public static void main(String[] args) {
System.out.println("Hello");
}
}
//test print 2: char array, accessed each digit one by one
[
//test print 3: char array, concatenate in a loop and print out as a whole
public class myClass {
public static void main(String[] args) {
System.out.println("Hello");
}
}
It seems like the problem is triggered by the case when I tried to access a single value within the char array, but it is fine when I use a for loop to print it all.
Update:
I solved it, by replacing [ and other strange code in char array by [ or ].
Advice given in comment is very helpful. Appreciate!
It seems like msg is received as an HTML-encoded string.
You may use Apache Commons StringEscapeUtils.unescapeHtml4() to decode this string.
Related
I have a Reader reading in a file to edit it and save it afterwards with a printwriter.
The start input is like this
The problem is, that sometimes whitespaces are mistaken for new lines somehow like here. I goes even further in cutting it again after the first time
like this
I have tried some different split characters, like (what it actually is (you can see in System.out.println)) but I can´t get it to work properly
The Original loaded Textfile is this and the output of the getText is this
if (lastClicked != 0) {
String path;
switch (lastClicked) {
case 1:
path = "data/alyxia_status.got";
break;
case 2:
path = "data/mog_status.got";
break;
case 3:
path = "data/telias_status.got";
break;
default:
path = "data/tiernen_status.got";
}
String text = textPane.getText();
String toWrite = text.substring(44, text.length() - 16);
System.out.println(toWrite);
String[] parts = toWrite.split("<br>");
FileWriter fileWriter;
try {
fileWriter = new FileWriter(path);
PrintWriter printWriter = new PrintWriter(fileWriter);
printWriter.print(parts[0]);
for (int i = 1; i<parts.length; i++) {
if (parts[i] != "" && parts[i] != " ") {
printWriter.println();
printWriter.print(parts[i]);
}
}
printWriter.close();
} catch (IOException e1) {
e1.printStackTrace();
System.err.println("Saving failed");
}
}//end if
It should just split on the string "<br>" and not on white spaces that are in between (in System.out.println it´s showing "Base" and then in a newline "Damage")
The following code runs fine for me, try to invoke the printToFile method and pass your String array to is as a parameter. By isolating the problematic code in a separate method it should be much easier to debug. I've also noticed you are comparing String objects with operators, this is not advised and doesn't do what you think it does. Read this answer for more information.
public static void printToFile(String path, String[] output) {
FileWriter fileWriter;
try {
fileWriter = new FileWriter(path);
PrintWriter printWriter = new PrintWriter(fileWriter);
printWriter.print(output[0]);
for (int i = 1; i < output.length; i++)
{
/* DO NOT compare string with opeators like "!=" or "==,
* instead use equals method to properly compare them
*/
if (!output[i].equals("") && !output[i].equals(" ")) {
printWriter.println();
printWriter.print(output[i]);
}
}
printWriter.close();
}
catch (java.io.IOException e1) {
e1.printStackTrace();
System.err.println("Saving failed");
}
}
public static void main(String[] args) throws IOException
{
Path path = Paths.get("sample.txt");
String[] text = new String[] { "these ", " lines ", "should", " be ", " in new ", "line" };
printToFile(path.toString(), text);
Files.readAllLines(path).forEach(System.out::println);
}
Output
these
lines
should
be
in new
line
Edit: What #DodgyCodeException mentioned in the comments could be the actual cause of your problem. For visibility sake I will just paste the comment:
The first 44 characters of the text are discarded because of your text.substring(44, text.length() - 16);. This includes everything up to "-- Base" (just before "Damage").
Complete solution
I've written a full solution to your problem in the following code. Try the code and see if it works for you then read the explanation posted underneath the code:
public class Main {
/**
* Use {#link StringBuilder} to build a single {#code String}
* from the read contents of file located under given path.
*
* #param path {#code Path} of the file to read
* #throws IOException if an I/O error occurs reading from the file
* or a malformed or unmappable byte sequence is read.
*/
private static String getInputFileContent(Path path) throws IOException {
StringBuilder sb = new StringBuilder();
Files.readAllLines(path).forEach(sb::append);
return sb.toString();
}
/**
* #return the matched content contained in <body> tag within
* the provided text or {#code null} if there was no match.
*/
private static #Nullable String getHTMLBodyFromText(String text) {
Pattern pattern = Pattern.compile("(?:\\s*?<body>)(?:\\s*)((.*\\s)*)</body>");
Matcher matcher = pattern.matcher(text);
return matcher.find() ? matcher.group(1) : null;
}
public static void printToFile(Path path, String output) {
String toWrite = getHTMLBodyFromText(output);
if (toWrite == null) {
System.err.println("Unable to find body");
return;
}
String[] parts = toWrite.split("<br>");
FileWriter fileWriter;
try {
fileWriter = new FileWriter(path.toString());
PrintWriter printWriter = new PrintWriter(fileWriter);
printWriter.print(parts[0]);
for (int i = 1; i < parts.length; i++)
{
/* DO NOT compare string with opeators like "!=" or "==,
* instead use equals method to properly compare them
*/
if (!parts[i].equals("") && !parts[i].equals(" ")) {
printWriter.println(parts[i]);
printWriter.print(parts[i]);
}
}
printWriter.close();
}
catch (java.io.IOException e1) {
e1.printStackTrace();
System.err.println("Saving failed");
}
}
public static void main(String[] args) throws IOException
{
Path inputPath = Paths.get("input.txt");
Path outputPath = Paths.get("output.txt");
printToFile(outputPath, getInputFileContent(inputPath));
}
}
I've used Regex to find the text contained within the <body> tag of the input file you provided (the actual content we want is located in group 1) which was the part that was causing this problem. If you are further interested to see how the pattern included in this code works see this demo.
The rest of your code works fine so all you have to do is call the printToFile method and pass the return value of textPane.getText() as output String argument and it will process and print the required result for you to the text file located under a path of your choosing.
I wrote a program that generates random numbers into two text files and random letters into a third according the two constant files. Now I need to read from each text file, line by line, and put them together. The program is that the suggestion found here doesn't really help my situation. When I try that approach it just reads all lines until it's done without allowing me the option to pause it, go to a different file, etc.
Ideally I would like to find some way to read just the next line, and then later go to the line after that. Like maybe some kind of variable to hold my place in reading or something.
public static void mergeProductCodesToFile(String prefixFile,
String inlineFile,
String suffixFile,
String productFile) throws IOException
{
try (BufferedReader br = new BufferedReader(new FileReader(prefixFile)))
{
String line;
while ((line = br.readLine()) != null)
{
try (PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(productFile, true))))
{
out.print(line); //This will print the next digit to the right
}
catch (FileNotFoundException e)
{
System.err.println("File error: " + e.getMessage());
}
}
}
}
EDIT: The digits being created according to the following. Basically, constants tell it how many digits to create in each line and how many lines to create. Now I need to combine these together without deleting anything from either text file.
public static void writeRandomCodesToFile(String codeFile,
char fromChar, char toChar,
int numberOfCharactersPerCode,
int numberOfCodesToGenerate) throws IOException
{
for (int i = 1; i <= PRODUCT_COUNT; i++)
{
int I = 0;
if (codeFile == "inline.txt")
{
for (I = 1; I <= CHARACTERS_PER_CODE; I++)
{
int digit = (int)(Math.random() * 10);
try (PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(codeFile, true))))
{
out.print(digit); //This will print the next digit to the right
}
catch (FileNotFoundException e)
{
System.err.println("File error: " + e.getMessage());
System.exit(1);
}
}
}
if ((codeFile == "prefix.txt") || (codeFile == "suffix.txt"))
{
for (I = 1; I <= CHARACTERS_PER_CODE; I++)
{
Random r = new Random();
char digit = (char)(r.nextInt(26) + 'a');
digit = Character.toUpperCase(digit);
try (PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(codeFile, true))))
{
out.print(digit);
}
catch (FileNotFoundException e)
{
System.err.println("File error: " + e.getMessage());
System.exit(1);
}
}
}
//This will take the text file to the next line
if (I >= CHARACTERS_PER_CODE)
{
{
Random r = new Random();
char digit = (char)(r.nextInt(26) + 'a');
try (PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(codeFile, true))))
{
out.println(""); //This will return a new line for the next loop
}
catch (FileNotFoundException e)
{
System.err.println("File error: " + e.getMessage());
System.exit(1);
}
}
}
}
System.out.println(codeFile + " was successfully created.");
}// end writeRandomCodesToFile()
Being respectfull with your code, it will be something like this:
public static void mergeProductCodesToFile(String prefixFile, String inlineFile, String suffixFile, String productFile) throws IOException {
try (BufferedReader prefixReader = new BufferedReader(new FileReader(prefixFile));
BufferedReader inlineReader = new BufferedReader(new FileReader(inlineFile));
BufferedReader suffixReader = new BufferedReader(new FileReader(suffixFile))) {
StringBuilder line = new StringBuilder();
String prefix, inline, suffix;
while ((prefix = prefixReader.readLine()) != null) {
//assuming that nothing fails and the files are equals in # of lines.
inline = inlineReader.readLine();
suffix = suffixReader.readLine();
line.append(prefix).append(inline).append(suffix).append("\r\n");
// write it
...
}
} finally {/*close writers*/}
}
Some exceptions may be thrown.
I hope you don't implement it in one single method.
You can make use of iterators too, or a very simple reader class (method).
I wouldn't use List to load the data at least I guarantee that the files will be low sized and that I can spare the memory usage.
My approach as we discussed by storing the data and interleaving it. Like Sergio said in his answer, make sure memory isn't a problem in terms of the size of the file and how much memory the data structures will use.
//the main method we're working on
public static void mergeProductCodesToFile(String prefixFile,
String inlineFile,
String suffixFile,
String productFile) throws IOException
{
try {
List<String> prefix = read(prefixFile);
List<String> inline = read(inlineFile);
List<String> suffix = read(productFile);
String fileText = interleave(prefix, inline, suffix);
//write the single string to file however you want
} catch (...) {...}//do your error handling...
}
//helper methods and some static variables
private static Scanner reader;//I just prefer scanner. Use whatever you want.
private static StringBuilder sb;
private static List<String> read(String filename) throws IOException
{
List<String> list = new ArrayList<String>;
try (reader = new Scanner(new File(filename)))
{
while(reader.hasNext())
{ list.add(reader.nextLine()); }
} catch (...) {...}//catch errors...
}
//I'm going to build the whole file in one string, but you could also have this method return one line at a time (something like an iterator) and output it to the file to avoid creating the massive string
private static String interleave(List<String> one, List<String> two, List<String> three)
{
sb = new StringBuilder();
for (int i = 0; i < one.size(); i++)//notice no checking on size equality of words or the lists. you might want this
{
sb.append(one.get(i)).append(two.get(i)).append(three.get(i)).append("\n");
}
return sb.toString()
}
Obviously there is still some to be desired in terms of memory and performance; additionally there are ways to make this slightly more extensible to other situations, but it's a good starting point. With c#, I could more easily make use of the iterator to make interleave give you one line at a time, potentially saving memory. Just a different idea!
I have a method Report Dose stat in Java:
public String getReportDoseStat(){
double maxdose=getMaxDose();
String s=("Average dose:\t"+getAvDose()+"\n");
s+=("Max dose:\t"+maxdose+"\n");
s+=("Pixels 90% of max dose or more:\t"+getNmbrPixDose(maxdose*0.9)+"/"+getNmbrPixDose(0.0)+"\n");
s+=("Pixels 50% of max dose or more:\t"+getNmbrPixDose(maxdose*0.5)+"/"+getNmbrPixDose(0.0)+"\n");
s+=("Pixels 10% of max dose or more:\t"+getNmbrPixDose(maxdose*0.1)+"/"+getNmbrPixDose(0.0)+"\n");
return s;
}
I would like to write the values generated from the this code to a table written in the method:
public void writeDosesTable(String p)// writing the dose table
{
{
PrintStream fos;
try{
fos=new PrintStream(new File(p));
String s;
for(int j=0;j<nz;j++){
s="";
for(int i=0;i<nx;i++){
s+=det_els.get(j+i*nz).getDose()+";";// comma separated or Semicolon separated mentioned here
}
fos.println(s);
// prints out the stream of values in Doses table separated by Semicolon
}
fos.flush();
fos.close();
}
catch (IOException e){
e.printStackTrace();
}
//finally
//{fos.close();}
}
}
How could I possibly generate such a thing?
Instead of having getDoseTable() method you can directly print the values in a file and while writing itself format your statements with the desired seperator. Something like below:
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
public class Test {
public static void main(String[] args) throws IOException {
String[] str = { "a", "b", "c" };
BufferedWriter wr = new BufferedWriter(new FileWriter(new File(
System.getProperty("user.dir") + File.separator + "test.csv")));
for (String string : str) {
wr.write(string + ",");
}
wr.flush();
wr.close();
}
}
Here String [] str , can be the string which you wish to write in a csv file delimited with certain delimiter and then while writing take care of where you are inserting the delimiter. Let me know if you need further assistance.
I want make a game of life clone using text files to specify my starting board, then write the finished board to a new text file in a similar format. E.g. load this:
Board in:
wbbbw
bbbbb
wwwww
wbwbw
bwbwb
from a file, then output something like this:
Board out:
wbbbw
bbbbb
wwwww
wwwww
bwbwb
I do this by making a 2D array (char[][] board) of characters, reading the file line by line into a string, and using String.charAt() to access each character and store it in the array.
Afterward, I convert each element of board (i.e., board[0], board[1], etc.), back to a string using String.valueOf(), and write that to a new line in the second file.
Please tell me I'm an idiot for doing this and that there is a better way to go through the file -> string -> array -> string -> file process.
You can use String.toCharArray() for each line while reading the file.
char[][] board = new char[5][];
int i = 0;
while((line = buffRdr.readLine()) != null) {
board[i++] = line.toCharArray();
}
And while writing either String.valueOf() or java.util.Arrays.toString().
for(int i=0; i<board.length; i++) {
//write Arrays.toString(board[i]);
}
// Remember to handle whitespace chars in array
char[] row = "wbbbw bbbbb wwwww wbwbw bwbwb".toCharArray()
Everything else seems good.
Why not use an already existing text format such as JSON instead of inventing your own?
There are tons of JSON parsers out there that can read and write two dimensional arrays.
You get both the benefit of easy reading directly from the file(as with your original method) and the benefit of not having to parse an annoying string format.
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
public class GameOfLife
{
private String mFilename;
private ArrayList<String> mLines;
public GameOfLife(String filename)
{
mFilename = filename;
read();
}
public char get(int x, int y)
{
String line = mLines.get(y);
return line.charAt(x);
}
public void set(char c, int x, int y)
{
String line = mLines.get(y);
String replacement = line.substring(0, x) + c + line.substring(x + 1, line.length());
mLines.set(y, replacement);
}
private void read()
{
mLines = new ArrayList<String>();
try
{
BufferedReader in = new BufferedReader(new FileReader(mFilename));
String line = in.readLine();
while (line != null)
{
mLines.add(line);
line = in.readLine();
}
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
}
private void write()
{
try
{
BufferedWriter out = new BufferedWriter(new FileWriter(mFilename));
for (String line : mLines)
{
out.write(line + "\n");
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
I am not an experienced Java programmer and i'm trying to write some text to a file and then read it with Scanner. I know there are lots of ways of doing this, but i want to write records to file with delimiters, then read the pieces.
The problem is so small. When I look the output some printing isn't seen(shown in below). I mean the bold line in the Output that is only written "Scanner". I would be appreciated if anyone can answer why "String: " isn't seen there. (Please answer just what i ask)
I couldn't understand if it is a simple printing problem or a line end problem with "\r\n".
Here is the code:
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Scanner;
public class Tmp {
public static void main(String args[]) throws IOException {
int i;
boolean b;
String str;
FileWriter fout = new FileWriter("test.txt");
fout.write("Testing|10|true|two|false\r\n");
fout.write("Scanner|12|one|true|");
fout.close();
FileReader fin = new FileReader("Test.txt");
Scanner src = new Scanner(fin).useDelimiter("[|\\*]");
while (src.hasNext()) {
if (src.hasNextInt()) {
i = src.nextInt();
System.out.println("int: " + i);
} else if (src.hasNextBoolean()) {
b = src.nextBoolean();
System.out.println("boolean: " + b);
} else {
str = src.next();
System.out.println("String: " + str);
}
}
fin.close();
}
}
Here is the output:
String: Testing
int: 10
boolean: true
String: two
String: false
Scanner
int: 12
String: one
boolean: true
You're not setting your delimiter right; [|\\*] is a character class consisting of 2 characters, |, *.
String s = "hello|world*foo*bar\r\nEUREKA!";
System.out.println(s);
// prints:
// hello|world*foo*bar
// EUREKA!
Scanner sc;
sc = new Scanner(s).useDelimiter("[|\\*]");
while (sc.hasNext()) {
System.out.print("[" + sc.next() + "]");
}
// prints:
// [hello][world][foo][bar
// EUREKA!]
System.out.println();
sc = new Scanner(s).useDelimiter("\r?\n|\r|\\|");
while (sc.hasNext()) {
System.out.print("[" + sc.next() + "]");
}
// prints:
// [hello][world*foo*bar][EUREKA!]
You seemed to have found that "[|\\n]" "works", but this actually leaves a trailing \r at the end of some tokens.
Coincidentally, you should look up PrintWriter; it has println methods that uses the system property line.separator. It's basically what System.out is-a.
PrintWriter fout = new PrintWriter(new File("test.txt"));
fout.println("Testing|10|true|two|false");
The problem is that you are writing out the String "String: " and then writing out control character \r, or carriage return, and then writing out the contents.
The following version should work a bit better for you:
FileWriter fout = new FileWriter("test.txt");
fout.write("Testing|10|true|two|false\n");
fout.write("Scanner|12|one|true|");
fout.close();
FileReader fin = new FileReader("test.txt");
Scanner src = new Scanner(fin).useDelimiter("[|\n]");
To really see what I am talking about with the \r, you should change your original program so the print code looks like this:
} else {
str = src.next().trim();
str = str.replace('\n', '_');
str = str.replace('\r', '_');
System.out.println("String: " + str);
}
You should see the output:
String: false__Scanner