This my output file. I'used standart "System.out.print()" for writing operation. There is a tab space between each value. But due to difference of word size, format looks bad. How can I fix the format of output?
This should print an element of your String by column every two tabs. If you need more tabs because the names are too long, you can increase the number of tabs in //here rememberingh that every tab have a length of 8 characters.
try{
FileOutputStream file = new FileOutputStream("filename.txt", true);
PrintStream out = new PrintStream(file);
String s=line;
String[] items = s.split("\t");
for(String item : items){
if(item.length()<8){ //here
out.print(item + "\t\t" ); //here
}else{
if(item.length()>16){ //here
out.print(item + "\t" );
}
}
}catch (IOException e){
System.out.println("Error: " + e);
System.exit(1);
}
}
You can write to a .csv file which can be opened in Excel and will give you data divided by column.
Use System.out.format, you can specify width to make things consistent.
Check out the Oracle Tutorial explanation.
Related
I am having a List of DTO which is mapped from a HTTP response(using RestTemplate call) having two value id and content. When I am iterating over list of DTO's, I am escaping HTML characters in content and replacing some unwated characters using the code below:
String content = null;
for(TestDto testDto: testDtoList) {
try {
content = StringEscapeUtils.unescapeHtml4(testDto.getContent()).
replaceAll("<style(.+?)</style>", "").
replaceAll("<script(.+?)</script>", "").
replaceAll("(?s)<[^>]*>(\\s*<[^>]*>)*", " ").
replaceAll("[^a-zA-Z0-9\\\\.]+", " ").
replace("\\n", " ").
replaceAll("\\\\r","").trim();
processContent(content);
} catch (Exception e) {
System.out.println("Content err: " + e.getMessage());
}
}
In between the loop, code get halted due to java constant string too long exception. Even I am not able to catch this exception.
How should I handle this problem?
EDIT :
The length of getContent() String can exceeds Integer.MAX_VALUE
That code is hard to read anyways so you might want to refactor it. One thing you could try is to use a StringBuffer along with Pattern, Matcher and the appendReplacement() and appendTail() methods. That way you could prove a list of patterns and replacements, iterate over it, iterate over all occurences of the current pattern and replace it. Unfortunately those methods don't accept StringBuilder but it might at least be worth a try. In fact, the replaceAll() method basically does the same but by doing it yourself you could skip the return sb.toString(); part which probably causes the problem.
Example:
class ReplacementInfo {
String pattern;
String replacement;
}
List<ReplacementInfo> list = ...; //build it
StringBuffer input = new StringBuffer( testDto.getContent() );
StringBuffer output = new StringBuffer( );
for( ReplacementInfo replacementInfo : list ) {
//create the pattern and matcher for the current input
Pattern pattern = Pattern.compile( replacementInfo.pattern );
Matcher matcher = pattern.matcher( input );
//replace all occurences of the pattern
while( matcher.find() ) {
matcher.appendReplacement( output, replacementInfo.replacement );
}
//add the rest of the input
matcher.appendTail( output );
//reuse the output as the input for the next iteration
input = output;
output = new StringBuffer();
}
At the end input would contain the result unless you handle reusing the intermediate steps differently, e.g. by clearing the buffers and adding output to input thus keeping output until the next iteration.
Btw, you might also want to look into using StringEscapeUtils.UNESCAPE_HTML4.translate(input, writer) along with a StringWriter that allows you to access the underlying StringBuffer and thus completely operate on the content without using String.
Supposing your DTO isn't big enough, you could:
store the response in a temporary file,
add a catch clause with the specific exception that is thrown during the runtime, and inside the clause the handling code for it.
That way you can parse the strings and when the exception hits, you could handle the long string by splitting it in parts and cleaning it.
Change your catch block like below,
String content = null;
for(TestDto testDto: testDtoList) {
try {
content = StringEscapeUtils.unescapeHtml4(testDto.getContent()).
replaceAll("<style(.+?)</style>", "").
replaceAll("<script(.+?)</script>", "").
replaceAll("(?s)<[^>]*>(\\s*<[^>]*>)*", " ").
replaceAll("[^a-zA-Z0-9\\\\.]+", " ").
replace("\\n", " ").
replaceAll("\\\\r","").trim();
} catch (ContentTooLongException e) {
System.out.println("Content err: " + e.getMessage());
}catch (Exception e) {
System.out.println("other err: " + e.getMessage());
}
}
Now you'll be able to handle any exception.
I have an assignment where I have created a program to sell and order electronic devices and update two text files whenever a new sale/order has been made.
I found a way to update the text file instead of overwriting it so any old orders/sales are not lost and the new ones are added to the end of the file, but my assignment requires me to have the text file in the following form:
SALES
{
SALE
{
(Sale info here)
}
SALE
{
(Another sale info here)
}
}
The SALES { } needs to appear once in the whole file, and I need to update the file with each SALE { }. Can I make it so that
the writer writes only after SALES } (therefore in the 3rd line) and before } (so in the second to last line), even after restarting the application?
This is part of the code of my writer:
File file1= null;
BufferedWriter writer=null;
try {
file1=new File(path);
}
catch (NullPointerException e) {
System.err.println ("Not Found.");
}
try {
writer=new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file1, true)));
}
catch (FileNotFoundException e) {
System.err.println("Error opening file for writing.");
}
try
{
writer.write("SALES " + "\n" + "{");
//Writer writes sale info here
writer.write("\n" + "}");
}
catch (IOException e) {
System.err.println("Write error!");
}
Basically as of now, it creates SALES{ } every time I run the program, which is something I don't want.
Another way I thought of doing this is basically start the file with the following:
SALES
{
}
and just overwrite the last line with every new order, and at the end of each execution I will add another } in the end which will close the upper SALES {. But I also do not know how to do that.
Sorry if this sounds very amateurish. Thank you for any answers beforehand.
One way you can give a try is by checking whether "SALES
{" string is present in your file. If present you may directly write sales info else write the entire file.
You can include following snippet in your code to scan the file line by line as follows:
Scanner scanner = new Scanner(file1);
while(scanner.hasNextLine()){
if("SALES{".equals(scanner.nextLine().trim())){
//Writer writes sale info here
break;
}else{
writer.write("SALES " + "\n" + "{");
//Writer writes sale info here
writer.write("\n" + "}");
}
}
First of all, use this as a line separator:
String lineSeparator = System.getProperty("line.separator");
Why? diferent systems use diferent ways to separate the lines ( \n < linux, \r\n < windows, \r < mac).
In your code you will change de +"\n"+ to + lineSeparator + .
The best way to write this is to use a collection (array) of Sale Objects and then you will interate through this collection, like:
for(Sale sale : sales){
sale.getters // Infos
//write +\t+ (tab) and save infos
}
and then finish with "+}+"
For me its better to always create a new file in this case.
I am having some issue writing a small program for myself. I have a class that will read from a CSV and put the data into arraylist of the class Farts (this is short for fighting arts before you ask). This works, when I test my output I can see the values read in from the csv.
AssetManager assetManager =context.getAssets();
ArrayList<Farts> arrayfarts = new ArrayList<Farts>();
InputStream csvStream = null;
System.out.println("right before try loop");
try {
csvStream = assetManager.open("farts.txt");
InputStreamReader csvStreamReader = new InputStreamReader(csvStream);
CSVReader csvreader = new CSVReader(csvStreamReader);
Farts fdata = new Farts();
String[] line;
int temp=0;
while ((line=csvreader.readNext())!=null){
System.out.println("inside of while");
fdata.fname=line[0];
fdata.description=line[1];
arrayfarts.add(temp,fdata);
System.out.println("Array iteration " + temp + " of " + arrayfarts.size());
System.out.println(arrayfarts.get(temp).fname + " " + arrayfarts.get(temp).description + "\n");
temp++;
}
} catch (IOException e) {
e.printStackTrace();
System.out.println("ioexception"+e.toString());
}
return arrayfarts;
}
Back in my Main class I then use .addall to add what is returned from above. However the data in the Arraylist is populated by only the last value entered into it.
arrayFarts.addAll(readcsv.retrieveFarts(this));
System.out.println(arrayFarts.get(0).fname + " " + arrayFarts.get(0).description + "\n");
int temp=0;
while (temp<arrayFarts.size()){
cupboard().withDatabase(db).put(arrayFarts.get(temp));
System.out.println("Array iteration " + temp + " of " + arrayFarts.size());
System.out.println(arrayFarts.get(temp).fname+" "+arrayFarts.get(temp).description+"\n");
temp++;
}
Am I missing something?
The problem lies in these lines:
fdata.fname=line[0];
fdata.description=line[1];
arrayfarts.add(temp,fdata);
You need to create a new Farts instance each loop, not change a single instance.
As it stands, you simply add the same instance multiple times to the list, while changing its values. This means that you will see only the last parsed values after the loop completes. You will also see it multiple times, as ArrayList allows duplicates.
I am setting up a rank system where each member has a username and a rank. The program reads the username and rank from a text file and assigns it to the user.
One username and rank per line, such as:
user1 1
user2 2
user3 3
I have set up a program to add usernames and ranks to the text file, however I cannot seem to figure out how to delete a specific user from the list, such as if I wanted to only delete user 2 and his/her rank and leave the other two, however it is important that afterwards there isn't a blank line left behind.
Just for reference here is the code for how I write it to the file in the first place:
try {
BufferedWriter out = new BufferedWriter(new FileWriter("stafflist.txt", true));
for (int i = 0; i < 1; i++) {
out.newLine();
out.write(target.getUsername() + " " + target.getRights());
}
out.close();
SerializableFilesManager.savePlayer(target);
if (loggedIn) {
target.getPackets().sendGameMessage(modString + Utils.formatPlayerNameForDisplay(member.getUsername()) + "!", true);}
member.getPackets().sendGameMessage(successString + Utils.formatMemberNameForDisplay(target.getUsername()) + " to a Moderator.",true);
loggedIn = false;
} catch (IOException e) {
System.out.println("GiveMod - Can't find stafflist.txt");
}
return true;
You cannot delete data from the middle of a file (without leaving nulls). You need to rewrite at least what underneath it. A Simple solution would be loading everything in memory, remove that line and dump the collection again.
An alternative solution would be to:
Open a FileChannel from a RandomAccessFile
read the file line by line and keep the file-pointer of the line head. fileChannel.position();file.readLine(); load what comes after that into a collection. truncate the file from that position file.setLength(linePosition); and then dump the collection at the end of the file.
If your data doesn't fit in memory then you can use a temp file instead of a collection. Create a temp-file File.createTempFile(...), read the remaining data line by line and write to temp, truncate the original file ,read temp line by and write to original.
OR, guess what, use a database.
There seems to be an issue in your for loop. It is looping between 0 and 1, so I think the output you posted is incorrect. Anyway, if you want to only print out certain lines you can filter it as follows:
for (int i = 0; i < 1; i++) {
if(!target.getUsername().equals("user2")){
out.newLine();
out.write(target.getUsername() + " " + target.getRights());
}
}
Read the file into some Collection, remove desired users and rewrite the file using the modified Collection.
Hope you are well. Could you help me with the below code.
I would like to make sure that a user Inputs a value into the edtScore and it is not left blank before they hit the Save Button. Currently the user can hit the save button even if the edtScore is left blank.
Thanks for the Help.
public void saveLogOnClick (View view){
String FILENAME = "results.csv"; //Stores onto Mobile Phone Storage Space
String entry = edtDate.getText().toString() + "," +
edtTime.getText().toString() + "," +
category.getSelectedItem().toString() + "," +
edtScore.getText().toString() +"\n";
try{
FileOutputStream out = openFileOutput(FILENAME, Context.MODE_APPEND);
out.write(entry.getBytes());
out.close();
toastIt("Entry Saved");
} catch (Exception e){
e.printStackTrace();
}
}
I'm a beginner, but I think this is easier than it appears. But for the sake of simplicity, this is what I can say at my level.
The easiest way to check if edtScore was empty would be to check if the string is blank, like so:
if( edtScore.getText().toString() == "" ){
return; // exit failure
}
And then, with further research I could come up with:
String str = edtScore.getText().toString();
if(str != null && !str.isEmpty()){
return;// exit failure.
}