Why does this keep overwriting? - java

For some reason my program is overwriting the file and not adding to it.
This is the method that I am using to create the file and name it:
public void filenameMethod() throws IOException{
System.out.println("Input the name of the file");
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
filename = br.readLine();
raf = new RandomAccessFile(filename, "rw");
}
I'm using this method to take in the input from the user, it sets the value to a variable that are then written to a file:
public void inputMethod() throws IOException{
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
System.out.println("Input Carname, ID, Existing Mileage, Gas Cost, Number of Days, Rate, Total Charge, Discount, Tax, Net Charge and Return Milage");
String tokenString;
tokenString = br.readLine();
StringTokenizer st;
st = new StringTokenizer(tokenString);
carName = st.nextToken();
id = Integer.parseInt(st.nextToken());
existingMileage = Integer.parseInt(st.nextToken());
gasCost = Integer.parseInt(st.nextToken());
ndays = Integer.parseInt(st.nextToken());
rate = Integer.parseInt(st.nextToken());
totalCharge = Integer.parseInt(st.nextToken());
discount = Integer.parseInt(st.nextToken());
tax = Integer.parseInt(st.nextToken());
netCharge = Integer.parseInt(st.nextToken());
returnMileage = Integer.parseInt(st.nextToken());
}
I am then using this method to write them to a file:
public void fileWriterMethod() throws IOException{
raf.writeInt(id);
raf.writeInt(existingMileage);
raf.writeInt(gasCost);
raf.writeInt(ndays);
raf.writeInt(rate);
raf.writeInt(totalCharge);
raf.writeInt(discount);
raf.writeInt(tax);
raf.writeInt(netCharge);
raf.writeInt(returnMileage);
raf.writeBytes(carName + "\r\n");
//Closing the stream
raf.close();
}
I don't understand why this is happening, can anyone help me?

seek to the end of your file before you start writing, for example:
File f = new File(filename);
long fileLength = f.length();
RandomAccessFile raf = new RandomAccessFile(filename, "rw");
raf.seek(fileLength);
raf.writeInt(id);
...
Relevant javadoc.

By default RandomAccessFile starts writing at start of file and will overwrite existing data. To write to end of file, you need to use skip to the end as follows:
raf.skipBytes( (int)raf.length() );

When you open RandomAccessFile its pointer points to the beginning of the file. If you want to move to specific position you have to use method seek(). In your case you have to move to the end of file, i.e. seek(fileLength):
File f = new File(filename);
long fileLength = f.length();
RandomAccessFile raf = new RandomAccessFile(f, "rw");
raf.seek(fileLength);
// now write your bytes

If you want to append to the file, you need to seek(long) to the end. Something like,
raf.seek(raf.length());
From the linked Javadoc,
Sets the file-pointer offset, measured from the beginning of this file, at which the next read or write occurs. The offset may be set beyond the end of the file. Setting the offset beyond the end of the file does not change the file length. The file length will change only by writing after the offset has been set beyond the end of the file.

You'll need to set the file pointer to the end of the file before you start writing, it defaults to the beginning.
raf.seek(raf.length());
placed before any of the write operations should do the trick.

Related

Replace Timestamp in Written Text File

