This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
I guess this comes down to reading and writing to the same file. I would like to be able to return the same text file as is input, but with all integer values quadrupled. Should I even be attempting this with Java, or is it better to write to a new file and overwrite the original .txt file?
In essence, I'm trying to transform This:
12
fish
55 10 yellow 3
into this:
48
fish
220 40 yellow 12
Here's what I've got so far. Currently, it doesn't modify the .txt file.
import java.io.*;
import java.util.Scanner;
public class CharacterStretcher
{
public static void main(String[] args)
{
Scanner keyboard = new Scanner( System.in );
System.out.println("Copy and paste the path of the file to fix");
// get which file you want to read and write
File file = new File(keyboard.next());
File file2 = new File("temp.txt");
BufferedReader reader;
BufferedWriter writer;
try {
// new a writer and point the writer to the file
FileInputStream fstream = new FileInputStream(file);
// Use DataInputStream to read binary NOT text.
reader = new BufferedReader(new InputStreamReader(fstream));
writer = new BufferedWriter(new FileWriter(file2, true));
String line = "";
String temp = "";
int var = 0;
int start = 0;
System.out.println("000");
while ((line = reader.readLine()) != null)
{
System.out.println("a");
if(line.contains("="))
{
System.out.println("b");
var = 0;
temp = line.substring(line.indexOf('='));
for(int x = 0; x < temp.length(); x++)
{
System.out.println(temp.charAt(x));
if(temp.charAt(x)>47 && temp.charAt(x)<58) //if 0<=char<=9
{
if(start==0)
start = x;
var*=10;
var+=temp.indexOf(x)-48; //converts back into single digit
}
else
{
if(start!=0)
{
temp = temp.substring(0, start) + var*4 + temp.substring(x);
//writer.write(line.substring(0, line.indexOf('=')) + temp);
//TODO: Currently writes a bunch of garbage to the end of the file, how to write in the middle?
//move x if var*4 has an extra digit
if((var<10 && var>2)
|| (var<100 && var>24)
|| (var<1000 && var>249)
|| (var<10000 && var>2499))
x++;
}
//start = 0;
}
System.out.println(temp + " " + start);
}
if(start==0)
writer.write(line);
else
writer.write(temp);
}
}
System.out.println("end");
// writer the content to the file
//writer.write("I write something to a file.");
// always remember to close the writer
writer.close();
//writer = null;
file2.renameTo(file); //TODO: Not sure if this works...
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Given that this is a pretty quick and simple hack of a formatted text file, I don't think you need to be too clever about it.
Your logic for deciding whether you are looking at a number is pretty complex and I'd say it's overkill.
I've written up a basic outline of what I'd do in this instance.
It's not very clever or impressive, but should get the job done I think.
I've left out the overwriting and reading the input form the console so you get to do some of the implementation yourself ;-)
import java.io.*;
public class CharacterStretcher {
public static void main(String[] args) {
//Assumes the input is at c:\data.txt
File inputFile = new File("c:\\data.txt");
//Assumes the output is at c:\temp.txt
File outputFile = new File("c:\\temp.txt");
try {
//Construct a file reader and writer
final FileInputStream fstream = new FileInputStream(inputFile);
final BufferedReader reader = new BufferedReader(new InputStreamReader(fstream));
final BufferedWriter writer = new BufferedWriter(new FileWriter(outputFile, false));
//Read the file line by line...
String line;
while ((line = reader.readLine()) != null) {
//Create a StringBuilder to build our modified lines that will
//go into the output file
StringBuilder newLine = new StringBuilder();
//Split each line from the input file by spaces
String[] parts = line.split(" ");
//For each part of the input line, check if it's a number
for (String part : parts) {
try {
//If we can parse the part as an integer, we assume
//it's a number because it almost certainly is!
int number = Integer.parseInt(part);
//We add this to out new line, but multiply it by 4
newLine.append(String.valueOf(number * 4));
} catch (NumberFormatException nfEx) {
//If we couldn't parse it as an integer, we just add it
//to the new line - it's going to be a String.
newLine.append(part);
}
//Add a space between each part on the new line
newLine.append(" ");
}
//Write the new line to the output file remembering to chop the
//trailing space off the end, and remembering to add the line
//breaks
writer.append(newLine.toString().substring(0, newLine.toString().length() - 1) + "\r\n");
writer.flush();
}
//Close the file handles.
reader.close();
writer.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
You may want to consider one of these:
Build the new file in memory, rather than trying to write to the same file you are reading from. You could use StringBuilder for this.
Write to a new file, then overwrite the old file with the new one. This SO Question may help you there.
With both of these, you will be able to see your whole output, separate from the input file.
Additionally, with option (2), you don't have the risk of the operation failing in the middle and giving you a messed up file.
Now, you certainly can modify the file in-place. But it seems like unnecessary complexity for your case, unless you have really huge input files.
At the very least, if you try it this way first, you can narrow down on why the more complicated version is failing.
You cannot read and simultaneously write to the same file, because this would modify the text you currently read. This means, you must first write a modified new file and later rename it to the original one. You probably need to remove the original file before renameing.
For renaming, you can use File.renameTo or see one of the many SO's questions
You seem to parse integers in your code by collecting single digits and adding them up. You should consider using either a Scanner.nextInt or employ Integer.parseInt.
You can read your file line by line, split the words at white space and then parse them and check if it is either an integer or some other word.
Related
I have data file “ReadFile1.txt”. I want to read each data from ReadFile1.txt and manipulate those data then write the results in another file “WriteFile2.txt”. Here is my function. The problem is it only reads 2nd,4th, and so on and does write only 2nd result. What’s wrong in this code? I appreciate your help.
public void doManipulate() throws NumberFormatException, IOException {
int multiple = 10;
try {
FileInputStream file = new FileInputStream("ReadFile1.txt");
InputStreamReader input = new InputStreamReader(file);
BufferedReader reader = new BufferedReader(input);
String data1;
while ((data1 = reader.readLine()) != null) {
int data2 = 0;
data1 = reader.readLine();
data2 = Integer.parseInt(data1);
int compressedFrames = data2*multiple;
File file2 = new File("WriteFile2.txt");
FileWriter writer = new FileWriter(file2);
writer.write(String.valueOf(compressedFrames) + "\n");
writer.flush();
writer.close();
}
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
You're calling reader.readLine() twice for every iteration of the while loop - the first time is in the loop declaration, which reads every odd line, and the second is just a couple of lines down (data1 = reader.readLine();). The second call is blowing away anything read by the first before you have a chance to parse it. Removing the second call should fix the "every other line" issue.
Another issue is that you're closing the writer at every iteration of the while loop - don't close the writer until the while loop is done or your output file will only have the first parsed data element in it after your program closes.
I'm currently writing my project for school in which requires me to read and write to txt files. I can read them correctly but I can only write to them at the end from an appended FileWriter. I would like to be able to overwrite things in my txt files on line numbers by first deleting the data on the line and then writing in the new data. I attempted to use this method...
public void overWriteFile(String dataType, String newData) throws IOException
{
ReadFile file = new ReadFile(path);
RandomAccessFile ra = new RandomAccessFile(path, "rw");
int line = file.lineNumber(path, dataType);
ra.seek(line);
ra.writeUTF(dataType.toUpperCase() + ":" + newData);
}
but I believe that the seek method moves along in bytes rather than line numbers. Can anyone help. Thanks in advance :)
P.S. the file.lineNumber method returns the exact line that the old data was on so I already have the line number that needs to be written to.
EDIT: Soloution found! Thanks guys :) I'll post the soloution below if anyone is interested
public void overWriteFile(String dataType, String newData, Team team, int dataOrder) throws IOException
{
try
{
ReadFile fileRead = new ReadFile(path);
String data = "";
if(path == "res/metadata.txt")
{
data = fileRead.getMetaData(dataType);
}
else if(path == "res/squads.txt")
{
data = fileRead.getSquadData(dataType, dataOrder);
}
else if(path == "res/users.txt")
{
data = fileRead.getUsernameData(dataType, dataOrder);
}
else if(path == ("res/playerdata/" + team.teamname + ".txt"))
{
//data = fileRead.getPlayerData(dataType, team.teamname, dataOrder);
}
BufferedReader file = new BufferedReader(new FileReader(path));
String line;
String input = "";
while((line = file.readLine()) != null)
{
input += line + '\n';
}
input = input.replace(dataType.toUpperCase() + ":" + data, dataType.toUpperCase() + ":" + newData);
FileOutputStream out = new FileOutputStream(path);
out.write(input.getBytes());
}
catch(Exception e)
{
System.out.println("Error overwriting file: " + path);
e.printStackTrace();
}
}
A quick and dirty solution would be to use the Files.readAllLines and Files.write methods to read all lines, change the one you want to change, and overwrite the whole file:
List<String> lines = Files.readAllLines(file.toPath());
lines.set(line, dataType.toUpperCase() + ":" + newData);
Files.write(file.toPath(), lines); // You can add a charset and other options too
Of course, that's not a good idea if it's a very big file. See this answer for some ideas on how to copy the file line by line in that case.
Regardless of how you do it, though, if you are changing the byte length of the line, you will need to rewrite the whole file (AFAIK). RandomAcessFile allows you to move around the file and overwrite data, but not to insert new bytes or removes existing ones, so the length of the file (in bytes) will stay the same.
Here is a link to a question just like this with a great answer:
I want to open a text file and edit a specific line in java
Basically, you can't just edit that line, unless it'll be the exact same length.
Instead, you'll want to copy over every line, and then when you reach the line number of the line you want to change, instead of copying over the old line, just put in your new line.
The link I gave you has a great example on how to do this.
I hope this helps...if not, let me know, and I'll elaborate further on the post. Good luck :)
my problem is to read non primes from txt file and write prime factors in same file.
i actually dont know how BufferedReader works.from my understanding i am trying to read the file data to buffer(8kb) and write prime factors to file.(by creating a new one)
class PS_Task2
{
public static void main(String[] args)
{
String line=null;
int x;
try
{
FileReader file2 = new FileReader("nonprimes.txt");
BufferedReader buff2=new BufferedReader(file2);
File file1 = new File("nonprimes.txt");
file1.createNewFile();
PrintWriter d=new PrintWriter(file1);
while((line = buff2.readLine()) != null)
{
x=Integer.parseInt(line);
d.printf ("%d--> ", x);
while(x%2==0)
{
d.flush();
d.print("2"+"*");
x=x/2;
}
for (int i = 3; i <= Math.sqrt(x); i = i+2)
{
while (x%i == 0)
{
d.flush();
d.printf("%d*", i);
x = x/i;
}
}
if (x > 2)
{
d.flush();
d.printf ("%d ", x);
}
d.flush();//FLUSING THE STREAM TO FILE
d.println("\n");
}
d.close(); // CLOSING FILE
}
feel free to give detailed explanation. :D thanks ~anirudh
reading and writing to a file in java doesnt EDIT the file, but clear the old one and creates a new one, you can use many approachesfor example, to get your data, modify it, and either save it on memory in a StringBuilder or a collection or what ever and re-write it again
well i created fileOne.txt containing the following data :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
and i want to multiply all those numbers by 10, then re-write them again :
public static void main(String [] args) throws Exception{ // just for the example
// locate the file
File fileOne = new File("fileOne.txt");
FileReader inputStream = new FileReader(fileOne);
BufferedReader reader = new BufferedReader(inputStream);
// create a LinkedList to hold the data read
List<Integer> numbers = new LinkedList<Integer>();
// prepare variables to refer to the temporary objects
String line = null;
int number = 0;
// start reading
do{
// read each line
line = reader.readLine();
// check if the read data is not null, so not to use null values
if(line != null){
number = Integer.parseInt(line);
numbers.add(number*10);
}
}while(line != null);
// free resources
reader.close();
// check the new numbers before writing to file
System.out.println("NEW NUMBERS IN MEMORY : "+numbers);
// assign a printer
PrintWriter writer = new PrintWriter(fileOne);
// write down data
for(int newNumber : numbers){
writer.println(newNumber);
}
// free resources
writer.flush();
writer.close();
}
this approach is not very good when dealing with massive data
As per your problem statement, you need to take input from a file, do some processing and write back the processed data in the same file. For this, please note the below points:
You may not create a file with same name in a directory, so you must create the new file at some other location; or write the content into different file and later rename it after deleting original one.
While your file is open for reading, modifying the same file is not a good idea. you could use below approach:
Read the content of the file and store in a data structure liek Arrays, ArrayList.
Close the file.
Process the data stored in the data structure.
Open the file in write mode (over-write mode rather than append mode)
Write back the processed data into the file.
I have a text file with data. The file has information from all months. Imagine that the information for January occupy 50 lines. Than February starts and it occupies 40 more lines. Than I have March and so on... Is it possible to read only part of the file? Can I say "read from line X to line Y"? or is there a better way to accomplish this? I only want to print the data correspondent to one month not the all file. Here is my code
public static void readFile()
{
try
{
DataInputStream inputStream =
new DataInputStream(new FileInputStream("SpreadsheetDatabase2013.txt"));
while(inputStream.available() != 0)
{
System.out.println("AVAILABLE: " + inputStream.available());
System.out.println(inputStream.readUTF());
System.out.println(inputStream.readInt());
for (int i = 0; i < 40; i++)
{
System.out.println(inputStream.readUTF());
System.out.println(inputStream.readUTF());
System.out.println(inputStream.readUTF());
System.out.println(inputStream.readUTF());
System.out.println(inputStream.readUTF());
System.out.println(inputStream.readDouble());
System.out.println(inputStream.readUTF());
System.out.println(inputStream.readBoolean());
System.out.println();
}
}// end while
inputStream.close();
}// end try
catch (Exception e)
{
System.out.println("An error has occurred.");
}//end catch
}//end method
Thank you for your time.
My approach to this would be to read the entire contents of the text file and store it in a ArrayList and read only the lines for the requested month.
Example:
Use this function to read the all the lines from the file.
/**
* Read from a file specified by the filePath.
*
* #param filePath
* The path of the file.
* #return List of lines in the file.
* #throws IOException
*/
public static ArrayList<String> readFromFile(String filePath)
throws IOException {
ArrayList<String> temp = new ArrayList<String>();
File file = new File(filePath);
if (file.exists()) {
BufferedReader brin;
brin = new BufferedReader(new FileReader(filePath));
String line = brin.readLine();
while (line != null) {
if (!line.equals(""))
temp.add(line);
line = brin.readLine();
}
brin.close();
}
return temp;
}
Then read only the ones you need from ArrayList temp.
Example:
if you want to read February month's data assuming its 50 lines of data and starts from 40th line.
for(int i=40;i<90;i++)
{
System.out.println(temp.get(i));
}
Note: This is only just one way of doing this. I am not certain if there is any other way!
I would use the scanner class.
Scanner scanner = new Scanner(filename);
Use scanner.nextLine() to get each of the lines of the file. If you only want from line x to line y you can use a for loop to scan each of the lines that you don't need before going through the scanner for the lines you do need. Be careful not to hit an exception without throwing it though.
Or you can go through the scanner and for each line, add the String contents of the line to an ArrayList. Good luck.
Based on how you said your data was organized, I would suggest doing something like this
ArrayList<String> temp = new ArrayList<String>();
int read = 0;
File file = new File(filePath);
if (file.exists()) {
BufferedReader brin;
brin = new BufferedReader(new FileReader(filePath));
String line = brin.readLine();
while (line != null) {
if (!line.equals("")){
if(line.equals("March"))
read = 1;
else if(line.equals("April"))
break;
else if(read == 1)
temp.add(line);
}
line = brin.readLine();
}
brin.close();
Just tried it myself, that'll take in all the data between March and April. You can adjust them as necessary or make them variables. Thanks to ngoa for the foundation code. Credit where credit is due
If you have Java 7, you can use Files.readAllLines(Path path, Charset cs), e.g.
Path path = // Path to "SpreadsheetDatabase2013.txt"
Charset charset = // "UTF-8" or whatever charset is used
List<String> allLines = Files.readAllLines(path, charset);
List<String> relevantLines = allLines.subList(x, y);
Where x (inclusive) and y (exclusive) indicates the line numbers that are of interest, see List.subList(int fromIndex, int toIndex).
One benefit of this solution, as stated in the JavaDoc of readAllLines():
This method ensures that the file is closed when all bytes have been read or an I/O error, or other runtime exception, is thrown.
so I'm designing a text editor. For the Open/Save methods, I'm trying to use a TextArea (it doesn't have to be one, it's just my current method). Now, I have two problems right now:
1) When I load a file, it currently doesn't remove the contents currently in the text editor. For example, if I typed in "Owl", then loaded a file that contained "Rat", it would end up as "OwlRat". To solve this, I plan to use the replaceRange method (again however, it isn't absolute, any suggestions would be great!). However, I must replace all the contents of the text editor, not just selected text, and I can't figure out how to do that. Any tips?
2) Currently, when I load a file, nothing will happen unless I saved that file the same time I ran the application. So, for example, running the program, saving a file, closing the program, running the program again, and then loading the file will give nothing. I know this is because the String x doesn't carry over, but I can't think of anyway to fix it. Somebody suggested Vectors, but I don't see how they would help...
Here is the code for the Open/Save methods:
Open:
public void Open(String name){
File textFile = new File(name + ".txt.");
BufferedReader reader = null;
try
{
textArea.append(x);
reader = new BufferedReader( new FileReader( textFile));
reader.read();
}
catch ( IOException e)
{
}
finally
{
try
{
if (reader != null)
reader.close();
}
catch (IOException e)
{
}
}
}
Save:
public void Save(String name){
File textFile = new File(name + ".txt");
BufferedWriter writer = null;
try
{
writer = new BufferedWriter( new FileWriter(textFile));
writer.write(name);
x = textArea.getText();
}
catch ( IOException e)
{
}
finally
{
try
{
if ( writer != null)
writer.close( );
}
catch ( IOException e)
{
}
}
}
I had this same problem my guy friend, after much thought and research I even found a solution.
You can use the ArrayList to put all the contents of the TextArea and send as parameter by calling the save, as the writer just wrote string lines, then we use the "for" line by line to write our ArrayList in the end we will be content TextArea in txt file.
if something does not make sense, I'm sorry is google translator and I who do not speak English.
Watch the Windows Notepad, it does not always jump lines, and shows all in one line, use Wordpad ok.
private void SaveActionPerformed(java.awt.event.ActionEvent evt) {
String NameFile = Name.getText();
ArrayList< String > Text = new ArrayList< String >();
Text.add(TextArea.getText());
SaveFile(NameFile, Text);
}
public void SaveFile(String name, ArrayList< String> message) {
path = "C:\\Users\\Paulo Brito\\Desktop\\" + name + ".txt";
File file1 = new File(path);
try {
if (!file1.exists()) {
file1.createNewFile();
}
File[] files = file1.listFiles();
FileWriter fw = new FileWriter(file1, true);
BufferedWriter bw = new BufferedWriter(fw);
for (int i = 0; i < message.size(); i++) {
bw.write(message.get(i));
bw.newLine();
}
bw.close();
fw.close();
FileReader fr = new FileReader(file1);
BufferedReader br = new BufferedReader(fr);
fw = new FileWriter(file1, true);
bw = new BufferedWriter(fw);
while (br.ready()) {
String line = br.readLine();
System.out.println(line);
bw.write(line);
bw.newLine();
}
br.close();
fr.close();
} catch (IOException ex) {
ex.printStackTrace();
JOptionPane.showMessageDialog(null, "Error in" + ex);
}
There's a lot going on here...
What is 'x' (hint: it's not anything from the file!), and why are you appending it to the text area?
BufferedReader.read() returns one character, which is probably not what you're expecting. Try looping across readline().
Follow Dave Newton's advice to handle your exceptions and provide better names for your variables.
The text file will persist across multiple invocation of your program, so the lack of data has nothing to do with that.
Good luck.
Use textArea.setText(TEXT); rather than append; append means to add on to, so when you append text to a TextArea, you add that text to it. setText on the other hand will set the text, replacing the old text with the new one (which is what you want).
As far as why it's failing to read, you are not reading correctly. First of all, .read() just reads a single character (not what you want). Second, you don't appear to do anything with the returned results. Go somewhere (like here) to find out how to read the file properly, then take the returned string and do textArea.setText(readString);.
And like the others said, use e.printStackTrace(); in all of your catch blocks to make the error actually show up in your console.