I have a problem with some java code.
I'm returning a text from a method, which is on a .txt file. Then, I'm storing this text to a variable "text" and writing this on another .txt file. But the problem is: this new .txt file gets a new blank line at the bottom. That's because inside my method read, the variable "text" is receiving a "\n". How can I solve this problem?
PS: I'm doing this with educational purposes.
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.FileReader;
import java.io.FileWriter;
public class Arquivo {
public static void main(String[] args) {
String text = read("in.txt");
write(text, "out.txt");
System.out.println("Text created!");
}
public static String read(String arquivo) {
String text = "";
try (BufferedReader br = new BufferedReader(new FileReader(arquivo))) {
String line = br.readLine();
while (line != null) {
text += line + "\n";
line = br.readLine();
}
} catch (IOException e) {
System.err.println(e.getMessage());
}
return text;
}
public static void write(String text, String arquivo) {
try (BufferedWriter bw = new BufferedWriter(new FileWriter(arquivo))) {
bw.write(text);
} catch (IOException e) {
System.err.println(e.getMessage());
}
}
}
My two created files "in.txt" and "out.txt".
this is
a text file.
this is
a text file.
(blank line)
please try this:
String line = br.readLine();
while (line != null) {
text += line;
line = br.readLine();
if (line!=null){
text += "\n";
}
}
you can try this variant:
String line;
while((line = br.readLine()) != null) {
text += line;
if (line!=null){
text += "\n";
}
}
A good solution to this type of problem is to add the newline before you write each additional line:
String line = br.readLine();
text += line;
while ((line = br.readLine()) != null) {
text = "\n" + line;
}
This way, you only add the newline for each additional line you write (no extraneous ones at the end). Notice the assignment (plus null check) in the while loop).
replace write(text, "out.txt"); with
write(text.substring(0,text.length()-1), "out.txt");
which will remove the last character, which is the /n before writing.
Store all the strings in a list, then join on the line feed
public static void main( String[] args ) {
String text = read( "in.txt" );
write( text, "out.txt" );
System.out.println( "Text created!" );
}
public static String read( String arquivo ) {
List<String> texts = new ArrayList<>();
try ( BufferedReader br = new BufferedReader( new FileReader( arquivo ) ) ) {
String line = br.readLine();
while ( line != null ) {
texts.add( line );
line = br.readLine();
}
} catch ( IOException e ) {
System.err.println( e.getMessage() );
}
return texts.stream().collect( Collectors.joining( "\n" ) );
}
public static void write( String text, String arquivo ) {
try ( BufferedWriter bw = new BufferedWriter( new FileWriter( arquivo ) ) ) {
bw.write( text );
} catch ( IOException e ) {
System.err.println( e.getMessage() );
}
}
String.trim()
public String trim()
Returns a copy of the string, with leading and
trailing whitespace omitted. If this String object represents an empty
character sequence, or the first and last characters of character
sequence represented by this String object both have codes greater
than '\u0020' (the space character), then a reference to this String
object is returned.
Otherwise, if there is no character with a code greater than '\u0020'
in the string, then a new String object representing an empty string
is created and returned.
Otherwise, let k be the index of the first character in the string
whose code is greater than '\u0020', and let m be the index of the
last character in the string whose code is greater than '\u0020'. A
new String object is created, representing the substring of this
string that begins with the character at index k and ends with the
character at index m-that is, the result of this.substring(k, m+1).
This method may be used to trim whitespace (as defined above) from the
beginning and end of a string.
Returns: A copy of this string with leading and trailing white space
removed, or this string if it has no leading or trailing white space.
https://docs.oracle.com/javase/7/docs/api/java/lang/String.html#trim()
Simply trim the string before you return it from read.
public static String read(String arquivo) {
String text = "";
try (BufferedReader br = new BufferedReader(new FileReader(arquivo))) {
String line = br.readLine();
while (line != null) {
text += line + "\n";
line = br.readLine();
}
} catch (IOException e) {
System.err.println(e.getMessage());
}
return text.trim();
}
Just do not add \n before the last line:
String text = "";
...
String line = br.readLine();
boolean addNewLine = false;
while (line != null) {
if (addNewLine) {
text += "\n";
} else {
addNewLine = true;
}
text += line;
line = br.readLine();
}
Also, for performance improvement, consider using a StringBuilder instead of the string concatenation:
StringBuilder sb = new StringBuilder();
...
String line = br.readLine();
boolean addNewLine = false;
while (line != null) {
if (addNewLine) {
sb.append('\n');
} else {
addNewLine = true;
}
sb.append(line);
line = br.readLine();
}
...
String text = sb.toString();
Related
I'm reading data from the input stream where string in two different formats.
One is with a header that is:
Scale id,Rec.No,Date,Time,Bill No.,Item No.,Plu,Name,Qty,Rate,Amount,Void
0,142,17/01/21,17:50,053,3848,001,POTATO ,0.615,50.00,30.75,N
0,143,17/01/21,17:50,053,3849,002,POTATO P ,0.985,36.00,35.46,N
0,144,17/01/21,17:50,053,3850,003,ONION P ,1.550,15.00,23.25,N
Second format is without header:
001,1234560,POTATO ,0,000,K,50.00,15.258,#
002,1234561,POTATO P ,0,000,K,36.00,15.258,#,0.00
003,1234562,ONION P ,0,000,K,15.00,15.258,#,0.00
004,1234563,BR. CHU.CHU. ,0,000,K,28.00,15.258,#,0.00
005,1234564,BR. ROUND ,0,000,K,24.00,15.258,#,0.00
I want to parse these two different formats in two different methods.
Logic and the logic I have used:
public void getReportResponse()throws IOException {
BufferedReader br = null;
str = new StringBuffer();
int bytes = 0;
byte[] packetBytes = new byte[256];
try {
br = new BufferedReader(new InputStreamReader(mmInStream));
String line="";
while ((line = br.readLine()) != null) {
// line = line.trim();
//dataparse.Data(s);
Log.i("DATA in getReportResponse", line);
if (line.matches("Scale id,Rec.No,Date,Time,Bill No.,Item No.,Plu,Name,Qty,Rate,Amount,Void")) {
do {
bytes = mmInStream.read( packetBytes );//READING THE INPUT STREAM
line = new String( packetBytes, 0, bytes );
// append the string in string buffer
str.append( line );
Log.i( TAG,"Report"+str);
// dataparse.ReportData(str.toString());
line="";
} while (str.length()!=-1);
Log.i( TAG,"REPORT"+str);
dataparse.ReportData(str.toString());//this method is for parse value without header after condition
} else {
String data = line.trim();
dataparse.Data(data);//this is working yes//this one is for passing data without header
// Log.i("DATA",line);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
But 'if' the condition doesn't work please help me
I would check for the header only once and also only check the first header element
//... removed for brevity
br = new BufferedReader(new InputStreamReader(mmInStream));
String line = br.readLine();
if (line != null && line.startsWith("Scale id")) {
handleHeader(line);
line = br.readLine();
}
while (line != null) {
String data = line.trim();
dataparse.Data(data);
line = br.readLine();
}
//... removed for brevity
Note that all code that is for the if condition has been moved into handleHeader
I'm trying to split a String[] but while trying to do the data is not getting split correctly. my code as follows:
try (FileReader fr = new FileReader(path);
BufferedReader br = new BufferedReader(fr))
{ int i;
String line = null;
System.out.println("Line value: "+line);
br.readLine();
for ( i=1;(line = br.readLine()) != null;i++) {
String[] s = line.split(",");
System.out.println("Value of row " + Float.parseFloat(datasetData.get((datasetData.size() - 1))[i])+" and column is: "+ s[1]);
series2.add(Float.parseFloat(datasetData.get((datasetData.size() - 1))[i]), Double.parseDouble((s[1])));
The result produced by this is:
"1594898820","0","","Aggregated",0.00,0.00,"N/A","N/A","N/A","N/A","N/A","N/A","N/A","N/A","N/A","N/A","N/A","N/A",0,0,0,0,0,0,0
But I need them without double quotes . Something like this:
1594898820,0,,Aggregated,0.00,0.00,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,0,0,0,0,0,0,0
Because i need to further use this data is some comparison and with quotes that is getting failed.
A naive way to do this is to replace:
The starting quote, if present, with an empty string
A closing quote, followed by a comma, with just a comma
An opening quote, preceded by a comma, with just a comma
The final quote, if present, with an empty string
Example
import java.io.*;
import java.nio.file.*;
public class Parser {
private static ClassLoader loader = Parser.class.getClassLoader();
public static void main(String[] args) {
try {
fixFile(loader.getResourceAsStream("data.csv"), "fixed.csv");
} catch (IOException e) {
e.printStackTrace();
}
}
private static void fixFile(InputStream stream, String filename) throws IOException {
Files.write(Paths.get(filename), fixLines(stream).getBytes());
}
private static String fixLines(InputStream inputStream) throws IOException {
StringBuilder sb = new StringBuilder();
try (BufferedReader br = new BufferedReader(new InputStreamReader(inputStream))) {
String line;
while ((line = br.readLine()) != null) {
sb.append(fixLine(line)).append(System.lineSeparator());
}
}
return sb.toString();
}
private static String fixLine(String line) {
return line.replaceFirst("^\"", "")
.replaceAll("\",", ",")
.replaceAll(",\"", ",")
.replaceFirst("\"$", "");
}
}
Input
"1594898820","0","","Aggregated",0.00,0.00,"N/A","N/A","N/A","N/A","N/A","N/A","N/A","N/A","N/A","N/A","N/A","N/A",0,0,0,0,0,0,0
Output
1594898820,0,,Aggregated,0.00,0.00,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,N/A,0,0,0,0,0,0,0
I'm writing a program in java to search for a list of words(transaction numbers) in a .txt file. The .txt file can have any number of lines.
List<String> transactionList = new ArrayList<String>(
Arrays.asList("JQ7P00049", "TM7P04797", "RT6P70037");
FileReader fileReader = new FileReader(filePath);
BufferedReader bufferedReader = new BufferedReader(fileReader);
try {
String readLine = bufferedReader.readLine();
for (String transactionIndex : transactionList) {
if (readLine != null) {
if (readLine.contains(transactionIndex)) {
System.out.println(transactionIndex + ": true");
readLine = bufferedReader.readLine();
} else {
readLine = bufferedReader.readLine();
}
}
}
}
The programs runs fine except if the word is split between two lines, for example:
-------- JQ7P0
0049----------
that's obviously because the bufferedReader reads line by line and does the comparison of search string with the content present in that line.
Is there any way to handle this scenario?
As durron597 mentioned, you weren't looping through the whole file, but here's a solution that assumes the file has at least 2 lines and that a transaction string doesn't span more than 2 lines.
It concatenates each line with the next, and searches for the strings in the concatenated lines. To prevent the same transaction from being printed twice, I added an additional check.
List<String> transactionList = new ArrayList<String>( Arrays.asList("JQ7P00049", "TM7P04797", "RT6P70037") );
FileReader fileReader = new FileReader(filePath);
BufferedReader bufferedReader = new BufferedReader(fileReader);
try {
// Search the first line
String lastLine = bufferedReader.readLine();
for (String transactionIndex : transactionList) {
if (lastLine.contains(transactionIndex)) {
System.out.println(transactionIndex + ": true");
}
}
String currentLine = null;
// Search the remaining lines
while((currentLine=bufferedReader.readLine()) != null) {
String combined = lastLine + currentLine;
for (String transactionIndex : transactionList) {
if (currentLine.contains(transactionIndex) || (!lastLine.contains(transactionIndex) && combined.contains(transactionIndex))) {
System.out.println(transactionIndex + ": true");
}
}
lastLine = currentLine;
}
} catch ( Exception e ) {
System.out.println( e.getClass().getSimpleName() + ": " + e.getMessage() );
} finally {
bufferedReader.close();
}
This program has a second problem: You aren't going to read all the lines in longer files, because you have no loop that will loop through all the lines in the file.
That said, you can do this by reading two lines at once, and merging them together.
Here's a complete program:
private static final List<String> transactionList = new ArrayList<String>(Arrays.asList(
"JQ7P00049", "TM7P04797", "RT6P70037"));
public static void main(String[] args) throws Exception {
String filePath = "test.txt";
FileReader fileReader = new FileReader(filePath);
BufferedReader bufferedReader = new BufferedReader(fileReader);
try {
String firstLine = bufferedReader.readLine();
String secondLine = bufferedReader.readLine();
if (secondLine == null) {
checkLine(firstLine);
}
do {
String combinedLine = firstLine + secondLine;
checkLine(combinedLine);
firstLine = secondLine;
} while ((secondLine = bufferedReader.readLine()) != null);
} finally {
}
}
private static void checkLine(String combinedLine) {
for (Iterator<String> iterator = transactionList.iterator(); iterator.hasNext();) {
String transactionIndex = iterator.next();
if (combinedLine.contains(transactionIndex)) {
System.out.println(transactionIndex + ": true");
iterator.remove();
}
}
}
Your code seems to not properly read the file, but rather reads as many lines as you have transaction numbers you're looking for. Assuming that this is not what you want, I have corrected it.
Also, I assume that an transaction number can span AT MOST two lines.
List<String> transactionList = new ArrayList<String>(
Arrays.asList("JQ7P00049", "TM7P04797", "RT6P70037"));
FileReader fileReader = new FileReader(filePath);
BufferedReader bufferedReader = new BufferedReader(fileReader);
String[] lastLines = {"",""};
try {
String readLine;
while((readLine = bufferedReader.readLine()) != null) {
lastLines[0] = lastLines[1];
lastLines[1] = readLine;
String combinedLastLines;
combinedLastLines = lastLines[0] + lastLines[1];
for (String transactionIndex : transactionList) {
if (combinedLastLines.contains(transactionIndex) && !lastLines[0].contains(transactionIndex)) {
System.out.println(transactionIndex + ": true");
}
}
}
}
The general idea is to always combine two lines, and look whether the transaction number is in there. Let's have a look at the code:
String[] lastLines = {"",""};
This line defines an array which we will use to store the two most recently read lines.
while((readLine = bufferedReader.readLine()) != null) {
This snippet reads as many lines as there are in your text file.
lastLines[0] = lastLines[1];
lastLines[1] = readLine;
String combinedLastLines;
combinedLastLines = lastLines[0] + lastLines[1];
This code is responsible for replacing the oldest line in the array, and push the currently readLine into the array. Those last two lines are then combined to one String!
if (combinedLastLines.contains(transactionIndex) && !lastLines[0].contains(transactionIndex)) {
Here we are searching the combined lines for the transaction numbers. But: when a transaction number is not spanning multiple lines, we might accidently find it twice. Therefore, the second check is for ensuring we did not find the transaction before.
Hope this is what you're looking for!
public class Auto
{
public static void main(String [] args) {
// The name of the file to open.
System.out.print("\nPlease enter TextfileName.txt : ");
Scanner keyboard = new Scanner(System.in);
String fileName = keyboard.next();
int counter = 0;
//Reading filename.text from code
System.out.println("\nReading '"+fileName+"' from Java Code.\n");
//Date and time stamp for the program.
DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Date date = new Date();
System.out.print("Todays date: "+dateFormat.format(date)+"\n\n\n");
// This will reference one line at a time
String line = null;
FileReader fileReader = null;
//-------------------------------------------------------TAB_1----------------------------------------------//
System.out.println("\t\t\t\t TAB_1[Date on]\n");
try {
// FileReader reads text files in the default encoding.
fileReader = new FileReader(fileName);
// Always wrap FileReader in BufferedReader.
BufferedReader bufferedReader = new BufferedReader(fileReader);
while((line = bufferedReader.readLine()) != null) {
counter++;
if(counter == 1 || counter == 3 || counter == 9)
{
// print out the lines above that are found in the text
System.out.println(line);
System.out.println("----------");
}
}
}
catch(FileNotFoundException ex) {
System.out.println("Unable to open file '" + fileName + "'");
}
catch(IOException ex) {
System.out.println("Error reading file '" + fileName + "'");
// Or we could just do this:
// ex.printStackTrace();
}
finally
{
if(fileReader != null){
// Always close files.
// BufferedReader.close();
}
}
some matcher would help, but i`m not sure how it works
}}
The one i have above is working but i want to also find a specific string anywhere in the text-file and print that line
Just use the contains method of the String class to check for occurances of a substring inside a string.
while((line = bufferedReader.readLine()) != null) {
if (line.contains("some string") {
System.out.println(line);
System.out.println("----------");
}
}
If you wish to check multiple substrings and not just one then you should create a String array of all the substrings you want to look for and loop through them.
First add the following line at the beggining of the class :
public static final String[] listOfStrings = new String[] { "substring 0", "sub string 1" , "substring 2" };
Replace the substrings with your own values.
Then, loop through them to find matches:
while((line = bufferedReader.readLine()) != null) {
for (String match : listOfStrings) {
if (line.contains(match)) {
System.out.println(line);
System.out.println("----------");
break; // No need to continue after the first match
}
}
}
I am loading text file contents to GUI using this code:
try {
BufferedReader br = new BufferedReader(new FileReader ("text.txt"));
String line;
while ((line = br.readLine()) != null) {
if (line.contains("TITLE")) {
jTextField2.setText(line.substring(11, 59));
}
}
in.close();
} catch (Exception e) {
}
Then contents of text.txt file:
JOURNAL journal name A12340001
TITLE Sound, mobility and landscapes of exhibition: radio-guided A12340002
tours at the Science Museum A12340003
AUTHOR authors name A12340004
On jTextField2 I am getting this line: "Sound, mobility and landscapes of exhibition: radio-guided".
The problem is I don't know how to get to jTextField2 the string of next line "tours at the Science Museum".
I would like to ask how can I get both line on jTextField2 i.e. "Sound, mobility and landscapes of exhibition: radio-guided tours at the Science Museum"?
Thank you in advance for any help.
If you are using Java 8 and assuming that the columns have a fixed number of characters, you could something like this:
public static void main(String args[]) throws IOException {
Map<String, String> sections = new HashMap<>();
List<String> content = (List<String>)Files.lines(Paths.get("files/input.txt")).collect(Collectors.toList());
String lastKey = "";
for(String s : content){
String k = s.substring(0, 10).trim();
String v = s.substring(10, s.length()-9).trim();
if(k.equals(""))
k=lastKey;
sections.merge(k, v, String::concat);
lastKey=k;
}
System.out.println(sections.get("TITLE"));
}
The first column is the key. When the keys does not exist, the last key is used. A Map is used to store the keys and the values. When the key already exist, the value is merged with the existing one by concatenation.
This code outputs the expected String: Sound, mobility and landscapes of exhibition: radio-guidedtours at the Science Museum.
EDIT: For Java 7
public static void main(String args[]) {
Map<String, String> sections = new HashMap<>();
String s = "", lastKey="";
try (BufferedReader br = new BufferedReader(new FileReader("files/input.txt"))) {
while ((s = br.readLine()) != null) {
String k = s.substring(0, 10).trim();
String v = s.substring(10, s.length() - 9).trim();
if (k.equals(""))
k = lastKey;
if(sections.containsKey(k))
v = sections.get(k) + v;
sections.put(k,v);
lastKey = k;
}
} catch (IOException e) {
System.err.println("The file could not be found or read");
}
System.out.println(sections.get("TITLE"));
}
Why not create a MyFile class that does the parsing for you, storing key-value-pairs in a Map<String, String>, which you can then access. This will make your code more readable and will be easier to maintain.
Something like the following:
public class MyFile {
private Map<String, String> map;
private String fileName;
public MyFile(String fileName) {
this.map = new HashMap<>();
this.fileName = fileName;
}
public void parse() throws IOException {
BufferedReader br = new BufferedReader(new FileReader(fileName));
String line = br.readLine();
String key = "";
while (line != null) {
//Only update key if the line starts with non-whitespace
key = line.startsWith(" ") ? title : line.substring(0, line.indexOf(" ")).trim();
//If the key is contained in the map, append to the value, otherwise insert a new value
map.put(key, map.get(key) == null ? line.substring(line.indexOf(" "), 59).trim() : map.get(key) + line.substring(line.indexOf(" "), 59).trim());
line = br.readLine();
}
}
public String getEntry(String key) {
return map.get(key);
}
public String toString() {
StringBuilder sb = new StringBuilder();
for (Entry entry:map.entrySet()) {
sb.append(entry.getKey()).append(" : ").append(entry.getValue()).append("\n");
}
return sb.toString();
}
}
This will parse the entire file first. The expected format of the file is:
0 ... 59
[KEY][WHITE SPACE][VALUE]
0 ... 59
[WHITE SPACE][VALUE TO APPEND TO PREVIOUS KEY]
This allows for variable length keys.
Allowing you to handle exceptions separately, and then easily reference the contents of the file like so:
MyFile journalFile = new MyFile("text.txt");
try {
journalFile.parse();
} catch (IOException e) {
System.err.println("Malformed file");
e.printStackTrace();
}
jTextField2.setText(journalFile.getEntry("TITLE"));
An empty (all spaces) first column indicates that a line is the continuation of the previous one. So you can buffer the lines and repeatedly concatenate them, until you get a non-empty first column, and then write/print the whole line.
try {
BufferedReader br = new BufferedReader(new FileReader("text.txt")) ;
String line ;
String fullTitle = "" ;
while ((line = br.readLine()) != null) {
//extract the fields from the line
String heading = line.substring(0, 9) ;
String titleLine = line.substring(10, 69) ;
//does not select on "TITLE", prints all alines
if(heading.equals(" ")) {
fullTitle = fullTitle + titleLine ;
} else {
System.out.println(fullTitle) ;
fullTitle = titleLine ;
}
}
System.out.println(fullTitle) ; //flush the last buffered line
} catch (Exception e) {
System.out.println(e) ;
}
you can do this
First of all read the entire file into a string object.
then get the indexes of the TITLE and AUTHOR
like int start=str.indexOf("TITLE"); and int end=str.indexOf("AUTHOR");
then add the length of TITLE into start index start+="TITLE".length();
and subtract the length of AUTHOR from end index end-="AUTHOR".length();
at last you have the start and end index of text that you want.
so get the text like.
String title=str.subString(start,end);