Cannot read first line of a file - java

I want to read the content of /etc/passwd file and get some data:
public void getLinuxUsers()
{
try
{
// !!! firstl line of the file is not read
BufferedReader in = new BufferedReader(new FileReader("/etc/passwd"));
String str;
str = in.readLine();
while ((str = in.readLine()) != null)
{
String[] ar = str.split(":");
String username = ar[0];
String userID = ar[2];
String groupID = ar[3];
String userComment = ar[4];
String homedir = ar[5];
System.out.println("Usrname " + username +
" user ID " + userID);
}
in.close();
}
catch (IOException e)
{
System.out.println("File Read Error");
}
}
I noticed two problems:
first line of the file is not read with root account information. I starts this way:
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
And how I can modify the code to use Java 8 NIO? I want to check first the existing of the file and then to proceed with reading the content.

The problem is that the first readLine() is outside the loop where the string is being processed, you should delete this:
str = in.readLine();
… Because in the next line (the one with the while) you're reassigning the str variable, that's why the first line is lost: the loop's body starts processing from the second line. Finally, to use Java nio, do something like this:
if (new File("/etc/passwd").exists()) {
Path path = Paths.get("/etc/passwd");
List<String> lines = Files.readAllLines(path, Charset.defaultCharset());
for (String line : lines) {
// loop body, same as yours
}
}

with nio:
Path filePath = Paths.get("/etc/passwd");
List<String> fileLines = Files.readAllLines(filePath);
Note that Files.readAllLines without 2nd parameter treats the file encoding as UTF-8, instead of system encoding (property "file.encoding")

Related

How to delete a whole line from a text file from the input entered

i'm trying to delete a whole line after entering the Association Name but isnt working. it keeps showing the error, could not delete original input file can you please help me with this?
String inputFileName = "Association Record.txt";
String outputFileName = "Association Report.txt";
String lineToRemove = JOptionPane.showInputDialog("Enter Association Name to Delete the Record");
try{
File inputFile = new File(inputFileName);
File outputFile = new File(outputFileName);
try{
BufferedReader r1= new BufferedReader(new FileReader(inputFile));
BufferedWriter w1 = new BufferedWriter(new FileWriter(outputFile));
String line = null;
while ((line = r1.readLine()) != null) {
if (!line.equals(lineToRemove)) {
w1.write(line);
w1.newLine();
}
}//end while
}
catch (IOException ex) {ex.printStackTrace();}
if (inputFile.delete()) {
if (!outputFile.renameTo(inputFile))
throw new IOException("Could not rename " + outputFileName + " to " + inputFileName);
}
else {throw new IOException("Could not delete original input file " + inputFileName);}
}
catch (Exception e){System.out.println(e.getMessage());}
}
example of one of the line in the file:
COMPUTER,pc,08/07/2018,brandon
*COMPUTER is the association name
If the word COMPUTER is the association word and the line you want to delete starts with the word COMPUTER then the String#equals() method is not the one to use in your IF statement. You would want to use the String#startsWith() method, for example:
boolean ignoreLetterCase = true; // ignore Letter Case by default
String lineToRemove = "computer";
String criteria = ignoreLetterCase ? lineToRemove.toLowerCase() : lineToRemove;
while ((line = r1.readLine()) != null) {
String procString = ignoreLetterCase ? line.toLowerCase : line;
if (!procString.startsWith(criteria)) {
w1.write(line);
w1.newLine();
}
}
The file data line COMPUTER,pc,08/07/2018,brandon will not be written to the destination file.
If however you want to ignore a file line that contains the associative word COMPUTER anywhere within a retrieved data line then you will want to utilize the String#contains() method, for example:
boolean ignoreLetterCase = true; // ignore Letter Case by default
String lineToRemove = "computer";
String criteria = ignoreLetterCase ? lineToRemove.toLowerCase() : lineToRemove;
while ((line = r1.readLine()) != null) {
String procString = ignoreLetterCase ? line.toLowerCase : line;
if (!procString.contains(criteria)) {
w1.write(line);
w1.newLine();
}
}
The file data line COMPUTER,pc,08/07/2018,brandon will not be written to the destination file. However a file data line which contains PRINTER,pc-computer,09/27/2018,joseph will also not be written to the destination file since the word computer is contained within the original file line.
I highly doubt this will ever be the case with your data file but if a retrieved file data line only contains the associative word (COMPUTER) then by all means you would want to use the String#equals() or String#equalsIgnoreCase() method.
If you want to ignore original file lines where the associative word is only pertinent within a specific data column of any retrieved file data line then you would want to parse (split) each line into a columnar data array and do your comparisons on the desired column (array elemental index). For example:
// Delete all file lines where the NAME column equals
// the name 'brandon' or 'Brandon' or 'BRANDON'.
boolean ignoreLetterCase = true; // ignore Letter Case by default
int deleteIfInColumn = 3;
String nameToDelete = "Brandon";
String criteria = ignoreLetterCase ? nameToDelete .toLowerCase() : nameToDelete;
while ((line = r1.readLine()) != null) {
String procString = ignoreLetterCase ? line.toLowerCase : line;
String[] columnData = procString.split(",");
if (columnData[deleteIfInColumn].equals(criteria)) {
continue; // Skip to next file line
}
w1.write(line);
w1.newLine();
}

