Currently I am trying something very simple. I am looking through an XML document for a certain phrase upon which I try to replace it. The problem I am having is that when I read the lines I store each line into a StringBuffer. When I write the it to a document everything is written on a single line.
Here my code:
File xmlFile = new File("abc.xml")
BufferedReader br = new BufferedReader(new FileReade(xmlFile));
String line = null;
while((line = br.readLine())!= null)
{
if(line.indexOf("abc") != -1)
{
line = line.replaceAll("abc","xyz");
}
sb.append(line);
}
br.close();
BufferedWriter bw = new BufferedWriter(new FileWriter(xmlFile));
bw.write(sb.toString());
bw.close();
I am assuming I need a new line character when I prefer sb.append but unfortunately I don't know which character to use as "\n" does not work.
Thanks in advance!
P.S. I figured there must be a way to use Xalan to format the XML file after I write to it or something. Not sure how to do that though.
The readline reads everything between the newline characters so when you write back out, obviously the newline characters are missing. These characters depend on the OS: windows uses two characters to do a newline, unix uses one for example. To be OS agnostic, retrieve the system property "line.separator":
String newline = System.getProperty("line.separator");
and append it to your stringbuffer:
sb.append(line).append(newline);
Modified as suggested by Brel, your text-substituting approach should work, and it will work well enough for simple applications.
If things start to get a little hairier, and you end up wanting to select elements based on their position in the XML structure, and if you need to be sure to change element text but not tag text (think <abc>abc</abc>), then you'll want to call in in the cavalry and process the XML with an XML parser.
Essentially you read in a Document using a DocuemntBuilder, you hop around the document's nodes doing whatever you need to, and then ask the Document to write itself back to file. Or do you ask the parser? Anyway, most XML parsers have a handful of options that let you format the XML output: You can specify indentation (or not) and maybe newlines for every opening tag, that kinda thing, to make your XML look pretty.
Sb would be the StringBuffer object, which has not been instantiated in this example. This can added before the while loop:
StringBuffer sb = new StringBuffer();
Scanner scan = new Scanner(System.in);
String filePath = scan.next();
String oldString = "old_string";
String newString = "new_string";
String oldContent = "";
BufferedReader br = null;
FileWriter writer = null;
File xmlFile = new File(filePath);
try {
br = new BufferedReader(new FileReader(xmlFile));
String line = br.readLine();
while (line != null) {
oldContent = oldContent + line + System.lineSeparator();
line = br.readLine();
}
String newContent = oldContent.replaceAll(oldString, newString);
writer = new FileWriter(xmlFile);
writer.write(newContent);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
scan.close();
br.close();
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Related
First off I am new at coding in java. I have done extensive research prior to posting this question but have not found the exact answer to my question. I am sure it is my lack of experience, but any assistance the community can provide would be much appreciated.
I am trying to debug a utility class that I have coded. The code is working except for the bit about adding a new line to the substituted text.
Here is the piece of code that is generating an error in NetBeans IDE. The error is incompatible types: Boolean can't be converted to int
try (BufferedWriter bw = new BufferedWriter(new FileWriter (NewCSVFile),true))
What I am trying to do is get this code to read a CSV text file, substitute and the write the new csv data to a new file but preserve the original new lines in the file. And, I want to ensure that the method used is platform independent thus why I am using BufferedWriter.
Here is all the code for your review.
public class TxtFileConverter {
public static void main (String[] args) {
// Location of the file you want to work with.
File CSVFile = new File("/Users/data.csv");
File NewCSVFile = new File("/Users/NewData.csv");
String search = "[,](?!\\w)";
String replace = ",0";
try{
FileReader fr = new FileReader(CSVFile);
String s;
String totalStr = "";
try (BufferedReader br = new BufferedReader(fr)) {
while ((s = br.readLine()) != null) {
totalStr += s;
}
totalStr = totalStr.replaceAll(search, replace);
try (BufferedWriter bw = new BufferedWriter(new FileWriter
(NewCSVFile),true)) {
bw.write(totalStr);
bw.newLine();
}
}
}catch(IOException e){
}
}
}
I think you are trying to read some lines from a file and write it to another file. In the output file, you get all the code in a single line.
I think the bug is in this piece of code.
while ((s = br.readLine()) != null) {
totalStr += s;
}
If you add a statement to add a new line character after reading a line from input file, you should get the desired output.
while ((s = br.readLine()) != null) {
totalStr += s;
totalStr += "\n";
}
The following code adds a newline character at the end of the file.
bw.newLine();
What do you think that true argument is doing in the BufferedWriter constructor? The second and optional argument is the buffer size, an integer. You probably don't even need to supply that argument unless you're doing something rather odd.
try (BufferedWriter bw = new BufferedWriter(new FileWriter(NewCSVFile)))
BufferedWriter has only two constructors:
public BufferedWriter(Writer out) //sz = defaultCharBufferSize = 8192
public BufferedWriter(Writer out, int sz) //sz Output-buffer size, a positive integer
There is no option with second boolean argument. I recommend to use first constructor in your case.
I am trying to split a combined text file. The combined text file has multiple xml files inside. I want to split on <?xml version='1.0'?> which is the start of every new xml inside the combined text file. Not sure what is the best way to do this. Currently this is what I have which does not split correctly.
Updated Code Working (fixed quotation in quotes problem added Pattern.quote):
Scanner scanner = new Scanner( new File("src/main/resources/Flume_Sample"), "UTF-8" );
String combinedText = scanner.useDelimiter("\\A").next();
scanner.close(); // Put this call in a finally block
String delimiter = "<?xml version=\"1.0\"?>";
String[] xmlFiles = combinedText.split("(?="+Pattern.quote(delimiter)+")");
for (int i = 0; i < xmlFiles.length; i++){
File file = new File("src/main/resources/output_"+i);
FileWriter writer = new FileWriter(file);
writer.write(xmlFiles[i]);
System.out.println(xmlFiles[i]);
writer.close();
}
The split method takes a regular expression string, so you may want to escape your delimiter String to a valid regex :
String[] xmlFiles = combinedText.split(Pattern.quote(delimiter));
See the Pattern.quote method .
Be also aware that you will load the entire initial file in memory if you proceed this way.
A streamed approach would perform better if the input file is large...
I would use something like this if you want to parse the data manually.
public static void parseFile(File file) throws AttributeException, LineException{
BufferedReader br = null;
String s = "";
int counter = 0;
if(file != null){
try{
br = new BufferedReader(new FileReader(file));
while((s = br.readLine()) != null){
if(s.contains("<?xml version='1.0'?>")){
//Write in new file with Stringbuffer and Filewritter.
}
}
br.close();
}catch (IOException e){
System.out.println(e);
}
}
}
I have a text file with some text in it and i'm planning on replacing certain characters in the text file. So for this i have to read the file using a buffered reader which wraps a file reader.
File file = new File("new.txt");
BufferedReader br = new BufferedReader(new FileReader(file));
String line = null;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
But since i have to edit characters i have to introduce a file writer and add the code which has a string method called replace all. so the overall code will look as given below.
File file = new File("new.txt");
FileWriter fw = new FileWriter(file);
BufferedReader br = new BufferedReader(new FileReader(file));
String line = null;
while ((line = br.readLine()) != null) {
System.out.println(line);
fw.write(br.readLine().replaceAll("t", "1") + "\n");
}
Problem is when i introduce a file writer to the code (By just having the initialization part and when i run the program it deletes the content in the file regardless of adding the following line)
fw.write(br.readLine().replaceAll("t", "1") + "\n");
Why is this occurring? am i following the correct approach to edit characters in a text file?
Or is there any other way of doing this?
Thank you.
public FileWriter(String fileName,
boolean append)
Parameters:
fileName - String The system-dependent filename.
append - boolean if true, then data will be written to the end of the
file rather than the beginning.
To append data use
new FileWriter(file, true);
The problem is that you're trying to write to the file while you're reading from it. A better solution would be to create a second file, put the transformed data into it, then replace the first file with it when you're done. Or if you don't want to do that, read all of the data out of the file first, then open it for writing and write the transformed data.
Also, have you considered using a text-processing language solution such as awk, sed or perl: https://unix.stackexchange.com/questions/112023/how-can-i-replace-a-string-in-a-files
You need to read the file first, and then, only after you read the entire file, you can write to it.
Or you open a different file for writing and then afterwards you replace the old file with the new one.
The reason is that once you start writing to a file, it is truncated (the data that was in the file is deleted).
The only way to avoid that is to open the file in "append" mode. With that mode, you start writing at the end of the file, so you don't delete its content. However, you won't be able to modify the existing content, you will only add content.
Maybe like this
public static void main(String[] args) throws IOException {
try {
File file = new File("/Users/alexanderkrum/IdeaProjects/printerTest/src/atmDep.txt");
Scanner myReader = new Scanner(file);
ArrayList<Integer> numbers = new ArrayList<>();
while (myReader.hasNextLine()) {
numbers.add(myReader.nextInt() + 1);
}
myReader.close();
FileWriter myWriter = new FileWriter(file);
for (Integer number :
numbers) {
myWriter.write(number.toString() + '\n');
}
myWriter.close();
} catch (FileNotFoundException e) {
System.out.println("An error occurred.");
e.printStackTrace();
}
}
Just add at last :
fw.close();
this will close it ,then it will not delete anything in the file.
:)
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'm trying to read a simple text file that contains the following:
LOAD
Bill's Beans
1200
20
15
30
QUIT
I need to store and print the contents line by line. I am doing so using the following code:
String inputFile = "(file path here)";
try {
Scanner input = new Scanner(inputFile);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
String currentLine = "";
while (!currentLine.equals("QUIT}")){
currentLine = input.nextLine();
System.out.println(currentLine);
}
input.close();
However, the output is very "messy". I am trying to avoid storing all new line characters and anything else that doesn't appear in the text file. Output is:
{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf540
{\fonttbl\f0\fmodern\fcharset0 Courier;}
{\colortbl;\red255\green255\blue255;}
\margl1440\margr1440\vieww9000\viewh8400\viewkind0
\deftab720
\pard\pardeftab720\ql\qnatural
\f0\fs26 \cf0 LOAD\
Bill's Beans\
1200\
20\
15\
30\
QUIT}
Any help would be greatly appreciated, thank you!
This looks like you're reading a RTF file, isn't that so, by any chance?
Otherwise, I found reading text files is most natural for me using this construct:
BufferedReader reader = new BufferedReader(
new FileReader(new File("yourfile.txt")
);
String text = null;
// repeat until all lines is read
while ((text = reader.readLine()) != null) {
// do whatever with the text line
}
Because this is an RTF file, look into this for example: RTFEditorKit
If you insist on writing your own RTF reader, the correct approach would be for you to extend FilterInputStream and handle the RTF metadata in its implementation.
Just add following code into your class, then call it with path parameter. it returns all lines as List object
public List<String> readStudentsNoFromText(String path) throws IOException {
List<String> result = new ArrayList<String>();
// Open the file that is the first
// command line parameter
FileInputStream fstream = new FileInputStream(new File(path));
// Get the object of DataInputStream
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String strLine;
//Read File Line By Line
while ((strLine = br.readLine()) != null) {
// Print the content on the console
System.out.println(strLine);
result.add(strLine.trim());
}
//Close the input stream
in.close();
return result;
}