I need to read a file and write it in a new file, the file that I read has it own time stamp, but in the written file I need to replace it with the current time eg( 2020-09-20 19:30 change it to 2020-09-30 01:30) I have been able to read and write it using the following code, but I am struggling with the change time stamp part
FileInputStream inputRead = null;
FileOutputStream outWrite = null;
try{
File infile =new File("test.txt");
File outfile =new File("test_log.txt");
inputRead = new FileInputStream(infile);
outWrite = new FileOutputStream(outfile);
byte[] buffer = new byte[2048];
int length;
while ((length = inputRead.read(buffer)) > 0){
System.getProperty("line.separator");
outWrite.write(buffer, 0, length);
}
inputRead.close();
outWrite.close();
}
catch(IOException ioe){
ioe.printStackTrace();
}
}
Sorry forgot to mention the Line Read is as follows " 20-09-2020 19:30 (Some Parameter) " to "(current date) + (Some Parameter)
Try this
File infile = new File("test.txt");
File outfile = new File("test_log.txt");
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
try (
BufferedReader inputRead = new BufferedReader(new InputStreamReader(new FileInputStream(infile)));
BufferedWriter outWrite = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outfile)))
) {
String line;
while ((line = inputRead.readLine()) != null) {
outWrite.write(System.lineSeparator());
String modifiedString = line.replaceAll("\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}", dateTimeFormatter.format(LocalDateTime.now()));
outWrite.write(modifiedString);
}
}
Expanding my answer a bit for clarity.
I've added try-with-resources, you don't need to close the streams manually which should otherwise be done in a finally (if it crashes they are left open).
I've added readers which is a higher level api on top of the stream. for convenience.
I've added search and replace on the string using regex that matches your example string. In my example above i'm using strings which could probably be optimized if needed.
String nextTimeStamp = "2020-09-30 01:30";
Path infile = Paths.get("test.txt");
Path outfile = Paths.get("test_log.txt");
try (Stream<String> lines = Files.lines(infile, Charset.defaultCharset());
PrintWriter out = new PrintWriter(outfile.toFile()) {
lines.map(line -> line.replaceAll("\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}", nextTimeStamp)
.forEach(line -> out.println(line));
}
(For a fixed Charset add an extra parameter with this Charset to PrintWriter too.
Java String is for text, byte[] for binary data. And on String one can do replace and other text operations.
line.replaceAll uses a regular expression to match. If you have the exact string to be replaced, you can use line.replace.
The syntax of what is called try-with-resources accepts AutoCloseable's inside try (...) and will ensure the objects are closed even on exception or return/break.

How to efficiently read and write to files using minimal RAM

My aim is to read from a large file, process 2 lines at a time, and write the result to a new file(s). These files can get very large, from 1GB to 150GB in size, so I'd like to attempt to do this processing using the least RAM possible
The processing is very simple: The lines split by a tab delimited, certain elements are selected, and the new String is written to the new files.
So far I have attempted using BufferedReader to read the File and PrintWriter to output the lines to a file:
while((line1 = br.readLine()) != null){
if(!line1.startsWith("#")){
line2 = br.readLine();
recordCount++;
one.println(String.format("%s\n%s\n+\n%s",line1.split("\t")[0] + ".1", line1.split("\t")[9], line1.split("\t")[10]));
two.println(String.format("%s\n%s\n+\n%s",line2.split("\t")[0] + ".2", line2.split("\t")[9], line2.split("\t")[10]));
}
}
I have also attempted to uses Java8 Streams to read and write from the file:
stream.forEach(line -> {
if(!line.startsWith("#")) {
try {
if (counter.getAndIncrement() % 2 == 0)
Files.write(path1, String.format("%s\n%s\n+\n%s", line.split("\t")[0] + ".1", line.split("\t")[9], line.split("\t")[10]).getBytes(), StandardOpenOption.APPEND);
else
Files.write(path2, String.format("%s\n%s\n+\n%s", line.split("\t")[0] + ".2", line.split("\t")[9], line.split("\t")[10]).getBytes(), StandardOpenOption.APPEND);
}catch(IOException ioe){
}
}
});
Finally, I have tried to use an InputStream and scanner to read the file and PrintWriter to output the lines:
inputStream = new FileInputStream(inputFile);
sc = new Scanner(inputStream, "UTF-8");
String line1, line2;
PrintWriter one = new PrintWriter(new FileOutputStream(dotOne));
PrintWriter two = new PrintWriter(new FileOutputStream(dotTwo));
while(sc.hasNextLine()){
line1 = sc.nextLine();
if(!line1.startsWith("#")) {
line2 = sc.nextLine();
one.println(String.format("%s\n%s\n+\n%s",line1.split("\t")[0] + ".1", line1.split("\t")[9], line1.split("\t")[10]));
two.println(String.format("%s\n%s\n+\n%s",line2.split("\t")[0] + ".2", line2.split("\t")[9], line2.split("\t")[10]));
}
}
The issue that I'm facing is that the program seems to be storing either the data to write, or the input file data into RAM.
All of the above methods do work, but use more RAM than I'd like them to.
Thanks in advance,
Sam
What you did not try is a MemoryMappedByteBuffer. The FileChannel.map might be usable for your purpose, not allocating in java memory.
Functioning code with a self made byte buffer would be:
try (FileInputStream fis = new FileInputStream(source);
FileChannel fic = fis.getChannel();
FileOutputStream fos = new FileOutputStream(target);
FileChannel foc = fos.getChannel()) {
ByteBuffer buffer = ByteBuffer.allocate(1024);
while (true) {
int nread = fic.read(buffer);
if (nread == -1) {}
break;
}
buffer.flip();
foc.write(buffer);
buffer.clear();
}
}
Using fic.map to consecutively map regions into OS memory seems easy, but
such more complex code I would need to test first.
When creating PrintWriter set autoFlush to true:
new PrintWriter(new FileOutputStream(dotOne), true)
This way the buffered data will be flushed with every println.

How to Access string in file by position in Java

I have a text file with the following contents:
one
two
three
four
I want to access the string "three" by its position in the text file in Java.I found the substring concept on google but unable to use it.
so far I am able to read the file contents:
import java.io.*;
class FileRead
{
public static void main(String args[])
{
try{
// Open the file that is the first
// command line parameter
FileInputStream fstream = new FileInputStream("textfile.txt");
// 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);
}
//Close the input stream
in.close();
}catch (Exception e){//Catch exception if any
System.err.println("Error: " + e.getMessage());
}
}
}
I want to apply the substring concept to the file.It asks for the position and displays the string.
String Str = new String("Welcome to Tutorialspoint.com");
System.out.println(Str.substring(10, 15) );
If you know the byte offsets within the file that you are interested in then it's straightforward:
RandomAccessFile raFile = new RandomAccessFile("textfile.txt", "r");
raFile.seek(startOffset);
byte[] bytes = new byte[length];
raFile.readFully(bytes);
raFile.close();
String str = new String(bytes, "Windows-1252"); // or whatever encoding
But for this to work you have to use byte offsets, not character offsets - if the file is encoded in a variable-width encoding such as UTF-8 then there's no way to seek directly to the nth character, you have to start at the top of the file and read and discard the first n-1 characters.
look for \r\n (linebreaks) in your text file. This way you should be able to count the rows containing your string.
your file in reality looks like this
one\r\n
two\r\n
three\r\n
four\r\n
You seem to be looking for this. The code I posted there works on the byte level, so it may not work for you. Another option is to use the BufferedReader and just read a single character in a loop like this:
String getString(String fileName, int start, int end) throws IOException {
int len = end - start;
if (len <= 0) {
throw new IllegalArgumentException("Length of string to output is zero or negative.");
}
char[] buffer = new char[len];
BufferedReader reader = new BufferedReader(new FileReader(fileName));
for (int i = 0; i < start; i++) {
reader.read(); // Ignore the result
}
reader.read(buffer, 0, len);
return new String(buffer);
}

Read a definite number of lines in a text file, using java

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.

Read file by keeping line track in java

I have servlet to read log file my jsp call servlet at some interval.I want to add functionality in my servlet so that it read file from line next to last line from previous read.
I have following code but its not working
File file = new File("D:\\graph\\temp.log");
FileReader fr = new FileReader(file);
LineNumberReader lnr = new LineNumberReader(fr);\
lnr.setLineNumber(count) // count is the variable keeping track of number of line
previously read.
Is it need some extra code ? or is there any other alernative to do the same ?
From the documentation:
Note however, that setLineNumber(int) does not actually change the
current position in the stream; it only changes the value that will be
returned by getLineNumber().
Sounds to me like you'll have to start from the beginning and call readLine in a loop until getLineNumber() is greater than count.
Something like this:
File file = new File("D:\\graph\\temp.log");
FileReader fr = new FileReader(file);
LineNumberReader lineReader = new LineNumberReader(fr);
// skip the lines you don't need
while (lineReader.getLineNumber() < count) {
lineReader.readLine();
}
// begin processing input here
Have you looked at RandomAccessFile. If you keep the count of bytes read. Than followin code will help you.
RandomAccessFile raf = new RandomAccessFile(fileName,"r");
byte[] cBuf = new byte[1024];
long count = offset;
raf.seek(offset);
long lineCOunt=0l;
while(true){
int lineCOunt =raf.read(cBuf);
count +=lineCOunt;
if(lineCOunt<1024){
System.out.println((new String(cBuf)).substring(0,i));
break;
}
System.out.println(new String(cBuf));

Categories

Resources