Ok, say I have a text file called "people.txt", and it contains the following information:
1 adam 20 M
2 betty 49 F
3 charles 9 M
4 david 22 M
5 ethan 41 M
6 faith 23 F
7 greg 22 M
8 heidi 63 F
Basically, the first number is the ID of the person, then comes the person's name, age and gender. Say I want to replace line 2, or the person with ID number 2 with different values. Now, I know I cant use RandomAccessFile for this because the names are not always the same number of bytes, neither are the ages. While searching random Java forums, I found that StringBuilder or StringBuffer should suffice for my needs, but I'm not sure how to implement either. Can they be used to directly write to the text file? I want this to work directly from user input.
Just created an example for you
public static void main(String args[]) {
try {
// Open the file that is the first
// command line parameter
FileInputStream fstream = new FileInputStream("d:/new6.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(fstream));
String strLine;
StringBuilder fileContent = new StringBuilder();
//Read File Line By Line
while ((strLine = br.readLine()) != null) {
// Print the content on the console
System.out.println(strLine);
String tokens[] = strLine.split(" ");
if (tokens.length > 0) {
// Here tokens[0] will have value of ID
if (tokens[0].equals("2")) {
tokens[1] = "betty-updated";
tokens[2] = "499";
String newLine = tokens[0] + " " + tokens[1] + " " + tokens[2] + " " + tokens[3];
fileContent.append(newLine);
fileContent.append("\n");
} else {
// update content as it is
fileContent.append(strLine);
fileContent.append("\n");
}
}
}
// Now fileContent will have updated content , which you can override into file
FileWriter fstreamWrite = new FileWriter("d:/new6.txt");
BufferedWriter out = new BufferedWriter(fstreamWrite);
out.write(fileContent.toString());
out.close();
//Close the input stream
in.close();
} catch (Exception e) {//Catch exception if any
System.err.println("Error: " + e.getMessage());
}
}
One solution could be to read in the file, line-by-line, manipulate the lines you need (performing some parsing/tokenization to get the ID/name/etc.), then write all the lines into the file (overwriting its current content). This solution depends on the size of the file you are working with: too large a file will consume a lot of memory as you are holding all its contents in memory at once
Another approach (to cut down on memory requirements) is to process the file lin-by-line, but instead of holding all lines in memory, you write the current line to a temporary file after processing of each line, then move the temporary file to the location of the input file (overwriting that file).
The classes FileReader and FileWriter should help you with reading/writing to the file. You might want to wrap them in a BufferedReader/BufferedWriter to improve performance.
Also, don't forget to close the reader (also, the writer) when done reading (writing) the file, so consequent accesses to the file are not blocked due to the file still being open
Related
Basically I've got an assignment which reads multiple lines from a .txt file.
There are 4 values in the text file per line and each value is separated by 2 spaces.
There are about 10 lines of data in the file.
After taking the input from the file the program then puts it onto a Database. The database connection functionality works fine.
My issue now is with reading from the file using a BufferedReader.
The issue is that if I uncomment any 1 of the 3 lines at the bottom the BufferedReader reads every other line. And if I don't use them then there's an exception as the next input is of type String.
I have contemplated using a Scanner with the .hasNextLine() method.
Any thoughts on what could be the problem and how to fix it?
Thanks.
File file = new File(FILE_INPUT_NAME);
FileReader fr = new FileReader(file);
BufferedReader readFile = new BufferedReader(fr);
String line = null;
while ((line = readFile.readLine()) != null) {
String[] split = line.split(" ", 4);
String id = split[0];
nameFromFile = split[1];
String year = split[2];
String mark = split[3];
idFromFile = Integer.parseInt(id);
yearOfStudyFromFile = Integer.parseInt(year);
markFromFile = Integer.parseInt(mark);
//line = readFile.readLine();
//readFile.readLine();
//System.out.println(readFile.readLine());
}
Edit: There was an error in the formatting of the .txt file. a missing value.
But now I get an ArrayOutOfBoundsException.
Edit edit: Another error in the .txt file! Turns out there was a single space instead of a double. It seems to be working now. But any advice on how to deal with file errors like this in the future?
The issue is that if I uncomment any 1 of the 3 lines at the bottom the BufferedReader reads every other line.
Correct. If you put any of those lines of code in, the line of text read will be thrown away and not processed. You're already reading in the while condition. You don't need another read. If you put any of those lines in, they will be thrown away and not proce
A compilable version of the code posted could be
public void read() throws IOException {
File file = new File(FILE_INPUT_NAME);
FileReader fr = new FileReader(file);
BufferedReader readFile = new BufferedReader(fr);
String line;
while ((line = readFile.readLine()) != null) {
String[] split = line.split(" ", 4);
if (split.length != 4) { // Not enough tokens (e.g., empty line) read
continue;
}
String id = split[0];
String nameFromFile = split[1];
String year = split[2];
String mark = split[3];
int idFromFile = Integer.parseInt(id);
int yearOfStudyFromFile = Integer.parseInt(year);
int markFromFile = Integer.parseInt(mark);
//line = readFile.readLine();
//readFile.readLine();
//System.out.println(readFile.readLine());
}
}
The above uses a single space (" " instead of the original " "). To split on any number of changes, a regular expression can be used, e.g. "\\s+". Of course, exactly 2 spaces can also be used, if that reflects the structure of the input data.
What the method should do with the extracted values (e.g., returning them in an object of some type, or saving them to a database directly), is up to the application using it.
I wanted to delete a line from a textfile after asking the user what he/she wants to delete but I don't know what to do next in my code.
The textfile looks like this:
1::name::mobileNum::homeNum::fax::birthday::email::website::address // line the user wants to delete
2::name::mobileNum::homeNum::fax::birthday::email::website::address
3::name::mobileNum::homeNum::fax::birthday::email::website::address
Here's my code:
public static void readFromFile(String ans, String file) throws Exception {
BufferedReader fileIn = new BufferedReader(new FileReader(file));
GetUserInput console = new GetUserInput();
String checkLine = fileIn.readLine();
while(checkLine!=null) {
String [] splitDetails = checkLine.split("::");
Contact details = new Contact(splitDetails[0], splitDetails[1], splitDetails[2], splitDetails[3], splitDetails[4], splitDetails[5], splitDetails[6], splitDetails[7], splitDetails[8]);
checkLine = fileIn.readLine();
if(ans.equals(splitDetails[0])) {
// not sure what the code will look like here.
// in this part, it should delete the line the user wants to delete in the textfile
}
}
}
So the output of the textfile should be like this:
2::name::mobileNum::homeNum::fax::birthday::email::website::address
3::name::mobileNum::homeNum::fax::birthday::email::website::address
Also, I want the line number 2 and 3 to be adjusted to 1 and 2:
1::name::mobileNum::homeNum::fax::birthday::email::website::address
2::name::mobileNum::homeNum::fax::birthday::email::website::address
How would I do this?
Here's a working code, assuming you are using Java >= 7:
public static void removeLine(String ans, String file) throws IOException {
boolean foundLine = false;
try (BufferedReader br = Files.newBufferedReader(Paths.get(file));
BufferedWriter bw = Files.newBufferedWriter(Paths.get(file + ".tmp"))) {
String line;
while ((line = br.readLine()) != null) {
String[] tokens = line.split("::", 2);
if (tokens[0].equals(ans)) {
foundLine = true;
} else {
if (foundLine) {
bw.write((Integer.parseInt(tokens[0]) - 1) + "::" + tokens[1]);
} else {
bw.write(line);
}
bw.newLine();
}
}
}
Files.move(Paths.get(file + ".tmp"), Paths.get(file), StandardCopyOption.REPLACE_EXISTING);
}
It is not possible to delete a line from a file. What you need to do is read the existing file, write the contents you want to keep to a temporary file and then rename the temporary file to overwrite the input file.
Here, the temporary file is created in the same directory as the input file, with the extension .tmp added (note that you can also use Files.createTempFile for this).
For each line that is read, we check if this is the line the user wants to delete.
If it is, we update a boolean variable telling us that we just hit the line to be deleted and we do not copy this line to the temporary file.
If it is not, we have a choice:
Either we did not yet hit the line to be deleted. Then we simply copy what we read to the temporary file
Or we did and we need to decrement the first number and copy the rest of the line to the temporary file.
The current line is splitted with the help of String.split(regex, limit) (it splits the line only two times, thereby creating an array of 2 Strings: first part is the number, second part is the rest of the line).
Finally, the temporary file overwrites the input file with Files.move (we need to use the REPLACE_EXISTING option).
I've saved a good few tweets in a text file with the following format:
Country:Brazil_result.txt Date: \r\n09/19/14 TweetTextExtract: #Brazil on track to becoming the leader of #wind #energy production in Latin America http://t.co/MFJjNPxodf
Country:Brazil_result.txt Date: \r\n09/19/14 TweetTextExtract: #ConceptOfficial FOLLOW ME GUYS PLEASE I LOVE YOU SO MUCH 💕BRAZIL LOVE YOU💙💚💛x16
Country:Brazil_result.txt Date: \r\n09/19/14 TweetTextExtract: #JamesFenn90 plenty teams travelled far more in Brazil from their bases to each game.I'm sure eng can manage a trip to Amsterdam etc etc
Now what I look to do is read in line by line from the text file and then split the line by "TweetTextExtract: " but for some reason I keep getting an ArrayIndexOutOfBoundsException:1 error and I can't see why as every line has the "TweetTextExtract: " term. Here is the error in the console:
Country:Brazil_result.txt Date: \r\n09/19/14 #ConceptOfficial FOLLOW ME GUYS
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 1
at WhatToThink.main(WhatToThink.java:28)
The line with this tweet has the "TweetTextExtract: " term and so does the line succeeding it. I'm not to sure why this is breaking. Here is the code:
String folderPath = "C:/Users/me/workspace/Sentiment Analysis/Good Data";
File fin = new File(folderPath + "/Brazil_result" + ".txt");
FileInputStream fis = new FileInputStream(fin);
BufferedReader br = new BufferedReader(new InputStreamReader(fis));
String line = null;
while ((line = br.readLine()) != null) {
String[] stringline = line.split("TweetTextExtract: ");
System.out.println(stringline[0] + stringline[1]);
//System.out.println(line);
}
br.close();
Your problem is almost surely a bad text encoding for your file. Save your file as UTF-8 (or UTF-16), then use
new InputStreamReader(fis, "UTF-8") //or UTF-16
If the encoding you use in the above constructor does not match the one of the text file, you will get gibberish and then the split won't work even on the first line.
If you want to keep the original encoding for you text file, just find out what it is and use it instead.
it actually doesn't give the exception for me when i run it.but how ever you can avoid this error by dynamically print element inside splited String.the following enhanced loop will gives you the same result ..
String[] stringline = line.split("TweetTextExtract: ");
for (String s : stringline) {
System.out.print(s);
}
System.out.println("");
and you can find your self how much element exist inside the stringline array by looking at the result.
You can use something like that:
if (line.contains("TweetTextExtract: ")){
String[] stringline = line.split("TweetTextExtract: ");
System.out.println(stringline[0] + stringline[1]);
}
else{
System.out.println("Line doesn't't contain \"TweetTextExtract: \"");
}
I'm reading .txt file into my program and am adding lines of the .txt into a String arrayList. How do I add lines DELINEATED BY AN ENTER KEY (in .txt) into separate elements of the arrayList? Right now if I had the following written in text:
this is a test
test
test test
It would output:
this is a testtesttest test
What I want it to do is read things on a per line basis, and put it into different elements of the stringArrayList. So I want "this is a test" to be an element, and "test", and then finally "test test".
My code is really ugly, but right now all I want to do is get it to work for my purpose. My first purpose is getting to read a .txt by line. My second purpose is going to be parsing an element for a particular substring (a URL), connecting that URL to the internet, and then comparing a part of that page source of the webpage (parsing for a particular keyword) to the line ABOVE the substring I desire. But that's a question for another time :^)
import java.io.*;
import java.util.*;
public class Test {
public static void main(String [] args) {
// The name of the file to open.
String fileName = "test.txt";
List<String> listA = new ArrayList<String>();
// This will reference one line at a time
String line = null;
try {
// FileReader reads text files in the default encoding.
FileReader fileReader = new FileReader(fileName);
// Always wrap FileReader in BufferedReader.
BufferedReader bufferedReader = new BufferedReader(fileReader);
while((line = bufferedReader.readLine()) != null) {
System.out.println(line);
listA.add(line);
//*** THIS IS WHERE THE MAGIC HAPPENS ***\\ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
}
// Always close files.
bufferedReader.close();
}
catch(FileNotFoundException ex) {
System.out.println(
"Unable to open da file ofheee hah. '" +
fileName + "'");
}
catch(IOException ex) {
System.out.println(
"Error reading file '"
+ fileName + "'");
// Or we could just do this:
// ex.printStackTrace();
}
System.out.println();
System.out.println("array FOr loop thingy incoming:");
System.out.println();
for (int i = 0; i < listA.size(); i++) {
System.out.print((listA.get(i)).toString());
}
}
}
You just have to use println instead of print:
System.out.println((listA.get(i)).toString());
Alternatively, you can add the line break character \n
Your code seems to be working so far. If you just want to see what elements are in listA, just print it out:
System.out.println(listA);
Output:
[this is a test, , test, , test test, ]
Note that the extra lines in your input file are also being stored in listA. I'm not sure if that's the behavior you want.
Hi i'm working on an android app and this is my problem
I have a text file that is maybe 100 lines long it differs from phone to phone but lets say a section is like this
line 1 = 34
line 2 = 94
line 3 = 65
line 4 = 82
line 5 = 29
etc
each line will be equal to some number however that number will be different from phone since my application will be changing this number and it may already be different before my app is installed. So here's my problem i want to search the text file for say "line 3 = " then delete that entire line and replace it with "line 3 = some number"
My main goal is to change that number at the end of line 3 and keep line 3 that is the text exactly the same i only want to edit the number however the problem is that number will always be different
How can i go about doing this? thanks for any help
You can't "insert" or "remove" characters in the middle of a file. I.e., you can't replace 123 with 1234 or 12 in the middle of a file.
So either you "pad" each number so they all have equal width, i.e., you represent 43 as for instance 000043, or you'll probably have to regenerate the whole file.
To regenerate the whole file, I suggest you read the original file line by line, process the lines as appropriate, and write them out to a new, temporary file along the way. Then, when you're through, you replace the old file with the new one.
To process the line I suggest you do something like
String line = "line 3 = 65";
Pattern p = Pattern.compile("line (\\d+) = (\\d+)");
Matcher m = p.matcher(line);
int key, val;
if (m.matches()) {
key = Integer.parseInt(m.group(1));
val = Integer.parseInt(m.group(2));
// Update value if relevant key has been found.
if (key == 3)
val = 123456;
line = String.format("line %d = %d", key, val);
}
// write out line to file...
Thanks guys for the replies but what i ended up doing was using the sed command in bash and the wild card command * to replace the line and then just ran the script through java which went a little like this
Script
busybox sed -i 's/line 3 = .*/line 3 = 70/g' /path/to/file
Java
Command
execCommand("/path/to/script");
Method
public Boolean execCommand(String command)
{
try {
Runtime rt = Runtime.getRuntime();
Process process = rt.exec("su");
DataOutputStream os = new DataOutputStream(process.getOutputStream());
os.writeBytes(command + "\n");
os.flush();
os.writeBytes("exit\n");
os.flush();
process.waitFor();
} catch (IOException e) {
return false;
} catch (InterruptedException e) {
return false;
}
return true;
}
The simplest solution is to read the whole file into memory and then replace the line want to change and then write it back to the file.
For exmple:
String input = "line 1 = 34\nline 2 = 94\nline 3 = 65\nline 4 = 82\nline 5 = 29\n";
String out = input.replaceAll("line 3 = (\\d+)", "line 3 = some number");
...outputs:
line 1 = 34
line 2 = 94
line 3 = some number
line 4 = 82
line 5 = 29
A couple thoughts. An easier way to do this (if possible) would be to store these lines in a collection (like an ArrayList) and do all of your manipulation within your collection.
Another solution can be found here. If you need to replace the contents within a text file, you could call a method periodically to do this:
try {
BufferedReader in = new BufferedReader(new FileReader("in.txt"));
PrintWriter out = new PrintWriter(new File("out.txt"));
String line; //a line in the file
String params[]; //holds the line number and value
while ((line = in.readLine()) != null) {
params = line.split("="); //split the line
if (params[0].equalsIgnoreCase("line 3") && Integer.parseInt(params[1]) == 65) { //find the line we want to replace
out.println(params[0] + " = " + "3"); //output the new line
} else {
out.println(line); //if it's not the line, just output it as-is
}
}
in.close();
out.flush();
out.close();
}catch(Exception e) {
e.printStackTrace();
}