How to replace an string after a specific line in a file using java

I have a situation similar where I need to change a line in a batch file if similar string not found.
Suppose I have a code like below in batch(I know it is not correct code as it a dummy only)
public static void main(String[] args) {
if (user == '1234') {
ENV DEV
set DB myDBDEV
set Excel myExecelDEV
set API MyAPIURLDEV
} elseif (user == '5678') {
ENV UAT
set DB myDBUAT
set Excel myExecelUAT
set API MyAPIURLUAT
}
}
}
Now I want java to read above file, find ENV as DEV and change the value like myDBDEV, myExecelDEV, MyAPIURLDEV etc.
I am able to find the line number by using below code
FileInputStream fis = new FileInputStream("C:\\Users\\owner\\Desktop\\batch\\MYbatch-env.csh");
InputStreamReader input = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(input);
String data;
String result = new String();
int i=0;
while ((data = br.readLine()) != null) {
i++;
if(data.contains("ENV DEV")) {
System.out.println("line number -> "+i);
}
result = result.concat(data + "\n");
}
I have tried below code but that was not return line number so I use above approach
Finding line number of a word in a text file using java
I also tried below approach but it seems not working
How to replace an string after a specific line in a file using java
Now problem statement is replaceAll function will remove all key but I want to remove the next string of key means value. and it is a text as string not a hashmap kind thing,
In if block if DB string is myDBDEV2 then I want to change the values to myDBDEV
Example:
If below string found
ENV DEV
Then below value should check value of key DB and replace if not found required value
set DB myDBDEV
set Excel myExecelDEV
set API MyAPIURLDEV
And main thing is code should make change in if block only, else if variables should be affected as an file example I have shown in above URL.
Below solution work for me
public static void main(String[] args) throws Exception {
String filepath= "C:\\Users\\Demo\\Desktop\\batch\\Demo.sh";
FileInputStream fis = new FileInputStream(filepath);
InputStreamReader input = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(input);
String data;
String result = new String();
int lineNumber=0;
int i=0;
while ((data = br.readLine()) != null) {
i++;
if(data.contains("My String data")) {
System.out.println("line number -> "+i);
lineNumber=i;
break;
}
result = result.concat(data + "\n");
}
br.close();
lineNumber=lineNumber+1;
System.out.println(lineNumber);
String Mystring =" Mystring";
String Mystringline = Files.readAllLines(Paths.get(filepath)).get(lineNumber-1); // get method count from 0 so -1
System.out.println("Line data ->> "+Mystringline);
if(!Mystringline.equalsIgnoreCase(Mystring)) {
setVariable(lineNumber, Mystring, filepath);
}else {
System.out.println("Mystring is already pointing to correct DB");
}
System.out.println("Succesfully Change");
}
public static void setVariable(int lineNumber, String data, String filepath) throws IOException {
Path path = Paths.get(filepath);
List<String> lines = Files.readAllLines(path, StandardCharsets.UTF_8);
lines.set(lineNumber - 1, data);
Files.write(path, lines, StandardCharsets.UTF_8);
}
}

How to remove a particular string in a text file using java?

My input file has numerous records and for sample, let us say it has (here line numbers are just for your reference)
1. end
2. endline
3. endofstory
I expect my output as:
1.
2. endline
3. endofstory
But when I use this code:
import java.io.*;
public class DeleteTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
File file = new File("D:/mypath/file.txt");
File temp = File.createTempFile("file1", ".txt", file.getParentFile());
String charset = "UTF-8";
String delete = "end";
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), charset));
PrintWriter writer = new PrintWriter(new OutputStreamWriter(new FileOutputStream(temp), charset));
for (String line; (line = reader.readLine()) != null;) {
line = line.replace(delete, "");
writer.println(line);
}
reader.close();
writer.close();
}
catch (Exception e) {
System.out.println("Something went Wrong");
}
}
}
I get my output as:
1.
2. line
3. ofstory
Can you guys help me out with what I expect as output?
First, you'll need to replace the line with the new string List item not an empty string. You can do that using line = line.replace(delete, "List item"); but since you want to replace end only when it is the only string on a line you'll have to use something like this:
line = line.replaceAll("^"+delete+"$", "List item");
Based on your edits it seems that you indeed what to replace the line that contains end with an empty string. You can do that using something like this:
line = line.replaceAll("^"+delete+"$", "");
Here, the first parameter of replaceAll is a regular expression, ^ means the start of the string and $ the end. This will replace end only if it is the only thing on that line.
You can also check if the current line is the line you want to delete and just write an empty line to the file.
Eg:
if(line.equals(delete)){
writer.println();
}else{
writer.println(line);
}
And to do this process for multiple strings you can use something like this:
Set<String> toDelete = new HashSet<>();
toDelete.add("end");
toDelete.add("something");
toDelete.add("another thing");
if(toDelete.contains(line)){
writer.println();
}else{
writer.println(line);
}
Here I'm using a set of strings I want to delete and then check if the current line is one of those strings.

Removing commas from a text file

Im trying to remove all commas from my text file, where am i going wrong? I think its to do with the replaceAll field, ive done research into it, but cannot find any answers. I also need there to be a new line after a ";" as well as removing the commas. Thankyou in advance
`public static void open(){
// The name of the file to open.
String fileName = "Test.txt";
// 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) {
line.replaceAll(",","\\.");
System.out.println(line);
}
// Always close files.
bufferedReader.close();
}
catch(FileNotFoundException ex) {
System.out.println(
"Unable to open file '" +
fileName + "'");
}
catch(IOException ex) {
System.out.println(
"Error reading file '"
+ fileName + "'");
}
}`
Strings are immutable in Java, so System.out.println(line.replaceAll(",","\\.")) is what you want. You want to print the returned value.
line.replaceAll(",","\\.");
Java Strings are immutable - this does not alter line but returns a new String with the desired replacement applied. Try assigning that to a variable instead:
String s = line.replaceAll(",","\\.");
or printing it directly:
System.out.println(line.replaceAll(",","\\."));
You may try like this:
String s = line.replaceAll(",","\\.");
Note Java strings are immutable
or you may choose to directly print it as:
System.out.println(line.replaceAll(",","\\."));
In you code when you say:
line.replaceAll(",","\\.");
then there is no change in the line and it returns a new String.
changing line.replaceAll(",","\\."); to line = line.replaceAll(",","\\."); should fix your problem.
As for putting newlines after ";" use line = line.replaceAll(";",";\n");
Try to load file with :
public static String readAllText(String filename) throws Exception {
StringBuilder sb = new StringBuilder();
Files.lines(Paths.get(filename)).forEach(sb::append);
return sb.toString();
}
then change what do you want.
String file = readAllText("myfile.txt");
file = file.replace(",","\\.);

Get the offset of previous line in a file

I'm extracting data from a file line by line into a database and i can't figure out a proper way to flag lines that I've already read into my database.
I have the following code that I use to iterate through the file lines and I attempt to verify
that the line has my flag or else I try to append the flag to the file line
List<String> fileLines = new ArrayList<String>();
File logFile = new File("C:\\MyStuff\\SyslogCatchAllCopy.txt");
try {
RandomAccessFile raf = new RandomAccessFile(logFile, "rw");
String line = "";
String doneReadingFlag = "##";
Scanner fileScanner = new Scanner(logFile);
while ((line = raf.readLine()) != null && !line.contains(doneReading)) {
Scanner s = new Scanner(line);
String temp = "";
if (!s.hasNext(doneReadingFlag)) {
fileLines.add(line);
raf.write(doneReadingFlag.getBytes(), (int) raf.getFilePointer(),
doneReadingFlag.getBytes().length);
} else {
System.err.println("Allready Red");
}
}
} catch (FileNotFoundException e) {
System.out.println("File not found" + e);
} catch (IOException e) {
System.out.println("Exception while reading the file ");
}
// return fileLines;
// MoreProccessing(fileLines);
This code appends the flag to the next line and it overwrites the characters in that position
Any Help ?
When you write to a file, it doesn't insert do you should expect it to replace the characters.
You need to reserve space in the file for information you want to change or you can add information to another file.
Or instead of marking each file, you can store somewhere the lines number (or better the character position) you have read up to.
If you are not restarting your process you can have process read the file as it is appended (meaning you might not need to store where you are up to anywhere)
#Peter Lawrey I did as you said and it worked for me like that:
as follows:
ArrayList<String> fileLines=new ArrayList<String>();
File logFile=new File("C:\\MyStuff\\MyFile.txt");
RandomAccessFile raf = new RandomAccessFile(logFile, "rw");
String line="";
String doneReadingFlag="#";
long oldOffset=raf.getFilePointer();
long newOffset=oldOffset;
while ((line=raf.readLine())!=null)
{
newOffset=raf.getFilePointer();
if(!line.contains(doneReadingFlag))
{
fileLines.add(line);
raf.seek((long)oldOffset);
raf.writeChars(doneReadingFlag);
raf.seek(newOffset);
System.out.println("Line added and flaged");
}
else
{
System.err.println("Already Red");
}
oldOffset=newOffset;
}

Categories